From 8c7f4064758d2e3dffc6317d59c36933eb877067 Mon Sep 17 00:00:00 2001 From: Lionel Untereiner Date: Fri, 8 Jan 2016 09:48:26 +0100 Subject: [PATCH 001/402] first version of 2D CPH CMAP --- cgogn/core/cph/ihcmap2.h | 398 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 398 insertions(+) create mode 100644 cgogn/core/cph/ihcmap2.h diff --git a/cgogn/core/cph/ihcmap2.h b/cgogn/core/cph/ihcmap2.h new file mode 100644 index 00000000..97f6fcbe --- /dev/null +++ b/cgogn/core/cph/ihcmap2.h @@ -0,0 +1,398 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef CORE_CPH_IHCMAP2_H_ +#define CORE_CPH_IHCMAP2_H_ + +#include +#include + +namespace cgogn +{ + +template +class IHCMap2_T : protected CMap2_T +{ +public: + + typedef CMap2_T Inherit; + typedef IHCMap2_T Self; + + friend typename Self::Inherit; + friend typename Inherit::Inherit; + + template friend class cgogn::DartMarkerT; + + static const Orbit DART = Orbit::DART; + static const Orbit VERTEX = Orbit::PHI21; + static const Orbit EDGE = Orbit::PHI2; + static const Orbit FACE = Orbit::PHI1; + static const Orbit VOLUME = Orbit::PHI1_PHI2; + + typedef Cell Vertex; + typedef Cell Edge; + typedef Cell Face; + typedef Cell Volume; + + template + using AttributeHandler = typename AttributeHandlerCPH; + template + using DartAttributeHandler = AttributeHandlerCPH; + template + using VertexAttributeHandler = AttributeHandlerCPH; + template + using EdgeAttributeHandler = AttributeHandlerCPH; + template + using FaceAttributeHandler = AttributeHandlerCPH; + template + using VolumeAttributeHandler = AttributeHandlerCPH; + + using DartMarker = typename Inherit::DartMarker; + using DartMarkerStore = typename Inherit::DartMarkerStore; + +private: + unsigned int current_level_; + unsigned int maximum_level_; + unsigned int id_count_; + + DartAttribute dart_level_ ; + DartAttribute edge_id_ ; + +public: + IHCMap2_T() : Inherit() + { + init(); + } + + ~IHCMap2_T() override + {} + + IHCMap2_T(Self const&) = delete; + IHCMap2_T(Self &&) = delete; + Self& operator=(Self const&) = delete; + Self& operator=(Self &&) = delete; + + + inline void init_implicit_properties() + { + //initEdgeId() ; + + //init each edge Id at 0 + for(Dart d : Inherit) + { + set_edge_id(d, 0); + } + + // for(unsigned int orbit = 0u; orbit < Orbit::NB_ORBITS; ++orbit) + // { + // if(m_nextLevelCell[orbit] != NULL) + // { + // AttributeContainer& cellCont = m_attribs[orbit] ; + // for(unsigned int i = cellCont.begin(); i < cellCont.end(); cellCont.next(i)) + // m_nextLevelCell[orbit]->operator[](i) = EMBNULL ; + // } + // } + } + + /******************************************************************************* + * Basic topological operations + *******************************************************************************/ + + inline Dart phi1(Dart d) const + { + cgogn_debug_assert(get_dart_level(d) <= get_current_level(), "Access to a dart introduced after current level") ; + + bool finished = false ; + unsigned int edge_id = get_edge_id(d) ; + Dart it = d ; + do + { + it = Inherit::phi1(it) ; + if(get_dart_level(it) <= get_current_level()) + finished = true ; + else + { + while(get_edge_id(it) != edge_id) + it = Inherit::phi1(Inherit::phi2(it)) ; + } + } while(!finished) ; + return it ; + } + + inline Dart phi_1(Dart d) const + { + cgogn_debug_assert(get_dart_level(d) <= get_current_level(), "Access to a dart introduced after current level") ; + + bool finished = false ; + Dart it = Inherit::phi_1(d) ; + unsigned int edge_id = get_edge_id(d) ; + do + { + if(get_dart_level(it) <= get_current_level()) + finished = true ; + else + { + it = Inherit::phi_1(it) ; + while(get_edge_id(it) != edge_id) + it = Inherit::phi_1(Inherit::phi2(it)) ; + } + } while(!finished) ; + return it ; + } + + /** + * \brief phi2 + * @param d + * @return phi2(d) + */ + inline Dart phi2(Dart d) const + { + cgogn_debug_assert(get_dart_level(d) <= get_current_level(), "Access to a dart introduced after current level") ; + + if(Inherit::phi2(d) == d) + return d; + return Inherit::phi2(Inherit::phi_1(phi1(d))); + } + +protected: + + /** + * \brief add a Dart in the map + * @return the new Dart + */ + inline Dart add_dart() + { + Dart d = Inherit::add_dart(); + set_dart_level(d, get_current_level()); + if(get_current_level() > get_maximum_level()) // update max level + set_maximum_level(get_current_level()); // if needed + + return d ; + } + +protected: + + /******************************************************************************* + * Orbits traversal + *******************************************************************************/ + + template + inline void foreach_dart_of_vertex(Dart d, const FUNC& f) const + { + Dart it = d; + do + { + f(it); + it = phi2(phi_1(it)); + } while (it != d); + } + + template + void foreach_dart_of_volume(Dart d, const FUNC& f) const + { + DartMarkerStore marker(*this); + + std::vector* visited_faces = cgogn::get_dart_buffers()->get_buffer(); + visited_faces->push_back(d); // Start with the face of d + + // For every face added to the list + for(unsigned int i = 0; i < visited_faces->size(); ++i) + { + if (!marker.is_marked((*visited_faces)[i])) // Face has not been visited yet + { + // mark visited darts (current face) + // and add non visited adjacent faces to the list of face + Dart e = (*visited_faces)[i] ; + do + { + f(e); // apply the function to the darts of the face + marker.mark(e); // Mark + Dart adj = phi2(e); // Get adjacent face + if (!marker.is_marked(adj)) + visited_faces->push_back(adj); // Add it + e = phi1(e); + } while (e != (*visited_faces)[i]); + } + } + + cgogn::get_dart_buffers()->release_buffer(visited_faces); + } + + template + inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const + { + switch (ORBIT) + { + case Orbit::DART: Inherit::foreach_dart_of_orbit(c, f); break; + case Orbit::PHI1: Inherit::foreach_dart_of_orbit(c, f); break; + case Orbit::PHI2: f(c.dart); f(phi2(c.dart)); break; + case Orbit::PHI1_PHI2: foreach_dart_of_volume(c, f); break; + case Orbit::PHI21: foreach_dart_of_vertex(c, f); break; + case Orbit::PHI2_PHI3: + case Orbit::PHI1_PHI3: + case Orbit::PHI21_PHI31: + default: cgogn_assert_not_reached("Cells of this dimension are not handled"); break; + } + } + +public: + /*************************************************** + * LEVELS MANAGEMENT * + ***************************************************/ + + inline unsigned int get_current_level() const + { + return current_level_ ; + } + + inline void set_current_level(unsigned int l) + { + current_level_ = l ; + } + + inline void inc_current_level() + { + cgogn_debug_assert(get_current_level() < get_maximum_level(), "incCurrentLevel : already at maximum resolution level"); + ++current_level_ ; + } + + inline void dec_current_level() + { + cgogn_debug_assert(get_current_level() > 0u, "decCurrentLevel : already at minimum resolution level"); + --current_level_ ; + } + + inline unsigned int get_maximum_level() const + { + return maximum_level_ ; + } + + inline void set_maximum_level(unsigned int l) + { + maximum_level_ = l; + } + + inline unsigned int get_dart_level(Dart d) const + { + return dart_level_[d] ; + } + + inline void set_dart_level(Dart d, unsigned int l) + { + dart_level_[d] = l ; + } + + /*************************************************** + * EDGE ID MANAGEMENT * + ***************************************************/ + + /** + * Give a new unique id to all the edges of the map + */ + inline void init_edge_ids() + { + id_count_ = 0; + DartMarker marker(*this); + + for (Dart d : Inherit) + { + if(!marker.is_marked(d)) + { + marker.mark_orbit(Edge(d)) ; + edge_id_[d] = id_count_ ; + edge_id_[Inherit::phi2(d)] = id_count_++ ; + } + } + } + + /** + * Return the next available edge id + */ + inline unsigned int get_new_edge_id() const + { + return id_count_++ ; + } + + inline unsigned int get_edge_id(Dart d) const + { + return edge_id_[d] ; + } + + inline void set_edge_id(Dart d, unsigned int i) + { + edge_id_[d] = i ; + } + + inline unsigned int get_tri_refinement_edge_id(Dart d) const + { + unsigned int d_id = get_edge_id(phi_1(d)); + unsigned int e_id = get_edge_id(phi1(d)); + + unsigned int id = d_id + e_id; + + if(id == 0u) + return 1u; + else if(id == 1u) + return 2u; + else if(id == 2u) + { + if(d_id == e_id) + return 0u; + else + return 1u; + } + + //else if(id == 3) + return 0u; + } + + inline unsigned int get_quad_refinement_edge_id(Dart d) const + { + unsigned int e_id = get_edge_id(phi1(d)); + + if(e_id == 0u) + return 1u; + + //else if(e_id == 1) + return 0u; + } + +}; + +template +struct IHCMap2TopoTraits +{ + static const int PRIM_SIZE = 1; + typedef IHCMap2_T> CONCRETE; +}; + +struct IHCMap2DataTraits +{ + static const unsigned int CHUNK_SIZE = 4096; +}; + +using IHCMap2 = IHCMap2_T>; + +} // namespace cgogn + +#endif // CORE_CPH_IHCMAP2_H_ \ No newline at end of file From e66cde2c2a79c9b239627b9b7f431411c72cc29f Mon Sep 17 00:00:00 2001 From: Lionel Untereiner Date: Fri, 8 Jan 2016 11:39:14 +0100 Subject: [PATCH 002/402] adding foreach_cell with level parameter --- cgogn/core/cph/ihcmap2.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/cgogn/core/cph/ihcmap2.h b/cgogn/core/cph/ihcmap2.h index 97f6fcbe..5614242c 100644 --- a/cgogn/core/cph/ihcmap2.h +++ b/cgogn/core/cph/ihcmap2.h @@ -78,6 +78,9 @@ class IHCMap2_T : protected CMap2_T DartAttribute dart_level_ ; DartAttribute edge_id_ ; + ChunkArray* next_level_cell_[NB_ORBITS]; + + public: IHCMap2_T() : Inherit() { @@ -174,6 +177,18 @@ class IHCMap2_T : protected CMap2_T return Inherit::phi2(Inherit::phi_1(phi1(d))); } + template + inline void foreach_cell(const FUNC& f, unsigned int level) + { + + } + + template + inline void foreach_cell(const FUNC& f) + { + + } + protected: /** From c420453b682229dc80490cc88ba835792ac48129 Mon Sep 17 00:00:00 2001 From: Lionel Untereiner Date: Fri, 8 Jan 2016 11:39:45 +0100 Subject: [PATCH 003/402] first version of attribute_handler cph specific --- cgogn/core/cph/attribute_handler_cph.h | 147 +++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 cgogn/core/cph/attribute_handler_cph.h diff --git a/cgogn/core/cph/attribute_handler_cph.h b/cgogn/core/cph/attribute_handler_cph.h new file mode 100644 index 00000000..2fb46a47 --- /dev/null +++ b/cgogn/core/cph/attribute_handler_cph.h @@ -0,0 +1,147 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef CORE_CPH_ATTRIBUTE_HANDLER_CPH_H_ +#define CORE_CPH_ATTRIBUTE_HANDLER_CPH_H_ + +#include +#include + +namespace cgogn +{ + +/** + * \brief AttributeHandler class + * @TPARAM T the data type of the attribute to handlde + */ +template +class AttributeHandlerCPH : public AttributeHandler +{ +public: + + typedef AttributeHandler Inherit; + typedef AttributeHandlerCPH Self; + + typedef T value_type; + + AttributeHandlerCPH() : + Inherit() + {} + + AttributeHandlerCPH(MapData* const m, TChunkArray* const ca) : + Inherit(m,ca) + {} + + AttributeHandlerCPH(const Self& att) : + Inherit(att) + {} + + AttributeHandlerCPH(Self&& att) CGOGN_NOEXCEPT : + Inherit(att) + {} + + TChunkArray const* get_data() const + { + return Inherit::get_data(); + } + + bool is_valid() const + { + return Inherit::is_valid(); + } + + T& operator[](Dart d) + { + switch(ORBIT) + { + case Orbit::PHI1: return vertex_embedding(d); break; + default: edge_face_embedding(d); break; + } + + ImplicitHierarchicalMap2* m = reinterpret_cast(this->m_map) ; + assert(m->m_dartLevel[d] <= m->m_curLevel || !"Access to a dart introduced after current level") ; + assert(m->vertexInsertionLevel(d) <= m->m_curLevel || !"Access to the embedding of a vertex inserted after current level") ; + + unsigned int orbit = this->getOrbit() ; + unsigned int nbSteps = m->m_curLevel - m->vertexInsertionLevel(d) ; + unsigned int index = m->getEmbedding(d) ; + + if(index == EMBNULL) + { + index = Algo::Topo::setOrbitEmbeddingOnNewCell(m, d) ; + m->m_nextLevelCell[orbit]->operator[](index) = EMBNULL ; + } + + AttributeContainer& cont = m->getAttributeContainer() ; + unsigned int step = 0 ; + while(step < nbSteps) + { + step++ ; + unsigned int nextIdx = m->m_nextLevelCell[orbit]->operator[](index) ; + if (nextIdx == EMBNULL) + { + nextIdx = m->newCell() ; + m->copyCell(nextIdx, index) ; + m->m_nextLevelCell[orbit]->operator[](index) = nextIdx ; + m->m_nextLevelCell[orbit]->operator[](nextIdx) = EMBNULL ; + cont.refLine(index) ; + } + index = nextIdx ; + } + return this->m_attrib->operator[](index); + } + + const T& operator[](Dart d) const + { + ImplicitHierarchicalMap2* m = reinterpret_cast(this->m_map) ; + assert(m->m_dartLevel[d] <= m->m_curLevel || !"Access to a dart introduced after current level") ; + assert(m->vertexInsertionLevel(d) <= m->m_curLevel || !"Access to the embedding of a vertex inserted after current level") ; + + unsigned int orbit = this->getOrbit() ; + unsigned int nbSteps = m->m_curLevel - m->vertexInsertionLevel(d) ; + unsigned int index = m->getEmbedding(d) ; + + unsigned int step = 0 ; + while(step < nbSteps) + { + step++ ; + unsigned int next = m->m_nextLevelCell[orbit]->operator[](index) ; + if(next != EMBNULL) index = next ; + else break ; + } + return this->m_attrib->operator[](index); + } + + T& operator[](unsigned int a) + { + return AttributeHandler::operator[](a) ; + } + + const T& operator[](unsigned int a) const + { + return AttributeHandler::operator[](a) ; + } + +} // namespace cgogn + +#endif // CORE_CPH_ATTRIBUTE_HANDLER_CPH_H_ \ No newline at end of file From 71ec3670e78efe8c52d3e2ab2953364a36fdebbc Mon Sep 17 00:00:00 2001 From: lionel untereiner Date: Thu, 14 Jan 2016 16:51:40 +0100 Subject: [PATCH 004/402] adding cph into cmakelists --- cgogn/core/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cgogn/core/CMakeLists.txt b/cgogn/core/CMakeLists.txt index e6f81667..59acd00e 100644 --- a/cgogn/core/CMakeLists.txt +++ b/cgogn/core/CMakeLists.txt @@ -25,6 +25,9 @@ set(HEADER_FILES container/chunk_array.h container/chunk_stack.h + cph/attribute_handler_cph.h + cph/ihcmap2.h + utils/assert.h utils/buffers.h utils/definitions.h From b60da68202037856fe130ea0a791c1e777fee4bd Mon Sep 17 00:00:00 2001 From: Lionel Untereiner Date: Mon, 11 Jan 2016 17:24:07 +0100 Subject: [PATCH 005/402] init mr cmap2 --- cgogn/core/mrcmap/mrcmap2.h | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 cgogn/core/mrcmap/mrcmap2.h diff --git a/cgogn/core/mrcmap/mrcmap2.h b/cgogn/core/mrcmap/mrcmap2.h new file mode 100644 index 00000000..e69de29b From 4921fd31d058ea241c20ba588adf6c9d8cacb2d7 Mon Sep 17 00:00:00 2001 From: Lionel Untereiner Date: Mon, 11 Jan 2016 22:53:12 +0100 Subject: [PATCH 006/402] draft mrcmap2 --- cgogn/core/CMakeLists.txt | 2 + cgogn/core/mrcmap/mrcmap2.h | 214 ++++++++++++++++++++++++++++++++++++ 2 files changed, 216 insertions(+) diff --git a/cgogn/core/CMakeLists.txt b/cgogn/core/CMakeLists.txt index e6f81667..ec403973 100644 --- a/cgogn/core/CMakeLists.txt +++ b/cgogn/core/CMakeLists.txt @@ -33,6 +33,8 @@ set(HEADER_FILES utils/name_types.h utils/serialization.h utils/thread.h + + mrcmap/mrcmap2.h ) set(SOURCE_FILES diff --git a/cgogn/core/mrcmap/mrcmap2.h b/cgogn/core/mrcmap/mrcmap2.h index e69de29b..88580f60 100644 --- a/cgogn/core/mrcmap/mrcmap2.h +++ b/cgogn/core/mrcmap/mrcmap2.h @@ -0,0 +1,214 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef CORE_MRCMAP_MRCMAP2_H_ +#define CORE_MRCMAP_MRCMAP2_H_ + +#include +#include +#include + +namespace cgogn +{ + +template +class MRCMap2_T +{ +public: + + typedef MRCMap2_T Self; + typedef CMap2_T CMap2; + + template + using ChunkArray = typename CMap2::template ChunkArray; + + +protected: + /** + * pointers to maps (one for each level) + */ + std::deque maps_; + + /** + * pointers to attributs that stores next level + * correspondance indices for each dart + */ + std::deque*> next_level_indices_; + + /** + * pointers to attributs that stores previous level + * correspondance indices for each dart + */ + std::deque*> previous_level_indices_; + + /** + * stack for current level temporary storage + */ + std::stack> levels_stack_ ; + + /** + * current level in multiresolution map + */ + unsigned int current_level_; + + //TODO le niveau courant doit etre par thread + //appele sur la carte et non plus un champs de + //la classe carte + + + + inline void add_level_back() + { + //ajouter une carte par copie dans maps_ + //ajouter un chunkarray dans next_ + CMap2* last = maps_.back(); + maps_.emplace_back(last); + } + + inline void remove_level_back() + { + maps_.pop_back(); + } + + inline void add_level_front() + { + CMap2* first = maps_.front(); + maps.emplace_front(first); + } + + inline void remove_level_front() + { + maps_.pop_front(); + } + +public: + + MRCMap2_T() + {} + + ~MRCMap2_T() + {} + + MRCMap2_T(Self const&) = delete; + MRCMap2_T(Self &&) = delete; + Self& operator=(Self const&) = delete; + Self& operator=(Self &&) = delete; + + + //1 thread par niveau = 1 thread par carte + //n thread par niveau = n thread par carte + + inline unsigned int get_maximum_level() const + { + return static_cast(maps_.size()); + } + + inline unsigned int get_current_level() const + { + return current_level_; + } + + inline void set_current_level(unsigned int l) + { + current_level_ = l; + } + + inline void inc_current_level() + { + cgogn_debug_assert(get_current_level() < maps_.size() - 1, "incCurrentLevel : already at maximum resolution level"); + ++current_level_; + } + + inline void dec_current_level() + { + cgogn_debug_assert(get_current_level() > 0, "decCurrentLevel : already at minimum resolution level"); + --current_level_; + } + + /** + * store current resolution level on a stack + */ + inline void push_level() + { + levels_stack_.push_back(get_current_level()) ; + } + + /** + * set as current the resolution level of the top of the stack + */ + inline void pop_level() + { + set_current_level(levels_stack_.back()) ; + levels_stack_.pop_back() ; + } + + inline const CMap2* current() const + { + return maps_[get_current_level()]; + } + +protected: + + /******************************************************************************* + * Orbits traversal + *******************************************************************************/ + + template + inline void foreach_dart_of_vertex(Dart d, const FUNC& f) const + { + current()->foreach_dart_of_vertex(d, f); + } + + template + inline void foreach_dart_of_face(Dart d, const FUNC& f) const + { + current()->foreach_dart_of_face(d, f); + } + + template + void foreach_dart_of_volume(Dart d, const FUNC& f) const + { + current()->foreach_dart_of_volume(d, f); + } + + template + inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const + { + switch (ORBIT) + { + case Orbit::DART: foreach_dart_of_orbit(c, f); break; + case Orbit::PHI1: foreach_dart_of_orbit(c, f); break; + case Orbit::PHI2: //TODO add a foreach_dart_of_edge to cmap2 f(c.dart); f(phi2(c.dart)); break; + case Orbit::PHI1_PHI2: foreach_dart_of_volume(c, f); break; + case Orbit::PHI21: foreach_dart_of_vertex(c, f); break; + case Orbit::PHI2_PHI3: + case Orbit::PHI1_PHI3: + case Orbit::PHI21_PHI31: + default: cgogn_assert_not_reached("Cells of this dimension are not handled"); break; + } + } +}; + +} // namespace cgogn + +#endif // CORE_MRCMAP_MRCMAP2_H_ From 9970df5d5e3f8814507ece07df17e036f177b868 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Sun, 31 Jan 2016 17:19:59 +0100 Subject: [PATCH 007/402] added options CGOGN_USE_GLIBCXX_DEBUG and CGOGN_USE_GLIBCXX_DEBUG_PEDANTIC Fixed difficulties in finding openMP with clang 3.7 Using -pthread instead of -lpthread (was an issue with clang) Signed-off-by: Etienne Schmitt --- CMakeLists.txt | 28 +++++++++++++++++++++------- cgogn/core/container/chunk_array.h | 19 ++++++++++++++++--- cgogn/core/utils/name_types.h | 12 +++++++++++- cmake/CompilerOptions.cmake | 28 +++++++++++++++++++--------- 4 files changed, 67 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cf2f9f76..b27c3cbb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,11 +37,18 @@ endif() #### ThirdParty options set(CGOGN_THIRDPARTY_DIR ${CMAKE_SOURCE_DIR}/thirdparty) -option(CGOGN_PROVIDE_EIGEN "Use the version of eigen that is packaged with CGoGN" ON) -option(CGOGN_PROVIDE_TINYXML2 "Use the version of tinyxml2 that is packaged with CGoGN" ON) -option(CGOGN_BUILD_TESTS "build cgogn unit tests using google test framework" ON) -option(CGOGN_USE_OPENMP "activate openMP directives" OFF) -option(CGOGN_USE_PARALLEL_GLIBCXX "highly experimental : compiles using the parallel mode" OFF) +option(CGOGN_PROVIDE_EIGEN "Use the version of eigen that is packaged with CGoGN." ON) +option(CGOGN_PROVIDE_TINYXML2 "Use the version of tinyxml2 that is packaged with CGoGN." ON) +option(CGOGN_BUILD_TESTS "Build cgogn unit tests using google test framework." ON) +option(CGOGN_USE_OPENMP "Activate openMP directives." OFF) +if (NOT MSVC) + option(CGOGN_USE_PARALLEL_GLIBCXX "Highly experimental : compiles using the parallel mode." OFF) + option(CGOGN_USE_GLIBCXX_DEBUG "Use the debug version of STL (useful for bounds checking)." OFF) + option(CGOGN_USE_GLIBCXX_DEBUG_PEDANTIC "Use an extremely picky debug version of STL." OFF) + if (${CGOGN_USE_GLIBCXX_DEBUG_PEDANTIC}) + set(CGOGN_USE_GLIBCXX_DEBUG "ON") + endif(${CGOGN_USE_GLIBCXX_DEBUG_PEDANTIC}) +endif(NOT MSVC) if (${CGOGN_USE_PARALLEL_GLIBCXX}) set(CGOGN_USE_OPENMP "ON") endif() @@ -80,8 +87,15 @@ deduce_build_type() if(${CGOGN_USE_OPENMP}) find_package(OpenMP) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") + if(${OPENMP_FOUND}) + add_flags(CMAKE_C_FLAGS ${OpenMP_C_FLAGS}) + add_flags(CMAKE_CXX_FLAGS ${OpenMP_CXX_FLAGS}) + else() + if ((${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") AND (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "3.7"))) + add_flags(CMAKE_C_FLAGS "-fopenmp") + add_flags(CMAKE_CXX_FLAGS "-fopenmp") + endif() + endif() endif() if(CGOGN_BUILD_TESTS) diff --git a/cgogn/core/container/chunk_array.h b/cgogn/core/container/chunk_array.h index a59f1009..4263b129 100644 --- a/cgogn/core/container/chunk_array.h +++ b/cgogn/core/container/chunk_array.h @@ -24,13 +24,17 @@ #ifndef CORE_CONTAINER_CHUNK_ARRAY_H_ #define CORE_CONTAINER_CHUNK_ARRAY_H_ +#include +#include +#include +#include +#include + #include #include #include #include -#include -#include -#include + namespace cgogn { @@ -194,7 +198,16 @@ class ChunkArray : public ChunkArrayGen */ void swap_elements(unsigned int idx1, unsigned int idx2) override { +// small workaround to avoid difficulties with std::swap when _GLIBCXX_DEBUG is defined. +#ifndef _GLIBCXX_DEBUG std::swap(table_data_[idx1 / CHUNKSIZE][idx1 % CHUNKSIZE], table_data_[idx2 / CHUNKSIZE][idx2 % CHUNKSIZE] ); +#else + T& a = table_data_[idx1 / CHUNKSIZE][idx1 % CHUNKSIZE]; + T& b = table_data_[idx2 / CHUNKSIZE][idx2 % CHUNKSIZE]; + T tmp(std::move(a)); + a = std::move(b); + b = std::move(tmp); +#endif // _GLIBCXX_DEBUG } // void save(std::ostream& fs, unsigned int nb_lines) const diff --git a/cgogn/core/utils/name_types.h b/cgogn/core/utils/name_types.h index 20b35d28..6eb54e14 100644 --- a/cgogn/core/utils/name_types.h +++ b/cgogn/core/utils/name_types.h @@ -149,13 +149,23 @@ inline auto name_of_type_impl(const T&)->typename std::enable_if Date: Sun, 31 Jan 2016 20:17:58 +0100 Subject: [PATCH 008/402] added wrongly removed thread_start() and thread_stop() Signed-off-by: Etienne Schmitt --- cgogn/core/utils/thread.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cgogn/core/utils/thread.h b/cgogn/core/utils/thread.h index 7f407bcb..e29ec864 100644 --- a/cgogn/core/utils/thread.h +++ b/cgogn/core/utils/thread.h @@ -94,6 +94,7 @@ class ThreadFunction void operator()() { + thread_start(); while (true) { sync2_.wait(); // wait for vectors to be filled @@ -103,6 +104,7 @@ class ThreadFunction f_(e, thread_order_); sync1_.wait(); // wait every thread has finished } + thread_stop(); } }; From 21fa0f021bcef1de02ab95b4d92074a11b217050 Mon Sep 17 00:00:00 2001 From: Lionel Untereiner Date: Fri, 8 Jan 2016 09:48:26 +0100 Subject: [PATCH 009/402] first version of 2D CPH CMAP --- cgogn/core/cph/ihcmap2.h | 398 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 398 insertions(+) create mode 100644 cgogn/core/cph/ihcmap2.h diff --git a/cgogn/core/cph/ihcmap2.h b/cgogn/core/cph/ihcmap2.h new file mode 100644 index 00000000..97f6fcbe --- /dev/null +++ b/cgogn/core/cph/ihcmap2.h @@ -0,0 +1,398 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef CORE_CPH_IHCMAP2_H_ +#define CORE_CPH_IHCMAP2_H_ + +#include +#include + +namespace cgogn +{ + +template +class IHCMap2_T : protected CMap2_T +{ +public: + + typedef CMap2_T Inherit; + typedef IHCMap2_T Self; + + friend typename Self::Inherit; + friend typename Inherit::Inherit; + + template friend class cgogn::DartMarkerT; + + static const Orbit DART = Orbit::DART; + static const Orbit VERTEX = Orbit::PHI21; + static const Orbit EDGE = Orbit::PHI2; + static const Orbit FACE = Orbit::PHI1; + static const Orbit VOLUME = Orbit::PHI1_PHI2; + + typedef Cell Vertex; + typedef Cell Edge; + typedef Cell Face; + typedef Cell Volume; + + template + using AttributeHandler = typename AttributeHandlerCPH; + template + using DartAttributeHandler = AttributeHandlerCPH; + template + using VertexAttributeHandler = AttributeHandlerCPH; + template + using EdgeAttributeHandler = AttributeHandlerCPH; + template + using FaceAttributeHandler = AttributeHandlerCPH; + template + using VolumeAttributeHandler = AttributeHandlerCPH; + + using DartMarker = typename Inherit::DartMarker; + using DartMarkerStore = typename Inherit::DartMarkerStore; + +private: + unsigned int current_level_; + unsigned int maximum_level_; + unsigned int id_count_; + + DartAttribute dart_level_ ; + DartAttribute edge_id_ ; + +public: + IHCMap2_T() : Inherit() + { + init(); + } + + ~IHCMap2_T() override + {} + + IHCMap2_T(Self const&) = delete; + IHCMap2_T(Self &&) = delete; + Self& operator=(Self const&) = delete; + Self& operator=(Self &&) = delete; + + + inline void init_implicit_properties() + { + //initEdgeId() ; + + //init each edge Id at 0 + for(Dart d : Inherit) + { + set_edge_id(d, 0); + } + + // for(unsigned int orbit = 0u; orbit < Orbit::NB_ORBITS; ++orbit) + // { + // if(m_nextLevelCell[orbit] != NULL) + // { + // AttributeContainer& cellCont = m_attribs[orbit] ; + // for(unsigned int i = cellCont.begin(); i < cellCont.end(); cellCont.next(i)) + // m_nextLevelCell[orbit]->operator[](i) = EMBNULL ; + // } + // } + } + + /******************************************************************************* + * Basic topological operations + *******************************************************************************/ + + inline Dart phi1(Dart d) const + { + cgogn_debug_assert(get_dart_level(d) <= get_current_level(), "Access to a dart introduced after current level") ; + + bool finished = false ; + unsigned int edge_id = get_edge_id(d) ; + Dart it = d ; + do + { + it = Inherit::phi1(it) ; + if(get_dart_level(it) <= get_current_level()) + finished = true ; + else + { + while(get_edge_id(it) != edge_id) + it = Inherit::phi1(Inherit::phi2(it)) ; + } + } while(!finished) ; + return it ; + } + + inline Dart phi_1(Dart d) const + { + cgogn_debug_assert(get_dart_level(d) <= get_current_level(), "Access to a dart introduced after current level") ; + + bool finished = false ; + Dart it = Inherit::phi_1(d) ; + unsigned int edge_id = get_edge_id(d) ; + do + { + if(get_dart_level(it) <= get_current_level()) + finished = true ; + else + { + it = Inherit::phi_1(it) ; + while(get_edge_id(it) != edge_id) + it = Inherit::phi_1(Inherit::phi2(it)) ; + } + } while(!finished) ; + return it ; + } + + /** + * \brief phi2 + * @param d + * @return phi2(d) + */ + inline Dart phi2(Dart d) const + { + cgogn_debug_assert(get_dart_level(d) <= get_current_level(), "Access to a dart introduced after current level") ; + + if(Inherit::phi2(d) == d) + return d; + return Inherit::phi2(Inherit::phi_1(phi1(d))); + } + +protected: + + /** + * \brief add a Dart in the map + * @return the new Dart + */ + inline Dart add_dart() + { + Dart d = Inherit::add_dart(); + set_dart_level(d, get_current_level()); + if(get_current_level() > get_maximum_level()) // update max level + set_maximum_level(get_current_level()); // if needed + + return d ; + } + +protected: + + /******************************************************************************* + * Orbits traversal + *******************************************************************************/ + + template + inline void foreach_dart_of_vertex(Dart d, const FUNC& f) const + { + Dart it = d; + do + { + f(it); + it = phi2(phi_1(it)); + } while (it != d); + } + + template + void foreach_dart_of_volume(Dart d, const FUNC& f) const + { + DartMarkerStore marker(*this); + + std::vector* visited_faces = cgogn::get_dart_buffers()->get_buffer(); + visited_faces->push_back(d); // Start with the face of d + + // For every face added to the list + for(unsigned int i = 0; i < visited_faces->size(); ++i) + { + if (!marker.is_marked((*visited_faces)[i])) // Face has not been visited yet + { + // mark visited darts (current face) + // and add non visited adjacent faces to the list of face + Dart e = (*visited_faces)[i] ; + do + { + f(e); // apply the function to the darts of the face + marker.mark(e); // Mark + Dart adj = phi2(e); // Get adjacent face + if (!marker.is_marked(adj)) + visited_faces->push_back(adj); // Add it + e = phi1(e); + } while (e != (*visited_faces)[i]); + } + } + + cgogn::get_dart_buffers()->release_buffer(visited_faces); + } + + template + inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const + { + switch (ORBIT) + { + case Orbit::DART: Inherit::foreach_dart_of_orbit(c, f); break; + case Orbit::PHI1: Inherit::foreach_dart_of_orbit(c, f); break; + case Orbit::PHI2: f(c.dart); f(phi2(c.dart)); break; + case Orbit::PHI1_PHI2: foreach_dart_of_volume(c, f); break; + case Orbit::PHI21: foreach_dart_of_vertex(c, f); break; + case Orbit::PHI2_PHI3: + case Orbit::PHI1_PHI3: + case Orbit::PHI21_PHI31: + default: cgogn_assert_not_reached("Cells of this dimension are not handled"); break; + } + } + +public: + /*************************************************** + * LEVELS MANAGEMENT * + ***************************************************/ + + inline unsigned int get_current_level() const + { + return current_level_ ; + } + + inline void set_current_level(unsigned int l) + { + current_level_ = l ; + } + + inline void inc_current_level() + { + cgogn_debug_assert(get_current_level() < get_maximum_level(), "incCurrentLevel : already at maximum resolution level"); + ++current_level_ ; + } + + inline void dec_current_level() + { + cgogn_debug_assert(get_current_level() > 0u, "decCurrentLevel : already at minimum resolution level"); + --current_level_ ; + } + + inline unsigned int get_maximum_level() const + { + return maximum_level_ ; + } + + inline void set_maximum_level(unsigned int l) + { + maximum_level_ = l; + } + + inline unsigned int get_dart_level(Dart d) const + { + return dart_level_[d] ; + } + + inline void set_dart_level(Dart d, unsigned int l) + { + dart_level_[d] = l ; + } + + /*************************************************** + * EDGE ID MANAGEMENT * + ***************************************************/ + + /** + * Give a new unique id to all the edges of the map + */ + inline void init_edge_ids() + { + id_count_ = 0; + DartMarker marker(*this); + + for (Dart d : Inherit) + { + if(!marker.is_marked(d)) + { + marker.mark_orbit(Edge(d)) ; + edge_id_[d] = id_count_ ; + edge_id_[Inherit::phi2(d)] = id_count_++ ; + } + } + } + + /** + * Return the next available edge id + */ + inline unsigned int get_new_edge_id() const + { + return id_count_++ ; + } + + inline unsigned int get_edge_id(Dart d) const + { + return edge_id_[d] ; + } + + inline void set_edge_id(Dart d, unsigned int i) + { + edge_id_[d] = i ; + } + + inline unsigned int get_tri_refinement_edge_id(Dart d) const + { + unsigned int d_id = get_edge_id(phi_1(d)); + unsigned int e_id = get_edge_id(phi1(d)); + + unsigned int id = d_id + e_id; + + if(id == 0u) + return 1u; + else if(id == 1u) + return 2u; + else if(id == 2u) + { + if(d_id == e_id) + return 0u; + else + return 1u; + } + + //else if(id == 3) + return 0u; + } + + inline unsigned int get_quad_refinement_edge_id(Dart d) const + { + unsigned int e_id = get_edge_id(phi1(d)); + + if(e_id == 0u) + return 1u; + + //else if(e_id == 1) + return 0u; + } + +}; + +template +struct IHCMap2TopoTraits +{ + static const int PRIM_SIZE = 1; + typedef IHCMap2_T> CONCRETE; +}; + +struct IHCMap2DataTraits +{ + static const unsigned int CHUNK_SIZE = 4096; +}; + +using IHCMap2 = IHCMap2_T>; + +} // namespace cgogn + +#endif // CORE_CPH_IHCMAP2_H_ \ No newline at end of file From 95e25afe03ec9b64e18da45cbc2f46023521d1e2 Mon Sep 17 00:00:00 2001 From: Lionel Untereiner Date: Fri, 8 Jan 2016 11:39:14 +0100 Subject: [PATCH 010/402] adding foreach_cell with level parameter --- cgogn/core/cph/ihcmap2.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/cgogn/core/cph/ihcmap2.h b/cgogn/core/cph/ihcmap2.h index 97f6fcbe..5614242c 100644 --- a/cgogn/core/cph/ihcmap2.h +++ b/cgogn/core/cph/ihcmap2.h @@ -78,6 +78,9 @@ class IHCMap2_T : protected CMap2_T DartAttribute dart_level_ ; DartAttribute edge_id_ ; + ChunkArray* next_level_cell_[NB_ORBITS]; + + public: IHCMap2_T() : Inherit() { @@ -174,6 +177,18 @@ class IHCMap2_T : protected CMap2_T return Inherit::phi2(Inherit::phi_1(phi1(d))); } + template + inline void foreach_cell(const FUNC& f, unsigned int level) + { + + } + + template + inline void foreach_cell(const FUNC& f) + { + + } + protected: /** From 8a6ec94b5693655f31809c22616c4f0bdf7381a0 Mon Sep 17 00:00:00 2001 From: Lionel Untereiner Date: Fri, 8 Jan 2016 11:39:45 +0100 Subject: [PATCH 011/402] first version of attribute_handler cph specific --- cgogn/core/cph/attribute_handler_cph.h | 147 +++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 cgogn/core/cph/attribute_handler_cph.h diff --git a/cgogn/core/cph/attribute_handler_cph.h b/cgogn/core/cph/attribute_handler_cph.h new file mode 100644 index 00000000..2fb46a47 --- /dev/null +++ b/cgogn/core/cph/attribute_handler_cph.h @@ -0,0 +1,147 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef CORE_CPH_ATTRIBUTE_HANDLER_CPH_H_ +#define CORE_CPH_ATTRIBUTE_HANDLER_CPH_H_ + +#include +#include + +namespace cgogn +{ + +/** + * \brief AttributeHandler class + * @TPARAM T the data type of the attribute to handlde + */ +template +class AttributeHandlerCPH : public AttributeHandler +{ +public: + + typedef AttributeHandler Inherit; + typedef AttributeHandlerCPH Self; + + typedef T value_type; + + AttributeHandlerCPH() : + Inherit() + {} + + AttributeHandlerCPH(MapData* const m, TChunkArray* const ca) : + Inherit(m,ca) + {} + + AttributeHandlerCPH(const Self& att) : + Inherit(att) + {} + + AttributeHandlerCPH(Self&& att) CGOGN_NOEXCEPT : + Inherit(att) + {} + + TChunkArray const* get_data() const + { + return Inherit::get_data(); + } + + bool is_valid() const + { + return Inherit::is_valid(); + } + + T& operator[](Dart d) + { + switch(ORBIT) + { + case Orbit::PHI1: return vertex_embedding(d); break; + default: edge_face_embedding(d); break; + } + + ImplicitHierarchicalMap2* m = reinterpret_cast(this->m_map) ; + assert(m->m_dartLevel[d] <= m->m_curLevel || !"Access to a dart introduced after current level") ; + assert(m->vertexInsertionLevel(d) <= m->m_curLevel || !"Access to the embedding of a vertex inserted after current level") ; + + unsigned int orbit = this->getOrbit() ; + unsigned int nbSteps = m->m_curLevel - m->vertexInsertionLevel(d) ; + unsigned int index = m->getEmbedding(d) ; + + if(index == EMBNULL) + { + index = Algo::Topo::setOrbitEmbeddingOnNewCell(m, d) ; + m->m_nextLevelCell[orbit]->operator[](index) = EMBNULL ; + } + + AttributeContainer& cont = m->getAttributeContainer() ; + unsigned int step = 0 ; + while(step < nbSteps) + { + step++ ; + unsigned int nextIdx = m->m_nextLevelCell[orbit]->operator[](index) ; + if (nextIdx == EMBNULL) + { + nextIdx = m->newCell() ; + m->copyCell(nextIdx, index) ; + m->m_nextLevelCell[orbit]->operator[](index) = nextIdx ; + m->m_nextLevelCell[orbit]->operator[](nextIdx) = EMBNULL ; + cont.refLine(index) ; + } + index = nextIdx ; + } + return this->m_attrib->operator[](index); + } + + const T& operator[](Dart d) const + { + ImplicitHierarchicalMap2* m = reinterpret_cast(this->m_map) ; + assert(m->m_dartLevel[d] <= m->m_curLevel || !"Access to a dart introduced after current level") ; + assert(m->vertexInsertionLevel(d) <= m->m_curLevel || !"Access to the embedding of a vertex inserted after current level") ; + + unsigned int orbit = this->getOrbit() ; + unsigned int nbSteps = m->m_curLevel - m->vertexInsertionLevel(d) ; + unsigned int index = m->getEmbedding(d) ; + + unsigned int step = 0 ; + while(step < nbSteps) + { + step++ ; + unsigned int next = m->m_nextLevelCell[orbit]->operator[](index) ; + if(next != EMBNULL) index = next ; + else break ; + } + return this->m_attrib->operator[](index); + } + + T& operator[](unsigned int a) + { + return AttributeHandler::operator[](a) ; + } + + const T& operator[](unsigned int a) const + { + return AttributeHandler::operator[](a) ; + } + +} // namespace cgogn + +#endif // CORE_CPH_ATTRIBUTE_HANDLER_CPH_H_ \ No newline at end of file From 515bfafaea4dd287cd077bb42368200c1ca6b455 Mon Sep 17 00:00:00 2001 From: lionel untereiner Date: Thu, 14 Jan 2016 16:51:40 +0100 Subject: [PATCH 012/402] adding cph into cmakelists --- cgogn/core/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cgogn/core/CMakeLists.txt b/cgogn/core/CMakeLists.txt index 510871e4..97bb8184 100644 --- a/cgogn/core/CMakeLists.txt +++ b/cgogn/core/CMakeLists.txt @@ -27,6 +27,9 @@ set(HEADER_FILES container/chunk_array.h container/chunk_stack.h + cph/attribute_handler_cph.h + cph/ihcmap2.h + utils/assert.h utils/buffers.h utils/definitions.h From bdf32219e3d1549710a69c74079956588cf49656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Mon, 1 Feb 2016 11:21:06 +0100 Subject: [PATCH 013/402] added ~Viewer() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/attribute_handler.h | 3 +- cgogn/rendering/examples/simple_viewer.cpp | 70 ++++++++++++++++------ cgogn/rendering/shaders/vbo.h | 2 +- 3 files changed, 53 insertions(+), 22 deletions(-) diff --git a/cgogn/core/cmap/attribute_handler.h b/cgogn/core/cmap/attribute_handler.h index 2848ea3a..8e3a436f 100644 --- a/cgogn/core/cmap/attribute_handler.h +++ b/cgogn/core/cmap/attribute_handler.h @@ -24,10 +24,9 @@ #ifndef CORE_MAP_ATTRIBUTE_HANDLER_H_ #define CORE_MAP_ATTRIBUTE_HANDLER_H_ -#include #include #include - +#include namespace cgogn { diff --git a/cgogn/rendering/examples/simple_viewer.cpp b/cgogn/rendering/examples/simple_viewer.cpp index fe99e911..511802a7 100644 --- a/cgogn/rendering/examples/simple_viewer.cpp +++ b/cgogn/rendering/examples/simple_viewer.cpp @@ -21,25 +21,29 @@ * * *******************************************************************************/ -#include #include #include -#include -#include -#include -#include +#include #include + #include + #include -#include #include +#include +#include +#include +#include +#include + #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) using Map2 = cgogn::CMap2; using Vec3 = Eigen::Vector3d; +//using Vec3 = cgogn::geometry::Vec_T>; template using VertexAttributeHandler = Map2::VertexAttributeHandler; @@ -48,8 +52,17 @@ using VertexAttributeHandler = Map2::VertexAttributeHandler; class Viewer : public QOGLViewer { public: + Viewer(); + inline Viewer(const Viewer&) = delete; + Viewer& operator=(const Viewer&) = delete; - Map2 map; + virtual void draw(); + virtual void init(); + void import(const std::string& surfaceMesh); + virtual ~Viewer(); + +private: + Map2 map_; VertexAttributeHandler vertex_position_; VertexAttributeHandler vertex_normal_; @@ -57,17 +70,13 @@ class Viewer : public QOGLViewer cgogn::rendering::MapRender* render_; - virtual void draw(); - virtual void init(); - - void import(const std::string& surfaceMesh); - cgogn::rendering::VBO* vbo_pos_; cgogn::rendering::VBO* vbo_norm_; cgogn::rendering::ShaderSimpleColor* shader1_; cgogn::rendering::ShaderFlat* shader2_; cgogn::rendering::ShaderVectorPerVertex* shader3_; + }; @@ -78,12 +87,12 @@ class Viewer : public QOGLViewer void Viewer::import(const std::string& surfaceMesh) { - cgogn::io::import_surface(map, surfaceMesh); + cgogn::io::import_surface(map_, surfaceMesh); - vertex_position_ = map.get_attribute("position"); - vertex_normal_ = map.add_attribute("normal"); + vertex_position_ = map_.get_attribute("position"); + vertex_normal_ = map_.add_attribute("normal"); - cgogn::geometry::compute_normal_vertices(map, vertex_position_, vertex_normal_); + cgogn::geometry::compute_normal_vertices(map_, vertex_position_, vertex_normal_); cgogn::geometry::compute_bounding_box(vertex_position_, bb_); setSceneRadius(bb_.diag_size()); @@ -92,6 +101,29 @@ void Viewer::import(const std::string& surfaceMesh) showEntireScene(); } +Viewer::~Viewer() +{ + delete render_; + delete vbo_pos_; + delete vbo_norm_; + delete shader1_; + delete shader2_; + delete shader3_; +} + +Viewer::Viewer() : + map_(), + vertex_position_(), + vertex_normal_(), + bb_(), + render_(nullptr), + vbo_pos_(nullptr), + vbo_norm_(nullptr), + shader1_(nullptr), + shader2_(nullptr), + shader3_(nullptr) +{} + void Viewer::draw() { QMatrix4x4 proj; @@ -143,9 +175,9 @@ void Viewer::init() render_ = new cgogn::rendering::MapRender(); - render_->init_primitives(map, cgogn::rendering::POINTS); - render_->init_primitives(map, cgogn::rendering::LINES); - render_->init_primitives(map, cgogn::rendering::TRIANGLES); + render_->init_primitives(map_, cgogn::rendering::POINTS); + render_->init_primitives(map_, cgogn::rendering::LINES); + render_->init_primitives(map_, cgogn::rendering::TRIANGLES); shader1_ = new cgogn::rendering::ShaderSimpleColor; shader1_->add_vao(); diff --git a/cgogn/rendering/shaders/vbo.h b/cgogn/rendering/shaders/vbo.h index ee7c70dc..dc8b03fa 100644 --- a/cgogn/rendering/shaders/vbo.h +++ b/cgogn/rendering/shaders/vbo.h @@ -27,7 +27,7 @@ #include -#include // impossible to include directly attribute_handler.h ! +#include #include namespace cgogn From 0503078822b3910c0e98c142509472460e930fb7 Mon Sep 17 00:00:00 2001 From: lionel untereiner Date: Mon, 1 Feb 2016 18:04:26 +0100 Subject: [PATCH 014/402] cph2 are working --- cgogn/core/cmap/cmap2.h | 109 +++++++++++ cgogn/core/cph/attribute_handler_cph.h | 4 +- cgogn/core/cph/ihcmap2.h | 257 ++++++++++++++----------- 3 files changed, 260 insertions(+), 110 deletions(-) diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 6f530012..1e3fce63 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -260,11 +260,120 @@ class CMap2_T : public CMap1_T return f; } + inline Vertex cut_edge(Edge e) + { + Dart nd = cut_edge_topo(e); + + Vertex v(nd); + + if(this->template is_orbit_embedded()) + { + init_orbit_embedding(this->phi1(e), this->template add_attribute_element()); + init_orbit_embedding(phi2(e), this->template add_attribute_element()); + } + + if (this->template is_orbit_embedded()) + { + init_orbit_embedding(v, this->template add_attribute_element()); + } + + if (this->template is_orbit_embedded()) + { + this->template init_embedding(phi2(e), this->template get_embedding(e)); + init_orbit_embedding(this->phi1(e), this->template add_attribute_element()); + } + + if (this->template is_orbit_embedded()) + { + this->template init_embedding(nd, this->template get_embedding(e.dart)); + Dart nd2 = phi2(nd); + this->template init_embedding(this->phi1(nd2), this->template get_embedding(nd2)); + } + + if (this->template is_orbit_embedded()) + { + this->template init_embedding(nd, this->template get_embedding(e.dart)); + Dart nd2 = phi2(nd); + this->template init_embedding(this->phi1(nd2), this->template get_embedding(nd2)); + } + + return v; + } + + inline void split_face(Dart d, Dart e) + { + split_face_topo(d,e); + + if(this->template is_orbit_embedded()) + { + init_orbit_embedding(this->phi_1(e), this->template add_attribute_element()); + init_orbit_embedding(this->phi_1(d), this->template add_attribute_element()); + } + + if (this->template is_orbit_embedded()) + { + this->template init_embedding(this->phi_1(e), this->template get_embedding(d)); + this->template init_embedding(this->phi_1(d), this->template get_embedding(e)); + } + + if (this->template is_orbit_embedded()) + { + init_orbit_embedding(this->phi_1(d), this->template add_attribute_element()); + } + + if (this->template is_orbit_embedded()) + { + this->template init_embedding(this->phi_1(d), this->template get_embedding(d)); + init_orbit_embedding(e, this->template add_attribute_element()); + } + + if (this->template is_orbit_embedded()) + { + init_orbit_embedding(this->phi_1(e), this->template get_embedding(d)); + init_orbit_embedding(this->phi_1(d), this->template get_embedding(d)); + } + } + + inline unsigned int degree(Face f) const { return Inherit::degree(f); } + +protected: + + inline Dart cut_edge_topo(Dart d) + { + Dart e = phi2(d); + + //remove old phi2 links + phi2_unsew(d); + + //cut the 1-edge of d + Dart nd = Inherit::cut_edge_topo(d); + //cut the 1-edge of e = phi2(d) + Dart ne = Inherit::cut_edge_topo(e); + + //add new phi2links + phi2_sew(d, ne); + phi2_sew(e, nd); + + return nd; + } + + inline void split_face_topo(Dart d, Dart e) + { + cgogn_message_assert(d != e, "split_face: d == e"); + // cgogn_message_assert(this->same_face(d,e), "split_face: d et e are not from same face"); + + Dart dd = Inherit::cut_edge_topo(this->phi_1(d)); + Dart ee = Inherit::cut_edge_topo(this->phi_1(e)); + + Inherit::split_face_topo(dd, ee); + phi2_sew(dd, ee); + } + protected: inline void close_hole_topo(Dart d) diff --git a/cgogn/core/cph/attribute_handler_cph.h b/cgogn/core/cph/attribute_handler_cph.h index 2fb46a47..bf12fd45 100644 --- a/cgogn/core/cph/attribute_handler_cph.h +++ b/cgogn/core/cph/attribute_handler_cph.h @@ -24,8 +24,8 @@ #ifndef CORE_CPH_ATTRIBUTE_HANDLER_CPH_H_ #define CORE_CPH_ATTRIBUTE_HANDLER_CPH_H_ -#include -#include +#include +#include namespace cgogn { diff --git a/cgogn/core/cph/ihcmap2.h b/cgogn/core/cph/ihcmap2.h index 5614242c..8829a7b3 100644 --- a/cgogn/core/cph/ihcmap2.h +++ b/cgogn/core/cph/ihcmap2.h @@ -24,24 +24,46 @@ #ifndef CORE_CPH_IHCMAP2_H_ #define CORE_CPH_IHCMAP2_H_ -#include -#include +#include +// #include namespace cgogn { -template -class IHCMap2_T : protected CMap2_T +template +class ContainerCPHBrowser : public ContainerBrowser { + const CONTAINER& cac_; + const MAP* map_; + public: + ContainerCPHBrowser(const CONTAINER& cac, const MAP* map) : cac_(cac), map_(map) {} + virtual unsigned int begin() const { return cac_.real_begin(); } + virtual unsigned int end() const { return cac_.real_end(); } + virtual void next(unsigned int &it) const + { + cac_.real_next(it); + if(map_->get_dart_level(Dart(it)) > map_->get_current_level()) + it = cac_.real_end(); + } + virtual void next_primitive(unsigned int &it, unsigned int primSz) const { cac_.real_next_primitive(it,primSz); } + virtual void enable() {} + virtual void disable() {} + virtual ~ContainerCPHBrowser() {} +}; - typedef CMap2_T Inherit; - typedef IHCMap2_T Self; +template +class IHCMap2_T : public CMap2_T +{ +public: + + typedef CMap2_T Inherit; + typedef IHCMap2_T Self; friend typename Self::Inherit; friend typename Inherit::Inherit; - template friend class cgogn::DartMarkerT; + friend class DartMarker_T; static const Orbit DART = Orbit::DART; static const Orbit VERTEX = Orbit::PHI21; @@ -54,68 +76,70 @@ class IHCMap2_T : protected CMap2_T typedef Cell Face; typedef Cell Volume; + template + using ChunkArray = typename Inherit::template ChunkArray; + template + using ChunkArrayContainer = typename Inherit::template ChunkArrayContainer; + template - using AttributeHandler = typename AttributeHandlerCPH; + using AttributeHandler = typename Inherit::template AttributeHandler; template - using DartAttributeHandler = AttributeHandlerCPH; + using DartAttributeHandler = AttributeHandler; template - using VertexAttributeHandler = AttributeHandlerCPH; + using VertexAttributeHandler = AttributeHandler; template - using EdgeAttributeHandler = AttributeHandlerCPH; + using EdgeAttributeHandler = AttributeHandler; template - using FaceAttributeHandler = AttributeHandlerCPH; + using FaceAttributeHandler = AttributeHandler; template - using VolumeAttributeHandler = AttributeHandlerCPH; + using VolumeAttributeHandler = AttributeHandler; - using DartMarker = typename Inherit::DartMarker; - using DartMarkerStore = typename Inherit::DartMarkerStore; + using DartMarker = typename cgogn::DartMarker; + using DartMarkerStore = typename cgogn::DartMarkerStore; -private: +protected: unsigned int current_level_; unsigned int maximum_level_; unsigned int id_count_; - DartAttribute dart_level_ ; - DartAttribute edge_id_ ; + // DartAttributeHandler dart_level_ ; + // DartAttributeHandler edge_id_ ; + ChunkArray* dart_level_; + ChunkArray* edge_id_; - ChunkArray* next_level_cell_[NB_ORBITS]; + ContainerCPHBrowser, Self>* cph_browser; + std::vector nb_darts_per_level; + + inline void init() + { + dart_level_ = this->topology_.template add_attribute("dartLevel") ; + edge_id_ = this->topology_.template add_attribute("edgeId"); + + cph_browser = new ContainerCPHBrowser, Self>(this->topology_, this); + + this->topology_.set_current_browser(cph_browser); + } public: - IHCMap2_T() : Inherit() + IHCMap2_T() : Inherit(), + current_level_(0), + maximum_level_(0), + id_count_(0) { - init(); + init(); } ~IHCMap2_T() override - {} + { + this->topology_.template remove_attribute(dart_level_); + this->topology_.template remove_attribute(edge_id_); + } IHCMap2_T(Self const&) = delete; IHCMap2_T(Self &&) = delete; Self& operator=(Self const&) = delete; Self& operator=(Self &&) = delete; - - - inline void init_implicit_properties() - { - //initEdgeId() ; - - //init each edge Id at 0 - for(Dart d : Inherit) - { - set_edge_id(d, 0); - } - - // for(unsigned int orbit = 0u; orbit < Orbit::NB_ORBITS; ++orbit) - // { - // if(m_nextLevelCell[orbit] != NULL) - // { - // AttributeContainer& cellCont = m_attribs[orbit] ; - // for(unsigned int i = cellCont.begin(); i < cellCont.end(); cellCont.next(i)) - // m_nextLevelCell[orbit]->operator[](i) = EMBNULL ; - // } - // } - } /******************************************************************************* * Basic topological operations @@ -123,7 +147,7 @@ class IHCMap2_T : protected CMap2_T inline Dart phi1(Dart d) const { - cgogn_debug_assert(get_dart_level(d) <= get_current_level(), "Access to a dart introduced after current level") ; + cgogn_message_assert(get_dart_level(d) <= get_current_level(), "Access to a dart introduced after current level") ; bool finished = false ; unsigned int edge_id = get_edge_id(d) ; @@ -144,7 +168,7 @@ class IHCMap2_T : protected CMap2_T inline Dart phi_1(Dart d) const { - cgogn_debug_assert(get_dart_level(d) <= get_current_level(), "Access to a dart introduced after current level") ; + cgogn_message_assert(get_dart_level(d) <= get_current_level(), "Access to a dart introduced after current level") ; bool finished = false ; Dart it = Inherit::phi_1(d) ; @@ -170,25 +194,13 @@ class IHCMap2_T : protected CMap2_T */ inline Dart phi2(Dart d) const { - cgogn_debug_assert(get_dart_level(d) <= get_current_level(), "Access to a dart introduced after current level") ; + cgogn_message_assert(get_dart_level(d) <= get_current_level(), "Access to a dart introduced after current level") ; if(Inherit::phi2(d) == d) return d; return Inherit::phi2(Inherit::phi_1(phi1(d))); } - template - inline void foreach_cell(const FUNC& f, unsigned int level) - { - - } - - template - inline void foreach_cell(const FUNC& f) - { - - } - protected: /** @@ -198,9 +210,18 @@ class IHCMap2_T : protected CMap2_T inline Dart add_dart() { Dart d = Inherit::add_dart(); + + set_edge_id(d, 0); set_dart_level(d, get_current_level()); - if(get_current_level() > get_maximum_level()) // update max level - set_maximum_level(get_current_level()); // if needed + + // update max level if needed + if(get_current_level() > get_maximum_level()) + { + set_maximum_level(get_current_level()); + nb_darts_per_level.push_back(0); + } + +// inc_nb_darts(get_current_level()); return d ; } @@ -211,19 +232,45 @@ class IHCMap2_T : protected CMap2_T * Orbits traversal *******************************************************************************/ + template + inline void foreach_dart_of_DART(Dart d, const FUNC& f) const + { + f(d); + } + + template + inline void foreach_dart_of_PHI1(Dart d, const FUNC& f) const + { + Dart it = d; + do + { + f(it); + it = phi1(it); + } while (it != d); + } + + template + inline void foreach_dart_of_PHI2(Dart d, const FUNC& f) const + { + f(d); + Dart d2 = phi2(d); + if (d2 != d) + f(d2); + } + template - inline void foreach_dart_of_vertex(Dart d, const FUNC& f) const + inline void foreach_dart_of_PHI21(Dart d, const FUNC& f) const { Dart it = d; do { f(it); - it = phi2(phi_1(it)); + it = Inherit::phi2(Inherit::phi_1(it)); } while (it != d); } template - void foreach_dart_of_volume(Dart d, const FUNC& f) const + void foreach_dart_of_PHI1_PHI2(Dart d, const FUNC& f) const { DartMarkerStore marker(*this); @@ -258,19 +305,32 @@ class IHCMap2_T : protected CMap2_T { switch (ORBIT) { - case Orbit::DART: Inherit::foreach_dart_of_orbit(c, f); break; - case Orbit::PHI1: Inherit::foreach_dart_of_orbit(c, f); break; - case Orbit::PHI2: f(c.dart); f(phi2(c.dart)); break; - case Orbit::PHI1_PHI2: foreach_dart_of_volume(c, f); break; - case Orbit::PHI21: foreach_dart_of_vertex(c, f); break; - case Orbit::PHI2_PHI3: - case Orbit::PHI1_PHI3: - case Orbit::PHI21_PHI31: + case Orbit::DART: foreach_dart_of_DART(c, f); break; + case Orbit::PHI1: foreach_dart_of_PHI1(c, f); break; + case Orbit::PHI2: foreach_dart_of_PHI2(c, f); break; + case Orbit::PHI1_PHI2: foreach_dart_of_PHI1_PHI2(c, f); break; + case Orbit::PHI21: foreach_dart_of_PHI21(c, f); break; + case Orbit::PHI2_PHI3: + case Orbit::PHI1_PHI3: default: cgogn_assert_not_reached("Cells of this dimension are not handled"); break; } } public: + + inline unsigned int face_degree(Dart d) + { + unsigned int count = 0 ; + Dart it = d ; + do + { + ++count ; + it = phi1(it) ; + } while (it != d) ; + return count ; + } + + /*************************************************** * LEVELS MANAGEMENT * ***************************************************/ @@ -287,13 +347,13 @@ class IHCMap2_T : protected CMap2_T inline void inc_current_level() { - cgogn_debug_assert(get_current_level() < get_maximum_level(), "incCurrentLevel : already at maximum resolution level"); + cgogn_message_assert(get_current_level() < get_maximum_level(), "incCurrentLevel : already at maximum resolution level"); ++current_level_ ; } inline void dec_current_level() { - cgogn_debug_assert(get_current_level() > 0u, "decCurrentLevel : already at minimum resolution level"); + cgogn_message_assert(get_current_level() > 0u, "decCurrentLevel : already at minimum resolution level"); --current_level_ ; } @@ -309,53 +369,34 @@ class IHCMap2_T : protected CMap2_T inline unsigned int get_dart_level(Dart d) const { - return dart_level_[d] ; + return (*dart_level_)[d.index] ; } inline void set_dart_level(Dart d, unsigned int l) { - dart_level_[d] = l ; + (*dart_level_)[d.index] = l ; } /*************************************************** * EDGE ID MANAGEMENT * ***************************************************/ - /** - * Give a new unique id to all the edges of the map - */ - inline void init_edge_ids() - { - id_count_ = 0; - DartMarker marker(*this); - - for (Dart d : Inherit) - { - if(!marker.is_marked(d)) - { - marker.mark_orbit(Edge(d)) ; - edge_id_[d] = id_count_ ; - edge_id_[Inherit::phi2(d)] = id_count_++ ; - } - } - } - /** * Return the next available edge id */ - inline unsigned int get_new_edge_id() const + inline unsigned int get_new_edge_id() { return id_count_++ ; } inline unsigned int get_edge_id(Dart d) const { - return edge_id_[d] ; + return (*edge_id_)[d.index] ; } inline void set_edge_id(Dart d, unsigned int i) { - edge_id_[d] = i ; + (*edge_id_)[d.index] = i ; } inline unsigned int get_tri_refinement_edge_id(Dart d) const @@ -392,22 +433,22 @@ class IHCMap2_T : protected CMap2_T return 0u; } -}; -template -struct IHCMap2TopoTraits -{ - static const int PRIM_SIZE = 1; - typedef IHCMap2_T> CONCRETE; + inline void inc_nb_darts(unsigned int level) + { + nb_darts_per_level[level]++; + } }; -struct IHCMap2DataTraits +template +struct IHCMap2Type { - static const unsigned int CHUNK_SIZE = 4096; + typedef IHCMap2_T> TYPE; }; -using IHCMap2 = IHCMap2_T>; +template +using IHCMap2 = IHCMap2_T>; } // namespace cgogn -#endif // CORE_CPH_IHCMAP2_H_ \ No newline at end of file +#endif // CORE_CPH_IHCMAP2_H_ From fb5170faa43a3764e99c2a3ca1e1745abc5b2f03 Mon Sep 17 00:00:00 2001 From: Lionel Untereiner Date: Tue, 19 Jan 2016 21:07:51 +0100 Subject: [PATCH 015/402] adding cut_edge and split_face topo operations --- cgogn/core/cph/ihcmap2.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/cgogn/core/cph/ihcmap2.h b/cgogn/core/cph/ihcmap2.h index e48e93d2..b517202d 100644 --- a/cgogn/core/cph/ihcmap2.h +++ b/cgogn/core/cph/ihcmap2.h @@ -230,6 +230,27 @@ class IHCMap2_T : public CMap2_T return d ; } + inline Vertex cut_edge(Edge e) + { + Dart dd = phi2(e); + unsigned int e_id = get_edge_id(e) ; + + Vertex v = Inherit::cut_edge(e); + + set_edge_id(phi1(e), e_id) ; + set_edge_id(phi1(dd), e_id) ; + + return v; + } + + inline void split_face(Face d, Face e) + { + Inherit::split_face(d, e); + + foreach_dart_of_orbit(d, [this, e_id] (Dart dit) { set_edge_id(dit, e_id); }); + foreach_dart_of_orbit(e, [this, e_id] (Dart dit) { set_edge_id(dit, e_id); }); + } + protected: /******************************************************************************* @@ -307,6 +328,9 @@ class IHCMap2_T : public CMap2_T template inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const { + static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || + ORBIT == Orbit::PHI2 || ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21, + "Orbit not supported in a CMap2"); switch (ORBIT) { case Orbit::DART: foreach_dart_of_DART(c, f); break; From 20956b2a3cc220e01e4a64ace924542912225760 Mon Sep 17 00:00:00 2001 From: Lionel Untereiner Date: Tue, 19 Jan 2016 21:08:25 +0100 Subject: [PATCH 016/402] adding embedded opertions for ihcmap2 --- cgogn/core/cph/ihcmap2_modifier.h | 114 ++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 cgogn/core/cph/ihcmap2_modifier.h diff --git a/cgogn/core/cph/ihcmap2_modifier.h b/cgogn/core/cph/ihcmap2_modifier.h new file mode 100644 index 00000000..bd345cab --- /dev/null +++ b/cgogn/core/cph/ihcmap2_modifier.h @@ -0,0 +1,114 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef CORE_CPH_IHCMAP_MODIFIER_H_ +#define CORE_CPH_IHCMAP_MODIFIER_H_ + +#include + +namespace cgogn +{ + +template +class IHCMap2Modifier_T +{ +public: + + using Self = IHCMap2Modifier_T; + using IHCMap2 = cgogn::IHCMap2; + + template + using ChunkArrayContainer = typename IHCMap2::template ChunkArrayContainer; + + inline IHCMap2Modifier_T(IHCMap2& ihmap): ihmap_(ihmap) + {} + IHCMap2Modifier_T(const Self&) = delete; + IHCMap2Modifier_T(Self&&) = delete; + Self& operator=(const Self&) = delete; + Self& operator=(Self&&) = delete; + inline ~IHCMap2Modifier_T() = default; + +public: + + inline Vertex cut_edge(Edge d) + { + Vertex v = ihmap_.cut_edge(e); + + if(ihmap_.is_orbit_embedded()) + { + ihmap_.init_orbit_embedding(v, ihmap_.add_attribute_element()); + ihmap_.init_orbit_embedding(ihmap_.phi1(ihmap_.phi2(v)), ihmap_.add_attribute_element()); + } + + if(ihmap_.is_orbit_embedded()) + { + ihmap_.init_orbit_embedding(v, ihmap_.add_attribute_element()); + } + + if(ihmap_.is_orbit_embedded()) + { + ihmap_.init_orbit_embedding(ihmap_.phi2(d), ihmap_.get_embedding(d)) ; + set_orbit_embedding(); + + set_orbit_embeddingOnNewCell(nd, this->template getEmbedding()) ; + Algo::Topo::copyCellAttributes(*this, nd, d) ; + } + + if(ihmap_.is_orbit_embedded()) + { + ihmap_.init_embedding(v, ihmap_.get_embedding(d)) ; + Dart e = ihmap_.phi2(v) ; + ihmap_.init_embedding(ihmap_.phi1(e), ihmap_.getEmbedding(e)) ; + } + + if(ihmap_.is_orbit_embedded()) + { + + } + + return v; + } + + inline void split_face(Face d, Face e) + { + ihmap_.split_face(d, e); + + if(ihmap_.is_orbit_embedded()) + { + unsigned int cur = m_curLevel ; + m_curLevel = m_maxLevel ; + ihmap_.set_orbit_embedding(d, ihmap_.get_embedding(d)) ; + ihmap_.set_orbit_embedding(e, ihmap_.get_embedding(e)) ; + m_curLevel = cur ; + } + } + +private: + IHCMap2& ihmap_; + +}; + +} // namespace cgogn + + +#endif // CORE_CPH_IHCMAP_MODIFIER_H_ \ No newline at end of file From e22e102dc1e189beb7c12fef154df4e9b97e07e3 Mon Sep 17 00:00:00 2001 From: Lionel Untereiner Date: Mon, 1 Feb 2016 21:55:53 +0100 Subject: [PATCH 017/402] changes the hierarchy of cph --- cgogn/core/CMakeLists.txt | 1 + cgogn/core/cph/ihcmap2.h | 215 +++--------------- .../{ihcmap2_modifier.h => ihcmap2_regular.h} | 82 ++----- cgogn/core/cph/ihcmap_base.h | 187 +++++++++++++++ cgogn/core/examples/CMakeLists.txt | 2 +- 5 files changed, 244 insertions(+), 243 deletions(-) rename cgogn/core/cph/{ihcmap2_modifier.h => ihcmap2_regular.h} (50%) create mode 100644 cgogn/core/cph/ihcmap_base.h diff --git a/cgogn/core/CMakeLists.txt b/cgogn/core/CMakeLists.txt index 97bb8184..e3d72900 100644 --- a/cgogn/core/CMakeLists.txt +++ b/cgogn/core/CMakeLists.txt @@ -29,6 +29,7 @@ set(HEADER_FILES cph/attribute_handler_cph.h cph/ihcmap2.h + cph/cph.h utils/assert.h utils/buffers.h diff --git a/cgogn/core/cph/ihcmap2.h b/cgogn/core/cph/ihcmap2.h index b517202d..dde34243 100644 --- a/cgogn/core/cph/ihcmap2.h +++ b/cgogn/core/cph/ihcmap2.h @@ -26,12 +26,12 @@ #include +#include namespace cgogn { -<<<<<<< HEAD template class ContainerCPHBrowser : public ContainerBrowser { @@ -55,17 +55,17 @@ class ContainerCPHBrowser : public ContainerBrowser }; template -class IHCMap2_T : public CMap2_T +class IHCMap2_T : public CMap2_T, public CPH { public: - typedef CMap2_T Inherit; + typedef CMap2_T Inherit_CMAP; + typedef CPH Inherit_CPH; typedef IHCMap2_T Self; friend typename Self::Inherit; friend typename Inherit::Inherit; - friend class DartMarker_T; static const Orbit DART = Orbit::DART; @@ -101,69 +101,51 @@ class IHCMap2_T : public CMap2_T using DartMarkerStore = typename cgogn::DartMarkerStore; protected: - unsigned int current_level_; - unsigned int maximum_level_; - unsigned int id_count_; - - // DartAttributeHandler dart_level_ ; - // DartAttributeHandler edge_id_ ; - ChunkArray* dart_level_; - ChunkArray* edge_id_; - ContainerCPHBrowser, Self>* cph_browser; - std::vector nb_darts_per_level; - inline void init() { - dart_level_ = this->topology_.template add_attribute("dartLevel") ; - edge_id_ = this->topology_.template add_attribute("edgeId"); - - cph_browser = new ContainerCPHBrowser, Self>(this->topology_, this); - + cph_browser = new ContainerCPHBrowser, Self>(this->topology_, this); this->topology_.set_current_browser(cph_browser); + + // Inherit_CPH::new_level_darts(); } public: - IHCMap2_T() : Inherit(), - current_level_(0), - maximum_level_(0), - id_count_(0) + IHCMap2_T() : Inherit_MAP(), Inherit_CPH(this->topology_) { - init(); + init(); } ~IHCMap2_T() override - { - this->topology_.template remove_attribute(dart_level_); - this->topology_.template remove_attribute(edge_id_); - } + {} IHCMap2_T(Self const&) = delete; IHCMap2_T(Self &&) = delete; Self& operator=(Self const&) = delete; Self& operator=(Self &&) = delete; +protected: /******************************************************************************* * Basic topological operations *******************************************************************************/ inline Dart phi1(Dart d) const { - cgogn_message_assert(get_dart_level(d) <= get_current_level(), "Access to a dart introduced after current level") ; + cgogn_message_assert(Inherit_CPH::get_dart_level(d) <= Inherit_CPH::get_current_level(), "Access to a dart introduced after current level") ; bool finished = false ; unsigned int edge_id = get_edge_id(d) ; Dart it = d ; do { - it = Inherit::phi1(it) ; - if(get_dart_level(it) <= get_current_level()) + it = Inherit_CMAP::phi1(it) ; + if(Inherit_CPH::get_dart_level(it) <= Inherit_CPH::get_current_level()) finished = true ; else { - while(get_edge_id(it) != edge_id) - it = Inherit::phi1(Inherit::phi2(it)) ; + while(Inherit_CPH::get_edge_id(it) != edge_id) + it = Inherit_CMAP::phi1(Inherit_CMAP::phi2(it)) ; } } while(!finished) ; return it ; @@ -171,20 +153,20 @@ class IHCMap2_T : public CMap2_T inline Dart phi_1(Dart d) const { - cgogn_message_assert(get_dart_level(d) <= get_current_level(), "Access to a dart introduced after current level") ; + cgogn_message_assert(Inherit_CPH::get_dart_level(d) <= Inherit_CPH::get_current_level(), "Access to a dart introduced after current level") ; bool finished = false ; - Dart it = Inherit::phi_1(d) ; - unsigned int edge_id = get_edge_id(d) ; + Dart it = Inherit_CMAP::phi_1(d) ; + unsigned int edge_id = Inherit_CPH::get_edge_id(d) ; do { - if(get_dart_level(it) <= get_current_level()) + if(Inherit_CPH::get_dart_level(it) <= Inherit_CPH::get_current_level()) finished = true ; else { - it = Inherit::phi_1(it) ; - while(get_edge_id(it) != edge_id) - it = Inherit::phi_1(Inherit::phi2(it)) ; + it = Inherit_CMAP::phi_1(it) ; + while(Inherit_CPH::get_edge_id(it) != edge_id) + it = Inherit_CMAP::phi_1(Inherit_CMAP::phi2(it)) ; } } while(!finished) ; return it ; @@ -197,11 +179,11 @@ class IHCMap2_T : public CMap2_T */ inline Dart phi2(Dart d) const { - cgogn_message_assert(get_dart_level(d) <= get_current_level(), "Access to a dart introduced after current level") ; + cgogn_message_assert(Inherit_CPH::get_dart_level(d) <= Inherit_CPH::get_current_level(), "Access to a dart introduced after current level") ; - if(Inherit::phi2(d) == d) + if(Inherit_CMAP::phi2(d) == d) return d; - return Inherit::phi2(Inherit::phi_1(phi1(d))); + return Inherit_CMAP::phi2(Inherit_CMAP::phi_1(phi1(d))); } protected: @@ -212,45 +194,23 @@ class IHCMap2_T : public CMap2_T */ inline Dart add_dart() { - Dart d = Inherit::add_dart(); + Dart d = Inherit_CMAP::add_dart(); - set_edge_id(d, 0); - set_dart_level(d, get_current_level()); + Inherit_CPH::set_edge_id(d, 0); + Inherit_CPH::set_dart_level(d, Inherit_CPH::get_current_level()); // update max level if needed - if(get_current_level() > get_maximum_level()) + if(Inherit_CPH::get_current_level() > Inherit_CPH::get_maximum_level()) { - set_maximum_level(get_current_level()); - nb_darts_per_level.push_back(0); + Inherit_CPH::set_maximum_level(Inherit_CPH::get_current_level()); + // Inherit_CPH::new_level_darts(); } -// inc_nb_darts(get_current_level()); +// Inherit_CPH::inc_nb_darts(get_current_level()); - return d ; } - inline Vertex cut_edge(Edge e) - { - Dart dd = phi2(e); - unsigned int e_id = get_edge_id(e) ; - - Vertex v = Inherit::cut_edge(e); - - set_edge_id(phi1(e), e_id) ; - set_edge_id(phi1(dd), e_id) ; - - return v; - } - - inline void split_face(Face d, Face e) - { - Inherit::split_face(d, e); - - foreach_dart_of_orbit(d, [this, e_id] (Dart dit) { set_edge_id(dit, e_id); }); - foreach_dart_of_orbit(e, [this, e_id] (Dart dit) { set_edge_id(dit, e_id); }); - } - protected: /******************************************************************************* @@ -290,7 +250,7 @@ class IHCMap2_T : public CMap2_T do { f(it); - it = Inherit::phi2(Inherit::phi_1(it)); + it = Inherit_CMAP::phi2(Inherit_CMAP::phi_1(it)); } while (it != d); } @@ -357,113 +317,6 @@ class IHCMap2_T : public CMap2_T } while (it != d) ; return count ; } - - /*************************************************** - * LEVELS MANAGEMENT * - ***************************************************/ - - inline unsigned int get_current_level() const - { - return current_level_ ; - } - - inline void set_current_level(unsigned int l) - { - current_level_ = l ; - } - - inline void inc_current_level() - { - cgogn_message_assert(get_current_level() < get_maximum_level(), "incCurrentLevel : already at maximum resolution level"); - ++current_level_ ; - } - - inline void dec_current_level() - { - cgogn_message_assert(get_current_level() > 0u, "decCurrentLevel : already at minimum resolution level"); - --current_level_ ; - } - - inline unsigned int get_maximum_level() const - { - return maximum_level_ ; - } - - inline void set_maximum_level(unsigned int l) - { - maximum_level_ = l; - } - - inline unsigned int get_dart_level(Dart d) const - { - return (*dart_level_)[d.index] ; - } - - inline void set_dart_level(Dart d, unsigned int l) - { - (*dart_level_)[d.index] = l ; - } - - /*************************************************** - * EDGE ID MANAGEMENT * - ***************************************************/ - - /** - * Return the next available edge id - */ - inline unsigned int get_new_edge_id() - { - return id_count_++ ; - } - - inline unsigned int get_edge_id(Dart d) const - { - return (*edge_id_)[d.index] ; - } - - inline void set_edge_id(Dart d, unsigned int i) - { - (*edge_id_)[d.index] = i ; - } - - inline unsigned int get_tri_refinement_edge_id(Dart d) const - { - unsigned int d_id = get_edge_id(phi_1(d)); - unsigned int e_id = get_edge_id(phi1(d)); - - unsigned int id = d_id + e_id; - - if(id == 0u) - return 1u; - else if(id == 1u) - return 2u; - else if(id == 2u) - { - if(d_id == e_id) - return 0u; - else - return 1u; - } - - //else if(id == 3) - return 0u; - } - - inline unsigned int get_quad_refinement_edge_id(Dart d) const - { - unsigned int e_id = get_edge_id(phi1(d)); - - if(e_id == 0u) - return 1u; - - //else if(e_id == 1) - return 0u; - } - - inline void inc_nb_darts(unsigned int level) - { - nb_darts_per_level[level]++; - } }; template diff --git a/cgogn/core/cph/ihcmap2_modifier.h b/cgogn/core/cph/ihcmap2_regular.h similarity index 50% rename from cgogn/core/cph/ihcmap2_modifier.h rename to cgogn/core/cph/ihcmap2_regular.h index bd345cab..477febca 100644 --- a/cgogn/core/cph/ihcmap2_modifier.h +++ b/cgogn/core/cph/ihcmap2_regular.h @@ -21,8 +21,8 @@ * * *******************************************************************************/ -#ifndef CORE_CPH_IHCMAP_MODIFIER_H_ -#define CORE_CPH_IHCMAP_MODIFIER_H_ +#ifndef CORE_CPH_IHCMAP2_REGULAR_H_ +#define CORE_CPH_IHCMAP2_REGULAR_H_ #include @@ -30,85 +30,45 @@ namespace cgogn { template -class IHCMap2Modifier_T +class IHCMap2Regular : IHCMap2 { public: - using Self = IHCMap2Modifier_T; - using IHCMap2 = cgogn::IHCMap2; + typedef IHCMap2 Inherit; + typedef IHCMap2Regular Self; - template - using ChunkArrayContainer = typename IHCMap2::template ChunkArrayContainer; - inline IHCMap2Modifier_T(IHCMap2& ihmap): ihmap_(ihmap) + IHCMap2Regular() : Inherit() {} - IHCMap2Modifier_T(const Self&) = delete; - IHCMap2Modifier_T(Self&&) = delete; + + ~IHCMap2Regular() override + {} + + IHCMap2Regular(const Self&) = delete; + IHCMap2Regular(Self&&) = delete; Self& operator=(const Self&) = delete; Self& operator=(Self&&) = delete; - inline ~IHCMap2Modifier_T() = default; + inline ~IHCMap2Regular() = default; public: - inline Vertex cut_edge(Edge d) + inline void add_triangular_level() { - Vertex v = ihmap_.cut_edge(e); - - if(ihmap_.is_orbit_embedded()) - { - ihmap_.init_orbit_embedding(v, ihmap_.add_attribute_element()); - ihmap_.init_orbit_embedding(ihmap_.phi1(ihmap_.phi2(v)), ihmap_.add_attribute_element()); - } - - if(ihmap_.is_orbit_embedded()) - { - ihmap_.init_orbit_embedding(v, ihmap_.add_attribute_element()); - } - - if(ihmap_.is_orbit_embedded()) - { - ihmap_.init_orbit_embedding(ihmap_.phi2(d), ihmap_.get_embedding(d)) ; - set_orbit_embedding(); - - set_orbit_embeddingOnNewCell(nd, this->template getEmbedding()) ; - Algo::Topo::copyCellAttributes(*this, nd, d) ; - } - - if(ihmap_.is_orbit_embedded()) - { - ihmap_.init_embedding(v, ihmap_.get_embedding(d)) ; - Dart e = ihmap_.phi2(v) ; - ihmap_.init_embedding(ihmap_.phi1(e), ihmap_.getEmbedding(e)) ; - } - - if(ihmap_.is_orbit_embedded()) - { - - } - - return v; + } - inline void split_face(Face d, Face e) + inline void add_quadrangular_level() { - ihmap_.split_face(d, e); - - if(ihmap_.is_orbit_embedded()) - { - unsigned int cur = m_curLevel ; - m_curLevel = m_maxLevel ; - ihmap_.set_orbit_embedding(d, ihmap_.get_embedding(d)) ; - ihmap_.set_orbit_embedding(e, ihmap_.get_embedding(e)) ; - m_curLevel = cur ; - } + } -private: - IHCMap2& ihmap_; + inline void add_mixed_level() + { + } }; } // namespace cgogn -#endif // CORE_CPH_IHCMAP_MODIFIER_H_ \ No newline at end of file +#endif // CORE_CPH_IHCMAP2_REGULAR_H_ \ No newline at end of file diff --git a/cgogn/core/cph/ihcmap_base.h b/cgogn/core/cph/ihcmap_base.h new file mode 100644 index 00000000..4ff6a97a --- /dev/null +++ b/cgogn/core/cph/ihcmap_base.h @@ -0,0 +1,187 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef CORE_CPH_CPH_H_ +#define CORE_CPH_CPH_H_ + +#include +#include + +namespace cgogn +{ + +template +class IHCMapBase +{ + typedef IHCMapBase Self; + + template + using ChunkArray = cgogn::ChunkArray; + template + using ChunkArrayContainer = cgogn::ChunkArrayContainer; + +protected: + unsigned int current_level_; + unsigned int maximum_level_; + + // DartAttributeHandler dart_level_ ; + // DartAttributeHandler edge_id_ ; + ChunkArray* dart_level_; + ChunkArray* edge_id_; + + std::vector nb_darts_per_level; + + const ChunkArrayContainer& topology_; + +public: + IHCMapBase(const ChunkArrayContainer& topology): + topology_(topology), + current_level_(0), + maximum_level_(0) + { + init(); + } + + ~IHCMapBase() + { + topology_.remove_attribute(dart_level_); + topology_.remove_attribute(edge_id_); + } + + IHCMapBase(Self const&) = delete; + IHCMapBase(Self &&) = delete; + Self& operator=(Self const&) = delete; + Self& operator=(Self &&) = delete; + +protected: + + void init() + { + dart_level_ = topology_.add_attribute("dartLevel") ; + edge_id_ = topology_.add_attribute("edgeId"); + } + + /*************************************************** + * LEVELS MANAGEMENT * + ***************************************************/ + + inline unsigned int get_current_level() const + { + return current_level_ ; + } + + inline void set_current_level(unsigned int l) + { + current_level_ = l ; + } + + inline unsigned int get_maximum_level() const + { + return maximum_level_ ; + } + + inline void set_maximum_level(unsigned int l) + { + maximum_level_ = l; + } + + inline unsigned int get_dart_level(Dart d) const + { + return (*dart_level_)[d.index] ; + } + + inline void set_dart_level(Dart d, unsigned int l) + { + (*dart_level_)[d.index] = l ; + } + + /*************************************************** + * EDGE ID MANAGEMENT * + ***************************************************/ + + inline unsigned int get_edge_id(Dart d) const + { + return (*edge_id_)[d.index] ; + } + + inline void set_edge_id(Dart d, unsigned int i) + { + (*edge_id_)[d.index] = i ; + } + + inline unsigned int get_tri_refinement_edge_id(Dart d, Dart e) const + { + unsigned int d_id = get_edge_id(d); + unsigned int e_id = get_edge_id(e); + + // unsigned int d_id = get_edge_id(phi_1(d)); + // unsigned int e_id = get_edge_id(phi1(d)); + + unsigned int id = d_id + e_id; + + if(id == 0u) + return 1u; + else if(id == 1u) + return 2u; + else if(id == 2u) + { + if(d_id == e_id) + return 0u; + else + return 1u; + } + + //else if(id == 3) + return 0u; + } + + inline unsigned int get_quad_refinement_edge_id(Dart d) const + { + // unsigned int e_id = get_edge_id(phi1(d)); + unsigned int e_id = get_edge_id(d); + + + if(e_id == 0u) + return 1u; + + //else if(e_id == 1) + return 0u; + } + + inline void inc_nb_darts(unsigned int level) + { + cgogn_message_assert(level < get_maximum_level(), "inc_nb_darts : already at maximum resolution level"); + nb_darts_per_level[level]++; + } + + inline void new_level_darts() + { + nb_darts_per_level.push_back(0); + } + +}; + +} // namespace cgogn + + +#endif // CORE_CPH_CPH_H_ \ No newline at end of file diff --git a/cgogn/core/examples/CMakeLists.txt b/cgogn/core/examples/CMakeLists.txt index 4baf3674..0e99a93f 100644 --- a/cgogn/core/examples/CMakeLists.txt +++ b/cgogn/core/examples/CMakeLists.txt @@ -10,4 +10,4 @@ add_definitions("-DCGOGN_TEST_MESHES_PATH=${CGOGN_TEST_MESHES_PATH}") add_subdirectory(chunk_array) add_subdirectory(map) -add_subdirectory(cph) \ No newline at end of file +# add_subdirectory(cph) \ No newline at end of file From 7a894493eead785da6346acba307a5fa5938efc3 Mon Sep 17 00:00:00 2001 From: Lionel Untereiner Date: Tue, 2 Feb 2016 08:49:44 +0100 Subject: [PATCH 018/402] adding regular & adaptive CPH2 --- cgogn/core/cph/ihcmap2_adaptive.h | 227 ++++++++++++++++++++++++++++++ cgogn/core/cph/ihcmap2_regular.h | 3 +- 2 files changed, 228 insertions(+), 2 deletions(-) create mode 100644 cgogn/core/cph/ihcmap2_adaptive.h diff --git a/cgogn/core/cph/ihcmap2_adaptive.h b/cgogn/core/cph/ihcmap2_adaptive.h new file mode 100644 index 00000000..9343a6ba --- /dev/null +++ b/cgogn/core/cph/ihcmap2_adaptive.h @@ -0,0 +1,227 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef CORE_CPH_IHCMAP2_ADAPTIVE_H_ +#define CORE_CPH_IHCMAP2_ADAPTIVE_H_ + +#include + +namespace cgogn +{ + +template +class IHCMap2Adaptive : IHCMap2 +{ +public: + typedef IHCMap2 Inherit; + typedef IHCMap2Adaptive Self; + + + IHCMap2Adaptive() : Inherit() + {} + + ~IHCMap2Adaptive() override + {} + + IHCMap2Adaptive(const Self&) = delete; + IHCMap2Adaptive(Self&&) = delete; + Self& operator=(const Self&) = delete; + Self& operator=(Self&&) = delete; + inline ~IHCMap2Adaptive() = default; + +public: + /*************************************************** + * CELLS INFORMATION * + ***************************************************/ + + /** + * Return the level of the edge of d in the current level map + */ + unsigned int edge_level(Dart d) + { + cgogn_message_assert(Inherit::getDartLevel(d) <= Inherit::getCurrentLevel(), "Access to a dart introduced after current level"); + unsigned int ld = Inherit::getDartLevel(d); + // unsigned int ldd = m_dartLevel[phi2(d)] ; // the level of an edge is the maximum of the + unsigned int ldd = Inherit::getDartLevel(Inherit::phi1(d)); + return ld < ldd ? ldd : ld ; + } + + /** + * Return the level of the face of d in the current level map + */ + unsigned int face_level(Dart d) + { + cgogn_message_assert(Inherit::getDartLevel(d) <= Inherit::getCurrentLevel(), "Access to a dart introduced after current level") ; + + if(Inherit::getCurrentLevel() == 0) + return 0 ; + } + + /** + * Given the face of d in the current level map, + * return a level 0 dart of its origin face + */ + Dart face_origin(Dart d) + { + cgogn_message_assert(Inherit::getDartLevel(d) <= Inherit::getCurrentLevel(), "Access to a dart introduced after current level") ; + unsigned int cur = Inherit::getCurrentLevel() ; + Dart p = d ; + unsigned int pLevel = Inherit::getDartLevel(p) ; + while(pLevel > 0) + { + p = faceOldestDart(p) ; + pLevel = Inherit::getDartLevel(p) ; + Inherit::setCurrentLevel(pLevel) ; + } + Inherit::setCurrentLevel(cur) ; + return p ; + } + + /** + * Return the oldest dart of the face of d in the current level map + */ + Dart face_oldest_dart(Dart d) + { + + } + + /** + * Return true if the edge of d in the current level map + * has already been subdivided to the next level + */ + bool edge_is_subdivided(Dart d) + { + cgogn_message_assert(Inherit::getDartLevel(d) <= Inherit::getCurrentLevel(), "Access to a dart introduced after current level") ; + + if(Inherit::getCurrentLevel() == Inherit::getMaxLevel()) + return false ; + + // Dart d2 = Inherit::phi2(d) ; + Dart d1 = Inherit::phi1(d) ; + Inherit::incCurrentLevel() ; + // Dart d2_l = phi2(d) ; + Dart d1_l = Inherit::phi1(d) ; + Inherit::decCurrentLevel(); + if(d1 != d1_l) + return true ; + else + return false ; + } + + /** + * Return true if the edge of d in the current level map + * is subdivided to the next level, + * none of its resulting edges is in turn subdivided to the next level + * and the middle vertex is of degree 2 + */ + bool edge_can_be_coarsened(Dart d) ; + + /** + * Return true if the face of d in the current level map + * has already been subdivided to the next level + */ + bool face_is_subdivided(Dart d) ; + + /** + * Return true if the face of d in the current level map + * is subdivided to the next level + * and none of its resulting faces is in turn subdivided to the next level + */ + bool face_is_subdivided_once(Dart d) ; + +protected: + /*************************************************** + * SUBDIVISION * + ***************************************************/ + + /** + * subdivide the edge of d to the next level + */ + void subdivideEdge(Dart d) + { + cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), "subdivideEdge : called with a dart inserted after current level") ; + cgogn_message_assert(!edge_is_subdivided(d), "Trying to subdivide an already subdivided edge") ; + + unsigned int eLevel = edge_level(d) ; + + unsigned int cur = Inherit::get_current_level() ; + Inherit::set_current_level(eLevel) ; + + Dart dd = Inherit::phi2(d) ; + + Inherit::set_current_level(eLevel + 1) ; + + Inherit::cut_edge(d) ; + unsigned int eId = Inherit::get_edge_id(d) ; + Inherit::set_edge_id(Inherit::phi1(d), eId) ; + Inherit::set_edge_id(Inherit::phi1(dd), eId) ; + + if(Inherit::template is_orbit_embedded()) + { + (*edgeVertexFunctor)(Inherit::phi1(d)) ; + } + + //quid des autres cellules ? + (*edgeEdgeFunctor)(Inherit::phi1(d)); + (*edgeEdgeFunctor)(d); + + + Inherit::set_current_level(cur) ; + } + + /** + * coarsen the edge of d from the next level + */ + void coarsenEdge(Dart d) + { + cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), "coarsenEdge : called with a dart inserted after current level") ; + cgogn_message_assert(edge_can_be_coarsened(d), "Trying to coarsen an edge that can not be coarsened") ; + + + unsigned int cur = Inherit::get_current_level() ; + // Dart e = Inherit::phi2(d) ; + Inherit::set_current_level(cur + 1) ; + // unsigned int dl = Inherit::get_dart_level(e) ; + // Inherit::set_dart_level(Inherit::phi1(e), dl) ; + // Inherit::collapseEdge(e) ; + Inherit::uncut_edge(d) ; + Inherit::set_current_level(cur) ; + } + +public: + /** + * subdivide the face of d to the next level + */ + unsigned int subdivideFace(Dart d, bool triQuad = true, bool OneLevelDifference = true); + + /** + * coarsen the face of d from the next level + */ + void coarsenFace(Dart d) ; + + +}; + +} // namespace cgogn + +#endif // CORE_CPH_IHCMAP2_ADAPTIVE_H_ diff --git a/cgogn/core/cph/ihcmap2_regular.h b/cgogn/core/cph/ihcmap2_regular.h index 477febca..d2955dd2 100644 --- a/cgogn/core/cph/ihcmap2_regular.h +++ b/cgogn/core/cph/ihcmap2_regular.h @@ -70,5 +70,4 @@ class IHCMap2Regular : IHCMap2 } // namespace cgogn - -#endif // CORE_CPH_IHCMAP2_REGULAR_H_ \ No newline at end of file +#endif // CORE_CPH_IHCMAP2_REGULAR_H_ From afedfa12d5d7a7f84ff6de68e5ca06b6bdebc073 Mon Sep 17 00:00:00 2001 From: lionel untereiner Date: Tue, 2 Feb 2016 14:09:39 +0100 Subject: [PATCH 019/402] adding an example of regular subdivision for cph2 adding adaptive cph2 --- cgogn/core/CMakeLists.txt | 6 +- cgogn/core/cph/ihcmap2.h | 23 +- cgogn/core/cph/ihcmap2_adaptive.h | 454 +++++++++++++++++++++---- cgogn/core/cph/ihcmap2_regular.h | 193 ++++++++++- cgogn/core/cph/ihcmap_base.h | 25 +- cgogn/core/examples/CMakeLists.txt | 2 +- cgogn/core/examples/cph/CMakeLists.txt | 9 + cgogn/core/examples/cph/cph2.cpp | 78 +++++ 8 files changed, 688 insertions(+), 102 deletions(-) create mode 100644 cgogn/core/examples/cph/CMakeLists.txt create mode 100644 cgogn/core/examples/cph/cph2.cpp diff --git a/cgogn/core/CMakeLists.txt b/cgogn/core/CMakeLists.txt index e3d72900..765161a4 100644 --- a/cgogn/core/CMakeLists.txt +++ b/cgogn/core/CMakeLists.txt @@ -27,9 +27,11 @@ set(HEADER_FILES container/chunk_array.h container/chunk_stack.h - cph/attribute_handler_cph.h + cph/attribute_handler_cph.h + cph/ihcmap_base.h cph/ihcmap2.h - cph/cph.h + cph/ihcmap2_adaptive.h + cph/ihcmap2_regular.h utils/assert.h utils/buffers.h diff --git a/cgogn/core/cph/ihcmap2.h b/cgogn/core/cph/ihcmap2.h index dde34243..5dc6a536 100644 --- a/cgogn/core/cph/ihcmap2.h +++ b/cgogn/core/cph/ihcmap2.h @@ -26,7 +26,7 @@ #include -#include // #include namespace cgogn @@ -55,16 +55,16 @@ class ContainerCPHBrowser : public ContainerBrowser }; template -class IHCMap2_T : public CMap2_T, public CPH +class IHCMap2_T : public CMap2_T, public IHCMapBase { public: typedef CMap2_T Inherit_CMAP; - typedef CPH Inherit_CPH; + typedef IHCMapBase Inherit_CPH; typedef IHCMap2_T Self; - friend typename Self::Inherit; - friend typename Inherit::Inherit; + friend typename Self::Inherit_CMAP; +// friend typename Inherit::Inherit; friend class DartMarker_T; @@ -80,12 +80,12 @@ class IHCMap2_T : public CMap2_T, public CPH typedef Cell Volume; template - using ChunkArray = typename Inherit::template ChunkArray; + using ChunkArray = typename Inherit_CMAP::template ChunkArray; template - using ChunkArrayContainer = typename Inherit::template ChunkArrayContainer; + using ChunkArrayContainer = typename Inherit_CMAP::template ChunkArrayContainer; template - using AttributeHandler = typename Inherit::template AttributeHandler; + using AttributeHandler = typename Inherit_CMAP::template AttributeHandler; template using DartAttributeHandler = AttributeHandler; template @@ -112,7 +112,7 @@ class IHCMap2_T : public CMap2_T, public CPH } public: - IHCMap2_T() : Inherit_MAP(), Inherit_CPH(this->topology_) + IHCMap2_T() : Inherit_CMAP(), Inherit_CPH(this->topology_) { init(); } @@ -135,7 +135,7 @@ class IHCMap2_T : public CMap2_T, public CPH cgogn_message_assert(Inherit_CPH::get_dart_level(d) <= Inherit_CPH::get_current_level(), "Access to a dart introduced after current level") ; bool finished = false ; - unsigned int edge_id = get_edge_id(d) ; + unsigned int edge_id = Inherit_CPH::get_edge_id(d) ; Dart it = d ; do { @@ -186,8 +186,7 @@ class IHCMap2_T : public CMap2_T, public CPH return Inherit_CMAP::phi2(Inherit_CMAP::phi_1(phi1(d))); } -protected: - +public: /** * \brief add a Dart in the map * @return the new Dart diff --git a/cgogn/core/cph/ihcmap2_adaptive.h b/cgogn/core/cph/ihcmap2_adaptive.h index 9343a6ba..14f5ba35 100644 --- a/cgogn/core/cph/ihcmap2_adaptive.h +++ b/cgogn/core/cph/ihcmap2_adaptive.h @@ -56,25 +56,74 @@ class IHCMap2Adaptive : IHCMap2 /** * Return the level of the edge of d in the current level map + * \details The level of an edge is the maximum of the levels of + * its darts. As phi1(d) and phi2(d) are from the same level we can + * optimize by checking phi1(d) instead of phi2(d) */ unsigned int edge_level(Dart d) { - cgogn_message_assert(Inherit::getDartLevel(d) <= Inherit::getCurrentLevel(), "Access to a dart introduced after current level"); - unsigned int ld = Inherit::getDartLevel(d); - // unsigned int ldd = m_dartLevel[phi2(d)] ; // the level of an edge is the maximum of the + cgogn_message_assert(Inherit::getDartLevel(d) <= Inherit::getCurrentLevel(), + "Access to a dart introduced after current level"); + + unsigned int ld = Inherit::getDartLevel(d); unsigned int ldd = Inherit::getDartLevel(Inherit::phi1(d)); - return ld < ldd ? ldd : ld ; + return ld < ldd ? ldd : ld; } /** * Return the level of the face of d in the current level map + * \details The level of a face is the minimum of the levels of its edges + * but a specific treatment has to be done in the particular case of a + * face with all neighboring faces are regularly subdivided + * but not the face itself */ unsigned int face_level(Dart d) { - cgogn_message_assert(Inherit::getDartLevel(d) <= Inherit::getCurrentLevel(), "Access to a dart introduced after current level") ; - - if(Inherit::getCurrentLevel() == 0) - return 0 ; + cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), + "Access to a dart introduced after current level"); + + if(Inherit::get_current_level() == 0) + return 0; + + Dart it = d; + Dart old = it; + unsigned int l_old = Inherit::get_dart_level(old); + unsigned int fLevel = edge_level(it); + do + { + it = Inherit::phi1(it); + unsigned int dl = Inherit::get_dart_level(it); + + // compute the oldest dart of the face in the same time + if(dl < l_old) + { + old = it; + l_old = dl; + } + unsigned int l = edge_level(it); + fLevel = l < fLevel ? l : fLevel; + } while(it != d); + + unsigned int cur = Inherit::get_current_level(); + Inherit::set_current_level(fLevel); + + unsigned int nbSubd = 0; + it = old; + unsigned int eId = Inherit::get_edge_id(old); + do + { + ++nbSubd; + it = Inherit::phi1(it); + } while(Inherit::get_edge_id(it) == eId); + + while(nbSubd > 1) + { + nbSubd /= 2; + --fLevel; + } + + Inherit::set_current_level(cur) ; + return fLevel ; } /** @@ -83,18 +132,20 @@ class IHCMap2Adaptive : IHCMap2 */ Dart face_origin(Dart d) { - cgogn_message_assert(Inherit::getDartLevel(d) <= Inherit::getCurrentLevel(), "Access to a dart introduced after current level") ; - unsigned int cur = Inherit::getCurrentLevel() ; - Dart p = d ; - unsigned int pLevel = Inherit::getDartLevel(p) ; + cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), + "Access to a dart introduced after current level"); + + unsigned int cur = Inherit::get_current_level(); + Dart p = d; + unsigned int pLevel = Inherit::get_dart_level(p); while(pLevel > 0) { - p = faceOldestDart(p) ; - pLevel = Inherit::getDartLevel(p) ; - Inherit::setCurrentLevel(pLevel) ; + p = face_oldest_dart(p); + pLevel = Inherit::get_dart_level(p); + Inherit::set_current_level(pLevel); } - Inherit::setCurrentLevel(cur) ; - return p ; + Inherit::set_current_level(cur); + return p; } /** @@ -102,30 +153,52 @@ class IHCMap2Adaptive : IHCMap2 */ Dart face_oldest_dart(Dart d) { - + cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), + "Access to a dart introduced after current level"); + + Dart it = d ; + Dart oldest = it ; + unsigned int l_old = Inherit::get_dart_level(oldest); + do + { + unsigned int l = Inherit::get_dart_level(it); + if(l == 0) + return it; + + if(l < l_old) + // if(l < l_old || (l == l_old && it < oldest)) + { + oldest = it; + l_old = l; + } + it = Inherit::phi1(it); + } while(it != d); + + return oldest; } /** * Return true if the edge of d in the current level map * has already been subdivided to the next level + * As before testing phi2(d) or phi1(d) is the same */ bool edge_is_subdivided(Dart d) { - cgogn_message_assert(Inherit::getDartLevel(d) <= Inherit::getCurrentLevel(), "Access to a dart introduced after current level") ; + cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), + "Access to a dart introduced after current level"); - if(Inherit::getCurrentLevel() == Inherit::getMaxLevel()) + if(Inherit::get_current_level() == Inherit::get_maximum_level()) return false ; - // Dart d2 = Inherit::phi2(d) ; - Dart d1 = Inherit::phi1(d) ; - Inherit::incCurrentLevel() ; - // Dart d2_l = phi2(d) ; - Dart d1_l = Inherit::phi1(d) ; - Inherit::decCurrentLevel(); + Dart d1 = Inherit::phi1(d); + unsigned int cur = Inherit::get_current_level(); + Inherit::set_current_level(cur + 1); + Dart d1_l = Inherit::phi1(d); + Inherit::set_current_level(cur); if(d1 != d1_l) - return true ; + return true; else - return false ; + return false; } /** @@ -134,20 +207,114 @@ class IHCMap2Adaptive : IHCMap2 * none of its resulting edges is in turn subdivided to the next level * and the middle vertex is of degree 2 */ - bool edge_can_be_coarsened(Dart d) ; + bool edge_can_be_coarsened(Dart d) + { + cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), + "Access to a dart introduced after current level"); + + bool subd = false ; + bool subdOnce = true ; + bool degree2 = false ; + if(edge_is_subdivided(d)) + { + subd = true ; + Dart d2 = Inherit::phi2(d) ; + unsigned int cur = Inherit::get_current_level(); + Inherit::set_current_level(cur + 1); + if(Inherit::vertexDegree(Inherit::phi1(d)) == 2) + { + degree2 = true ; + if(edge_is_subdivided(d) || edge_is_subdivided(d2)) + subdOnce = false ; + } + Inherit::set_current_level(cur); + + } + return subd && degree2 && subdOnce ; + } /** * Return true if the face of d in the current level map * has already been subdivided to the next level */ - bool face_is_subdivided(Dart d) ; + bool face_is_subdivided(Dart d) + { + cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), + "Access to a dart introduced after current level"); + + unsigned int fLevel = face_level(d) ; + if(fLevel <= Inherit::get_current_level()) + return false ; + + bool subd = false ; + + unsigned int cur = Inherit::get_current_level(); + Inherit::set_current_level(cur + 1); + if(Inherit::get_dart_level(Inherit::phi1(d)) == Inherit::get_current_level() + && Inherit::get_edge_id(Inherit::phi1(d)) != Inherit::get_edge_id(d)) + subd = true; + Inherit::set_current_level(cur); + + return subd; + } /** * Return true if the face of d in the current level map * is subdivided to the next level * and none of its resulting faces is in turn subdivided to the next level + * \details + * A face whose level in the current level map is lower than the current + * level can not be subdivided to higher levels */ - bool face_is_subdivided_once(Dart d) ; + bool face_is_subdivided_once(Dart d) + { + cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), + "Access to a dart introduced after current level"); + + unsigned int fLevel = face_level(d); + if(fLevel < Inherit::get_current_level()) + return false; + + unsigned int degree = 0 ; + bool subd = false ; + bool subdOnce = true ; + Dart fit = d ; + do + { + unsigned int cur = Inherit::get_current_level(); + Inherit::set_current_level(cur + 1); + if(Inherit::get_dart_level(Inherit::phi1(fit)) == Inherit::get_current_level() + && Inherit::get_edge_id(Inherit::phi1(fit)) != Inherit::get_edge_id(fit)) + { + subd = true ; + unsigned int cur2 = Inherit::get_current_level(); + Inherit::set_current_level(cur2 + 1); + if(Inherit::get_dart_level(Inherit::phi1(fit)) == Inherit::get_current_level() + && Inherit::get_edge_id(m_map.phi1(fit)) != Inherit::get_edge_id(fit)) + subdOnce = false ; + Inherit::set_current_level(cur2); + } + Inherit::set_current_level(cur); + ++degree ; + fit = Inherit::phi1(fit) ; + } while(subd && subdOnce && fit != d) ; + + if(degree == 3 && subd) + { + unsigned int cur = Inherit::get_current_level(); + Inherit::set_current_level(cur + 1); + Dart cf = Inherit::phi2(Inherit::phi1(d)) ; + unsigned int cur2 = Inherit::get_current_level(); + Inherit::set_current_level(cur2 + 1); + if(Inherit::get_dart_level(Inherit::phi1(cf)) == Inherit::get_current_level() + && Inherit::get_edge_id(Inherit::phi1(cf)) != Inherit::get_edge_id(cf)) + subdOnce = false ; + Inherit::set_current_level(cur2); + Inherit::set_current_level(cur); + } + + return subd && subdOnce ; + } protected: /*************************************************** @@ -157,69 +324,220 @@ class IHCMap2Adaptive : IHCMap2 /** * subdivide the edge of d to the next level */ - void subdivideEdge(Dart d) + void subdivide_edge(Dart d) { - cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), "subdivideEdge : called with a dart inserted after current level") ; - cgogn_message_assert(!edge_is_subdivided(d), "Trying to subdivide an already subdivided edge") ; + cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), + "subdivideEdge : called with a dart inserted after current level") ; + cgogn_message_assert(!edge_is_subdivided(d), "Trying to subdivide an already subdivided edge"); - unsigned int eLevel = edge_level(d) ; + unsigned int eLevel = edge_level(d); - unsigned int cur = Inherit::get_current_level() ; - Inherit::set_current_level(eLevel) ; + unsigned int cur = Inherit::get_current_level(); + Inherit::set_current_level(eLevel); - Dart dd = Inherit::phi2(d) ; + Dart dd = Inherit::phi2(d); - Inherit::set_current_level(eLevel + 1) ; + Inherit::set_current_level(eLevel + 1); - Inherit::cut_edge(d) ; - unsigned int eId = Inherit::get_edge_id(d) ; - Inherit::set_edge_id(Inherit::phi1(d), eId) ; - Inherit::set_edge_id(Inherit::phi1(dd), eId) ; + Inherit::cut_edge(d); + unsigned int eId = Inherit::get_edge_id(d); + Inherit::set_edge_id(Inherit::phi1(d), eId); + Inherit::set_edge_id(Inherit::phi1(dd), eId); - if(Inherit::template is_orbit_embedded()) - { - (*edgeVertexFunctor)(Inherit::phi1(d)) ; - } +// if(Inherit::template is_orbit_embedded()) +// { +// (*edgeVertexFunctor)(Inherit::phi1(d)); +// } - //quid des autres cellules ? - (*edgeEdgeFunctor)(Inherit::phi1(d)); - (*edgeEdgeFunctor)(d); +// //quid des autres cellules ? +// (*edgeEdgeFunctor)(Inherit::phi1(d)); +// (*edgeEdgeFunctor)(d); - Inherit::set_current_level(cur) ; + Inherit::set_current_level(cur); } /** * coarsen the edge of d from the next level */ - void coarsenEdge(Dart d) + void coarsen_edge(Dart d) { - cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), "coarsenEdge : called with a dart inserted after current level") ; - cgogn_message_assert(edge_can_be_coarsened(d), "Trying to coarsen an edge that can not be coarsened") ; - - - unsigned int cur = Inherit::get_current_level() ; - // Dart e = Inherit::phi2(d) ; - Inherit::set_current_level(cur + 1) ; - // unsigned int dl = Inherit::get_dart_level(e) ; - // Inherit::set_dart_level(Inherit::phi1(e), dl) ; - // Inherit::collapseEdge(e) ; - Inherit::uncut_edge(d) ; - Inherit::set_current_level(cur) ; + cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), + "coarsenEdge : called with a dart inserted after current level"); + cgogn_message_assert(edge_can_be_coarsened(d), "Trying to coarsen an edge that can not be coarsened"); + + + unsigned int cur = Inherit::get_current_level(); + // Dart e = Inherit::phi2(d); + Inherit::set_current_level(cur + 1); + // unsigned int dl = Inherit::get_dart_level(e); + // Inherit::set_dart_level(Inherit::phi1(e), dl); + // Inherit::collapseEdge(e); + Inherit::uncut_edge(d); + Inherit::set_current_level(cur); } public: /** * subdivide the face of d to the next level */ - unsigned int subdivideFace(Dart d, bool triQuad = true, bool OneLevelDifference = true); + unsigned int subdivide_face(Dart d, bool triQuad = true, bool OneLevelDifference = true) + { + cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), + "coarsenEdge : called with a dart inserted after current level"); + cgogn_message_assert(!face_is_subdivided(d), "Trying to coarsen an edge that can not be coarsened"); + + unsigned int fLevel = face_level(d); + Dart old = face_oldest_dart(d); + + unsigned int cur = Inherit::get_current_level(); + Inherit::set_current_level(fLevel); // go to the level of the face to subdivide its edges + + unsigned int degree = 0; + Dart it = old; + do + { + ++degree; // compute the degree of the face + + if(OneLevelDifference) + { + Dart nf = Inherit::phi2(it); + if(face_level(nf) == fLevel - 1) // check if neighboring faces have to be subdivided first + subdivide_face(nf,triQuad); + } + + if(!edge_is_subdivided(it)) + subdivide_edge(it); // and cut the edges (if they are not already) + it = Inherit::phi1(it); + } while(it != old); + + Inherit::setCurrentLevel(fLevel + 1); // go to the next level to perform face subdivision + + if((degree == 3) && triQuad) // if subdividing a triangle + { + Dart dd = Inherit::phi1(old); + Dart e = Inherit::phi1(dd); +// (*vertexVertexFunctor)(e) ; + + e = Inherit::phi1(e); + Inherit::split_face(dd, e); + + unsigned int id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); + Inherit::set_edge_id(Inherit::phi_1(dd), id); // set the edge id of the inserted + Inherit::set_edge_id(Inherit::phi_1(e), id); // edge to the next available id + + dd = e ; + e = Inherit::phi1(dd); +// (*vertexVertexFunctor)(e); + e = Inherit::phi1(e); + Inherit::split_face(dd, e); + id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); + Inherit::set_edge_id(Inherit::phi_1(dd), id); + Inherit::set_edge_id(Inherit::phi_1(e), id); + + dd = e ; + e = Inherit::phi1(dd); +// (*vertexVertexFunctor)(e); + e = Inherit::phi1(e); + Inherit::split_face(dd, e); + id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); + Inherit::set_edge_id(Inherit::phi_1(dd), id); + Inherit::set_edge_id(Inherit::phi_1(e), id); + } + else // if subdividing a polygonal face + { + Dart dd = Inherit::phi1(old); + Dart next = m_map.phi1(dd); +// (*vertexVertexFunctor)(next); + next = Inherit::phi1(next); + Inherit::splitFace(dd, next); // insert a first edge + Dart ne = Inherit::phi2(Inherit::phi_1(dd)); + Dart ne2 = Inherit::phi2(ne); + Inherit::cut_edge(ne); // cut the new edge to insert the central vertex + + unsigned int id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(ne))); + Inherit::set_edge_id(ne, id); + Inherit::set_edge_id(Inherit::phi2(ne), id); // set the edge id of the inserted + + id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(ne2)); + Inherit::set_edge_id(ne2, id); // edges to the next available ids + Inherit::set_edge_id(Inherit::phi2(ne2), id); + + + dd = Inherit::phi1(next); +// (*vertexVertexFunctor)(dd); + dd = Inherit::phi1(dd); + while(dd != ne) // turn around the face and insert new edges + { // linked to the central vertex + Inherit::splitFace(Inherit::phi1(ne), dd); + Dart nne = Inherit::phi2(Inherit::phi_1(dd)); + + id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(nne))); + Inherit::set_edge_id(nne, id) ; + Inherit::set_edge_id(Inherit::phi2(nne), id); + + dd = Inherit::phi1(dd); +// (*vertexVertexFunctor)(dd); + dd = Inherit::phi1(dd); + } + +// (*faceVertexFunctor)(Inherit::phi1(ne)); + } + + Inherit::set_current_level(cur); + + return fLevel ; + } /** * coarsen the face of d from the next level */ - void coarsenFace(Dart d) ; - - + void coarsen_face(Dart d) + { + cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), + "coarsenEdge : called with a dart inserted after current level"); + cgogn_message_assert(face_is_subdivided_once(d), "Trying to coarsen an edge that can not be coarsened"); + + unsigned int cur = Inherit::get_current_level(); + + unsigned int degree = 0; + Dart fit = d; + do + { + ++degree; + fit = Inherit::phi1(fit); + } while(fit != d); + + if(degree == 3) + { + fit = d ; + do + { + Inherit::set_current_level(cur + 1); + Dart innerEdge = Inherit::phi1(fit); + Inherit::set_current_level(Inherit::get_maximum_level()); + Inherit::merge_faces(innerEdge); + Inherit::set_current_level(cur); + fit = m_map.phi1(fit); + } while(fit != d); + } + else + { + Inherit::set_current_level(cur + 1); + Dart centralV = Inherit::phi1(Inherit::phi1(d)); + Inherit::set_current_level(Inherit::get_maximum_level()); + Inherit::delete_vertex(centralV); + Inherit::set_current_level(cur); + } + + fit = d ; + do + { + if(edge_can_be_coarsened(fit)) + coarsen_edge(fit); + fit = Inherit::phi1(fit); + } while(fit != d); + } }; } // namespace cgogn diff --git a/cgogn/core/cph/ihcmap2_regular.h b/cgogn/core/cph/ihcmap2_regular.h index d2955dd2..aab8a2d3 100644 --- a/cgogn/core/cph/ihcmap2_regular.h +++ b/cgogn/core/cph/ihcmap2_regular.h @@ -30,7 +30,7 @@ namespace cgogn { template -class IHCMap2Regular : IHCMap2 +class IHCMap2Regular : public IHCMap2 { public: @@ -41,9 +41,6 @@ class IHCMap2Regular : IHCMap2 IHCMap2Regular() : Inherit() {} - ~IHCMap2Regular() override - {} - IHCMap2Regular(const Self&) = delete; IHCMap2Regular(Self&&) = delete; Self& operator=(const Self&) = delete; @@ -54,17 +51,205 @@ class IHCMap2Regular : IHCMap2 inline void add_triangular_level() { + unsigned int cur = Inherit::get_current_level() ; + + Inherit::set_current_level(Inherit::get_maximum_level() + 1) ; + + //cut edges + Inherit::template foreach_cell([&] (typename Inherit::Edge e) + { + Dart dd = Inherit::phi2(e); + Inherit::cut_edge(e); + + unsigned int eid = Inherit::get_edge_id(e); + Inherit::set_edge_id(Inherit::phi1(e), eid); + Inherit::set_edge_id(Inherit::phi1(dd), eid); + }); + + //cut faces + Inherit::template foreach_cell([&] (typename Inherit::Face d) + { + Dart old = d ; + + if(Inherit::get_dart_level(old) == Inherit::get_maximum_level()) + old = Inherit::phi1(old) ; + + Dart dd = Inherit::phi1(old) ; + Dart e = Inherit::phi1(Inherit::phi1(dd)) ; + // insert a new edge + Inherit::split_face(dd, e) ; + + unsigned int id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); + Inherit::set_edge_id(Inherit::phi_1(dd), id) ; // set the edge id of the inserted + Inherit::set_edge_id(Inherit::phi_1(e), id) ; // edge to the next available id + + dd = e ; + e = Inherit::phi1(Inherit::phi1(dd)) ; + Inherit::split_face(dd, e) ; + id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); + Inherit::set_edge_id(Inherit::phi_1(dd), id) ; + Inherit::set_edge_id(Inherit::phi_1(e), id) ; + dd = e ; + e = Inherit::phi1(Inherit::phi1(dd)) ; + Inherit::split_face(dd, e) ; + id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); + Inherit::set_edge_id(Inherit::phi_1(dd), id) ; + Inherit::set_edge_id(Inherit::phi_1(e), id) ; + }); + + Inherit::set_current_level(cur) ; } inline void add_quadrangular_level() { + unsigned int cur = Inherit::get_current_level() ; + + Inherit::set_current_level(Inherit::get_maximum_level() + 1) ; + + //cut edges + Inherit::template foreach_cell([&] (typename Inherit::Edge e) + { + Dart dd = Inherit::phi2(e); + Inherit::cut_edge(e); + + unsigned int eid = Inherit::get_edge_id(e); + Inherit::set_edge_id(Inherit::phi1(e), eid); + Inherit::set_edge_id(Inherit::phi1(dd), eid); + }); + + //cut faces + Inherit::template foreach_cell([&] (typename Inherit::Face d) + { + Dart old = d ; + + if(Inherit::get_dart_level(old) == Inherit::get_maximum_level()) + old = Inherit::phi1(old) ; + + Dart dd = Inherit::phi1(old) ; + Dart next = Inherit::phi1(Inherit::phi1(dd)) ; + Inherit::split_face(dd, next) ; // insert a first edge + + Dart ne = Inherit::phi2(Inherit::phi_1(dd)) ; + Dart ne2 = Inherit::phi2(ne) ; + Inherit::cut_edge(ne) ; // cut the new edge to insert the central vertex + + unsigned int id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(ne))); + Inherit::set_edge_id(ne, id) ; + Inherit::set_edge_id(Inherit::phi2(ne), id) ; // set the edge id of the inserted + + id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(ne2)); + Inherit::set_edge_id(ne2, id) ; // edges to the next available ids + Inherit::set_edge_id(Inherit::phi2(ne2), id) ; + dd = Inherit::phi1(Inherit::phi1(next)) ; + while(dd != ne) // turn around the face and insert new edges + { // linked to the central vertex + Dart tmp = Inherit::phi1(ne) ; + Inherit::split_face(tmp, dd) ; + + Dart nne = Inherit::phi2(Inherit::phi_1(dd)) ; + + id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(nne))); + Inherit::set_edge_id(nne, id) ; + Inherit::set_edge_id(Inherit::phi2(nne), id) ; + dd = Inherit::phi1(Inherit::phi1(dd)) ; + } + }); + + Inherit::set_current_level(cur) ; } inline void add_mixed_level() { + unsigned int cur = Inherit::get_current_level() ; + + Inherit::set_current_level(Inherit::get_maximum_level() + 1) ; + + //cut edges + Inherit::template foreach_cell([&] (typename Inherit::Edge e) + { + Dart dd = Inherit::phi2(e); + Inherit::cut_edge(e); + + unsigned int eid = Inherit::get_edge_id(e); + Inherit::set_edge_id(Inherit::phi1(e), eid); + Inherit::set_edge_id(Inherit::phi1(dd), eid); + }); + + //cut faces + Inherit::template foreach_cell([&] (typename Inherit::Face d) + { + Dart old = d ; + + if(Inherit::get_dart_level(old) == Inherit::get_maximum_level()) + old = Inherit::phi1(old) ; + + unsigned int cur = Inherit::get_current_level(); + Inherit::set_current_level(cur - 1); + unsigned int degree = Inherit::face_degree(old) ; + Inherit::set_current_level(cur); + + if(degree == 3) + { + Dart dd = Inherit::phi1(old) ; + Dart e = Inherit::phi1(Inherit::phi1(dd)) ; + // insert a new edge + Inherit::split_face(dd, e) ; + + unsigned int id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); + Inherit::set_edge_id(Inherit::phi_1(dd), id) ; // set the edge id of the inserted + Inherit::set_edge_id(Inherit::phi_1(e), id) ; // edge to the next available id + + dd = e ; + e = Inherit::phi1(Inherit::phi1(dd)) ; + Inherit::split_face(dd, e) ; + id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); + Inherit::set_edge_id(Inherit::phi_1(dd), id) ; + Inherit::set_edge_id(Inherit::phi_1(e), id) ; + + dd = e ; + e = Inherit::phi1(Inherit::phi1(dd)) ; + Inherit::split_face(dd, e) ; + id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); + Inherit::set_edge_id(Inherit::phi_1(dd), id) ; + Inherit::set_edge_id(Inherit::phi_1(e), id) ; + } + else + { + Dart dd = Inherit::phi1(old) ; + Dart next = Inherit::phi1(Inherit::phi1(dd)) ; + Inherit::split_face(dd, next) ; // insert a first edge + + Dart ne = Inherit::phi2(Inherit::phi_1(dd)) ; + Dart ne2 = Inherit::phi2(ne) ; + Inherit::cut_edge(ne) ; // cut the new edge to insert the central vertex + + unsigned int id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(ne))); + Inherit::set_edge_id(ne, id) ; + Inherit::set_edge_id(Inherit::phi2(ne), id) ; // set the edge id of the inserted + + id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(ne2)); + Inherit::set_edge_id(ne2, id) ; // edges to the next available ids + Inherit::set_edge_id(Inherit::phi2(ne2), id) ; + + dd = Inherit::phi1(Inherit::phi1(next)) ; + while(dd != ne) // turn around the face and insert new edges + { // linked to the central vertex + Dart tmp = Inherit::phi1(ne) ; + Inherit::split_face(tmp, dd) ; + + Dart nne = Inherit::phi2(Inherit::phi_1(dd)) ; + + id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(nne))); + Inherit::set_edge_id(nne, id) ; + Inherit::set_edge_id(Inherit::phi2(nne), id) ; + dd = Inherit::phi1(Inherit::phi1(dd)) ; + } + } + }); +// Inherit::set_current_level(cur) ; } }; diff --git a/cgogn/core/cph/ihcmap_base.h b/cgogn/core/cph/ihcmap_base.h index 4ff6a97a..aef5ee6d 100644 --- a/cgogn/core/cph/ihcmap_base.h +++ b/cgogn/core/cph/ihcmap_base.h @@ -51,11 +51,11 @@ class IHCMapBase std::vector nb_darts_per_level; - const ChunkArrayContainer& topology_; + ChunkArrayContainer& topo_; public: - IHCMapBase(const ChunkArrayContainer& topology): - topology_(topology), + IHCMapBase(ChunkArrayContainer& topology): + topo_(topology), current_level_(0), maximum_level_(0) { @@ -64,8 +64,8 @@ class IHCMapBase ~IHCMapBase() { - topology_.remove_attribute(dart_level_); - topology_.remove_attribute(edge_id_); + topo_.remove_attribute(dart_level_); + topo_.remove_attribute(edge_id_); } IHCMapBase(Self const&) = delete; @@ -73,12 +73,12 @@ class IHCMapBase Self& operator=(Self const&) = delete; Self& operator=(Self &&) = delete; -protected: +public: void init() { - dart_level_ = topology_.add_attribute("dartLevel") ; - edge_id_ = topology_.add_attribute("edgeId"); + dart_level_ = topo_.template add_attribute("dartLevel") ; + edge_id_ = topo_.template add_attribute("edgeId"); } /*************************************************** @@ -134,9 +134,6 @@ class IHCMapBase unsigned int d_id = get_edge_id(d); unsigned int e_id = get_edge_id(e); - // unsigned int d_id = get_edge_id(phi_1(d)); - // unsigned int e_id = get_edge_id(phi1(d)); - unsigned int id = d_id + e_id; if(id == 0u) @@ -156,11 +153,9 @@ class IHCMapBase } inline unsigned int get_quad_refinement_edge_id(Dart d) const - { - // unsigned int e_id = get_edge_id(phi1(d)); + { unsigned int e_id = get_edge_id(d); - if(e_id == 0u) return 1u; @@ -184,4 +179,4 @@ class IHCMapBase } // namespace cgogn -#endif // CORE_CPH_CPH_H_ \ No newline at end of file +#endif // CORE_CPH_CPH_H_ diff --git a/cgogn/core/examples/CMakeLists.txt b/cgogn/core/examples/CMakeLists.txt index 0e99a93f..8aa69c86 100644 --- a/cgogn/core/examples/CMakeLists.txt +++ b/cgogn/core/examples/CMakeLists.txt @@ -10,4 +10,4 @@ add_definitions("-DCGOGN_TEST_MESHES_PATH=${CGOGN_TEST_MESHES_PATH}") add_subdirectory(chunk_array) add_subdirectory(map) -# add_subdirectory(cph) \ No newline at end of file +add_subdirectory(cph) diff --git a/cgogn/core/examples/cph/CMakeLists.txt b/cgogn/core/examples/cph/CMakeLists.txt new file mode 100644 index 00000000..14698500 --- /dev/null +++ b/cgogn/core/examples/cph/CMakeLists.txt @@ -0,0 +1,9 @@ +project(${CGOGN_TEST_PREFIX}map + LANGUAGES CXX +) + +set(CGOGN_TEST_MESHES_PATH "${CMAKE_SOURCE_DIR}/data/meshes/") +add_definitions("-DCGOGN_TEST_MESHES_PATH=${CGOGN_TEST_MESHES_PATH}") + +add_executable(cph2 cph2.cpp) +target_link_libraries(cph2 cgogn_core cgogn_io) diff --git a/cgogn/core/examples/cph/cph2.cpp b/cgogn/core/examples/cph/cph2.cpp new file mode 100644 index 00000000..58199ca0 --- /dev/null +++ b/cgogn/core/examples/cph/cph2.cpp @@ -0,0 +1,78 @@ + +#include + +using namespace cgogn; + +using IHMap2 = IHCMap2Regular; + + +template +using VertexAttributeHandler = IHMap2::VertexAttributeHandler; + + +int main() +{ + IHMap2 map; + + // VertexAttributeHandler vertex_position_ = map.get_attribute("position"); + + map.add_face(4); + + std::cout << "before add level Faces :" << std::endl; + map.template foreach_cell([&] (typename IHMap2::Face v) + { + std::cout << v << std::endl; + }); + std::cout << "End Faces" << std::endl; + + + { + map.add_mixed_level(); + + std::cout << "after add level Faces :" << std::endl; + map.template foreach_cell([&] (typename IHMap2::Face f) + { + std::cout << f << " | " << map.get_dart_level(f.dart) << std::endl; + }); + std::cout << "End Faces" << std::endl; + + + unsigned int cur = map.get_current_level(); + + std::cout << "current level = " << cur << std::endl; + map.set_current_level(cur - 1); + + std::cout << "after add level Faces :" << std::endl; + map.template foreach_cell([&] (typename IHMap2::Face f) + { + std::cout << f << " | " << map.get_dart_level(f.dart) << std::endl; + }); + std::cout << "End Vertices" << std::endl; + } + + { + map.add_mixed_level(); + + std::cout << "after add level Faces :" << std::endl; + map.template foreach_cell([&] (typename IHMap2::Face f) + { + std::cout << f << " | " << map.get_dart_level(f.dart) << std::endl; + }); + std::cout << "End Faces" << std::endl; + + + unsigned int cur = map.get_current_level(); + + std::cout << "current level = " << cur << std::endl; + map.set_current_level(cur - 1); + + std::cout << "after add level Faces :" << std::endl; + map.template foreach_cell([&] (typename IHMap2::Face f) + { + std::cout << f << " | " << map.get_dart_level(f.dart) << std::endl; + }); + std::cout << "End Vertices" << std::endl; + } + + return 0; +} From cc24ea3967bc5ef069726f3363cc27c21cce6b6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Mon, 1 Feb 2016 20:08:12 +0100 Subject: [PATCH 020/402] first attempt of using a thread_pool. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/CMakeLists.txt | 1 + cgogn/core/cmap/map_base.h | 70 ++++------ cgogn/core/cmap/map_base_data.h | 6 +- cgogn/core/utils/thread.cpp | 7 + cgogn/core/utils/thread.h | 3 + cgogn/core/utils/thread_pool.h | 142 +++++++++++++++++++++ cgogn/rendering/examples/simple_viewer.cpp | 2 +- 7 files changed, 181 insertions(+), 50 deletions(-) create mode 100644 cgogn/core/utils/thread_pool.h diff --git a/cgogn/core/CMakeLists.txt b/cgogn/core/CMakeLists.txt index 510871e4..79bdd472 100644 --- a/cgogn/core/CMakeLists.txt +++ b/cgogn/core/CMakeLists.txt @@ -35,6 +35,7 @@ set(HEADER_FILES utils/name_types.h utils/serialization.h utils/thread.h + utils/thread_pool.h utils/thread_barrier.h utils/string.h utils/precision.h diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 6b26a2ef..b6701edc 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -556,65 +556,39 @@ class MapBase : public MapBaseData static_assert(check_func_ith_parameter_type(FUNC, 0, Dart), "Wrong function first parameter type"); static_assert(check_func_ith_parameter_type(FUNC, 1, unsigned int), "Wrong function second parameter type"); - // these vectors will contain elements to be processed by the threads - // the first ones are passed to the threads - // the second ones are filled by this thread then swapped with the first ones - std::vector> vd1(nb_threads); - std::vector> vd2(nb_threads); - for (unsigned int i = 0; i < nb_threads; ++i) - { - vd1[i].reserve(PARALLEL_BUFFER_SIZE); - vd2[i].reserve(PARALLEL_BUFFER_SIZE); - } + using Future = std::future< typename std::result_of::type >; - bool finished = false; + const unsigned int nb_chunks = this->nb_darts()/PARALLEL_BUFFER_SIZE + 1u; + ThreadPool* thread_pool = cgogn::get_thread_pool(); - // creation of threads - Barrier sync1(nb_threads + 1); - Barrier sync2(nb_threads + 1); + std::vector> vd(nb_chunks); + std::vector futures; + futures.reserve(nb_chunks); - auto thread_deleter = [this] (std::thread* th) { const std::thread::id id = th->get_id(); th->join(); delete th; this->remove_thread(id); }; - - using thread_ptr = std::unique_ptr; - using ThreadFunc = ThreadFunction; - using tfs_ptr = std::unique_ptr; - - std::vector threads; - std::vector tfs; - threads.reserve(nb_threads); - tfs.reserve(nb_threads); - for (unsigned int i = 0; i < nb_threads; ++i) - { - tfs.emplace_back(tfs_ptr(new ThreadFunc(f, vd1[i], sync1, sync2, finished, i))); - threads.emplace_back(thread_ptr(new std::thread(std::ref( *(tfs[i]) )), thread_deleter)); - this->add_thread(threads.back()->get_id()); - } Dart it = Dart(this->topology_.begin()); - Dart end = Dart(this->topology_.end()); - while (it != end) - { - for (unsigned int i = 0; i < nb_threads; ++i) - vd2[i].clear(); + const Dart end = Dart(this->topology_.end()); - // fill vd2 vectors - unsigned int nb = 0; - while (it != end && nb < nb_threads * PARALLEL_BUFFER_SIZE) + for (unsigned int i = 0u; i < nb_chunks; ++i) + { + std::vector& darts = vd[i]; + darts.reserve(PARALLEL_BUFFER_SIZE); + for (unsigned j = 0; j < PARALLEL_BUFFER_SIZE && it != end; ++j) { - vd2[nb % nb_threads].push_back(it); - ++nb; + darts.push_back(it); this->topology_.next(it.index); } - - for (unsigned int i = 0; i < nb_threads; ++i) - vd1[i].swap(vd2[i]); - - sync2.wait(); // vectors are ready for threads to process - sync1.wait(); // wait for all threads to finish their vector + futures.emplace_back(thread_pool->enqueue( [&](){ + const std::vector& vec_darts = darts; + for (auto d : vec_darts) + f(d,0u); + })); } - finished = true; // say finish to all threads - sync2.wait(); // last barrier wait + for (auto& fu: futures) + { + fu.wait(); + } } /** diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index bd2631f3..11a25050 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -145,7 +146,10 @@ class MapBaseData : public MapGen mark_attributes_topology_[i].reserve(8); thread_ids_.reserve(MAX_NB_THREADS); - thread_ids_.push_back(std::this_thread::get_id()); + this->add_thread(std::this_thread::get_id()); + const auto& pool_threads_ids = cgogn::get_thread_pool()->get_threads_ids(); + for (const std::thread::id& ids : pool_threads_ids) + this->add_thread(ids); } ~MapBaseData() override diff --git a/cgogn/core/utils/thread.cpp b/cgogn/core/utils/thread.cpp index a163377a..b4798118 100644 --- a/cgogn/core/utils/thread.cpp +++ b/cgogn/core/utils/thread.cpp @@ -25,6 +25,7 @@ #include + namespace cgogn { @@ -60,4 +61,10 @@ CGOGN_UTILS_API Buffers* get_uint_buffers() return uint_buffers_thread; } +CGOGN_UTILS_API ThreadPool* get_thread_pool() +{ + static std::unique_ptr pool(new ThreadPool(NB_THREADS)); + return pool.get(); +} + } // namespace cgogn diff --git a/cgogn/core/utils/thread.h b/cgogn/core/utils/thread.h index e29ec864..2bde5381 100644 --- a/cgogn/core/utils/thread.h +++ b/cgogn/core/utils/thread.h @@ -27,6 +27,7 @@ #include #include #include +#include namespace cgogn { @@ -37,6 +38,8 @@ namespace cgogn const unsigned int MAX_NB_THREADS = 8u; CGOGN_UTILS_API extern unsigned int NB_THREADS; +CGOGN_UTILS_API ThreadPool* get_thread_pool(); + inline unsigned int get_nb_threads() { unsigned int c = std::thread::hardware_concurrency(); diff --git a/cgogn/core/utils/thread_pool.h b/cgogn/core/utils/thread_pool.h new file mode 100644 index 00000000..2bff04a5 --- /dev/null +++ b/cgogn/core/utils/thread_pool.h @@ -0,0 +1,142 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef CORE_UTILS_THREADPOOL_H_ +#define CORE_UTILS_THREADPOOL_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace cgogn +{ + +class ThreadPool { +public: + ThreadPool(size_t); + ThreadPool(const ThreadPool&) = delete; + ThreadPool& operator=(const ThreadPool&) = delete; + ThreadPool(ThreadPool&&) = delete; + ThreadPool& operator=(ThreadPool&&) = delete; + + template + auto enqueue(F&& f, Args&&... args) + -> std::future::type>; + + std::vector get_threads_ids() const + { + std::vector res; + res.reserve(workers_.size()); + for (const std::thread& w : workers_) + res.push_back(w.get_id()); + return res; + } + + virtual ~ThreadPool(); +private: + // need to keep track of threads so we can join them + std::vector< std::thread > workers_; + // the task queue + std::queue< std::function > tasks_; + + // synchronization + std::mutex queue_mutex_; + std::condition_variable condition_; + bool stop_; +}; + +// the constructor just launches some amount of workers +inline ThreadPool::ThreadPool(size_t threads) + : stop_(false) +{ + for(size_t i = 0;i task; + + { + std::unique_lock lock(this->queue_mutex_); + this->condition_.wait(lock, + [this]{ return this->stop_ || !this->tasks_.empty(); }); + if(this->stop_ && this->tasks_.empty()) + return; + task = std::move(this->tasks_.front()); + this->tasks_.pop(); + } + + task(); + } + } + ); +} + +// add new work item to the pool +template +auto ThreadPool::enqueue(F&& f, Args&&... args) +-> std::future::type> +{ + using return_type = typename std::result_of::type; + + auto task = std::make_shared< std::packaged_task >( + std::bind(std::forward(f), std::forward(args)...) + ); + + std::future res = task->get_future(); + { + std::unique_lock lock(queue_mutex_); + + // don't allow enqueueing after stopping the pool + if(stop_) + cgogn_assert_not_reached("enqueue on stopped ThreadPool"); + + tasks_.emplace([task](){ (*task)(); }); + } + condition_.notify_one(); + return res; +} + +// the destructor joins all threads +inline ThreadPool::~ThreadPool() +{ + { + std::unique_lock lock(queue_mutex_); + stop_ = true; + } + condition_.notify_all(); + for(std::thread &worker: workers_) + worker.join(); +} + +} // namespace cgogn + +#endif // CORE_UTILS_THREADPOOL_H_ diff --git a/cgogn/rendering/examples/simple_viewer.cpp b/cgogn/rendering/examples/simple_viewer.cpp index 511802a7..b8d30db4 100644 --- a/cgogn/rendering/examples/simple_viewer.cpp +++ b/cgogn/rendering/examples/simple_viewer.cpp @@ -53,7 +53,7 @@ class Viewer : public QOGLViewer { public: Viewer(); - inline Viewer(const Viewer&) = delete; + Viewer(const Viewer&) = delete; Viewer& operator=(const Viewer&) = delete; virtual void draw(); From 0327420b05b758a641d8e9240ffdf736f7b7d6a6 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Mon, 1 Feb 2016 21:48:07 +0100 Subject: [PATCH 021/402] thread index parameter Signed-off-by: Etienne Schmitt --- cgogn/core/basic/dart_marker.h | 4 +++- cgogn/core/cmap/map_base.h | 6 +++--- cgogn/core/utils/thread.cpp | 5 +++-- cgogn/core/utils/thread.h | 14 ++++++++++++-- cgogn/core/utils/thread_pool.h | 31 +++++++++++++++++-------------- 5 files changed, 38 insertions(+), 22 deletions(-) diff --git a/cgogn/core/basic/dart_marker.h b/cgogn/core/basic/dart_marker.h index 5eecfae0..71442dcb 100644 --- a/cgogn/core/basic/dart_marker.h +++ b/cgogn/core/basic/dart_marker.h @@ -24,8 +24,10 @@ #ifndef CORE_BASIC_DART_MARKER_H_ #define CORE_BASIC_DART_MARKER_H_ -#include +#include + #include +#include namespace cgogn { diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index b6701edc..9d1c0bbb 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -551,7 +551,7 @@ class MapBase : public MapBaseData } template - inline void parallel_foreach_dart(const FUNC& f, unsigned int nb_threads = NB_THREADS - 1) const + inline void parallel_foreach_dart(const FUNC& f) const { static_assert(check_func_ith_parameter_type(FUNC, 0, Dart), "Wrong function first parameter type"); static_assert(check_func_ith_parameter_type(FUNC, 1, unsigned int), "Wrong function second parameter type"); @@ -578,10 +578,10 @@ class MapBase : public MapBaseData darts.push_back(it); this->topology_.next(it.index); } - futures.emplace_back(thread_pool->enqueue( [&](){ + futures.emplace_back(thread_pool->enqueue( [&](unsigned int i){ const std::vector& vec_darts = darts; for (auto d : vec_darts) - f(d,0u); + f(d,i); })); } diff --git a/cgogn/core/utils/thread.cpp b/cgogn/core/utils/thread.cpp index b4798118..1e656995 100644 --- a/cgogn/core/utils/thread.cpp +++ b/cgogn/core/utils/thread.cpp @@ -24,7 +24,8 @@ #define CGOGN_UTILS_DLL_EXPORT #include - +#include +#include namespace cgogn { @@ -63,7 +64,7 @@ CGOGN_UTILS_API Buffers* get_uint_buffers() CGOGN_UTILS_API ThreadPool* get_thread_pool() { - static std::unique_ptr pool(new ThreadPool(NB_THREADS)); + static std::unique_ptr pool(new ThreadPool); return pool.get(); } diff --git a/cgogn/core/utils/thread.h b/cgogn/core/utils/thread.h index 2bde5381..f52e394c 100644 --- a/cgogn/core/utils/thread.h +++ b/cgogn/core/utils/thread.h @@ -24,14 +24,24 @@ #ifndef CORE_UTILS_THREAD_H_ #define CORE_UTILS_THREAD_H_ -#include +#include + #include +#include #include -#include + +#include namespace cgogn { +// forward declaration of the ThreadPool class +class ThreadPool; + +// forward declaration of the Buffers class +template +class Buffers; + /** * \brief The maximum nunmber of threads created by the API. */ diff --git a/cgogn/core/utils/thread_pool.h b/cgogn/core/utils/thread_pool.h index 2bff04a5..0f6abd3b 100644 --- a/cgogn/core/utils/thread_pool.h +++ b/cgogn/core/utils/thread_pool.h @@ -34,13 +34,14 @@ #include #include +#include namespace cgogn { class ThreadPool { public: - ThreadPool(size_t); + ThreadPool(); ThreadPool(const ThreadPool&) = delete; ThreadPool& operator=(const ThreadPool&) = delete; ThreadPool(ThreadPool&&) = delete; @@ -48,7 +49,7 @@ class ThreadPool { template auto enqueue(F&& f, Args&&... args) - -> std::future::type>; + -> std::future::type>; std::vector get_threads_ids() const { @@ -64,7 +65,7 @@ class ThreadPool { // need to keep track of threads so we can join them std::vector< std::thread > workers_; // the task queue - std::queue< std::function > tasks_; + std::queue< std::function > tasks_; // synchronization std::mutex queue_mutex_; @@ -73,16 +74,16 @@ class ThreadPool { }; // the constructor just launches some amount of workers -inline ThreadPool::ThreadPool(size_t threads) +inline ThreadPool::ThreadPool() : stop_(false) { - for(size_t i = 0;i task; + std::function task; { std::unique_lock lock(this->queue_mutex_); @@ -94,7 +95,7 @@ inline ThreadPool::ThreadPool(size_t threads) this->tasks_.pop(); } - task(); + task(i); } } ); @@ -102,13 +103,15 @@ inline ThreadPool::ThreadPool(size_t threads) // add new work item to the pool template -auto ThreadPool::enqueue(F&& f, Args&&... args) --> std::future::type> +auto ThreadPool::enqueue(F&& f, Args&&... args) +-> std::future::type> { - using return_type = typename std::result_of::type; + using return_type = typename std::result_of::type; - auto task = std::make_shared< std::packaged_task >( - std::bind(std::forward(f), std::forward(args)...) + auto task = std::make_shared< std::packaged_task >([&](unsigned int i) + { + return std::bind(std::forward(f), i, std::forward(args)...)(); + } ); std::future res = task->get_future(); @@ -119,7 +122,7 @@ auto ThreadPool::enqueue(F&& f, Args&&... args) if(stop_) cgogn_assert_not_reached("enqueue on stopped ThreadPool"); - tasks_.emplace([task](){ (*task)(); }); + tasks_.emplace([task](unsigned int i){ (*task)(i); }); } condition_.notify_one(); return res; From 766474afad4ff2206f86b378820f4b8ae6c81e45 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Mon, 1 Feb 2016 23:34:02 +0100 Subject: [PATCH 022/402] thread_pool.cpp and "no future" ! Signed-off-by: Etienne Schmitt --- cgogn/core/CMakeLists.txt | 1 + cgogn/core/cmap/map_base.h | 14 +----- cgogn/core/utils/thread_pool.cpp | 75 ++++++++++++++++++++++++++++++++ cgogn/core/utils/thread_pool.h | 75 ++++++++++++-------------------- 4 files changed, 105 insertions(+), 60 deletions(-) create mode 100644 cgogn/core/utils/thread_pool.cpp diff --git a/cgogn/core/CMakeLists.txt b/cgogn/core/CMakeLists.txt index 79bdd472..e7481d2a 100644 --- a/cgogn/core/CMakeLists.txt +++ b/cgogn/core/CMakeLists.txt @@ -60,6 +60,7 @@ set(SOURCE_FILES utils/assert.cpp utils/thread.cpp + utils/thread_pool.cpp utils/serialization.cpp ) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 9d1c0bbb..acaec8ce 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -556,15 +556,10 @@ class MapBase : public MapBaseData static_assert(check_func_ith_parameter_type(FUNC, 0, Dart), "Wrong function first parameter type"); static_assert(check_func_ith_parameter_type(FUNC, 1, unsigned int), "Wrong function second parameter type"); - using Future = std::future< typename std::result_of::type >; - const unsigned int nb_chunks = this->nb_darts()/PARALLEL_BUFFER_SIZE + 1u; ThreadPool* thread_pool = cgogn::get_thread_pool(); std::vector> vd(nb_chunks); - std::vector futures; - futures.reserve(nb_chunks); - Dart it = Dart(this->topology_.begin()); const Dart end = Dart(this->topology_.end()); @@ -578,16 +573,11 @@ class MapBase : public MapBaseData darts.push_back(it); this->topology_.next(it.index); } - futures.emplace_back(thread_pool->enqueue( [&](unsigned int i){ + thread_pool->enqueue_no_return( [&](unsigned int i){ const std::vector& vec_darts = darts; for (auto d : vec_darts) f(d,i); - })); - } - - for (auto& fu: futures) - { - fu.wait(); + }); } } diff --git a/cgogn/core/utils/thread_pool.cpp b/cgogn/core/utils/thread_pool.cpp new file mode 100644 index 00000000..160a4e6c --- /dev/null +++ b/cgogn/core/utils/thread_pool.cpp @@ -0,0 +1,75 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#include + +namespace cgogn + +{ + +std::vector ThreadPool::get_threads_ids() const +{ + std::vector res; + res.reserve(workers_.size()); + for (const std::thread& w : workers_) + res.push_back(w.get_id()); + return res; +} + +ThreadPool::~ThreadPool() +{ + stop_ = true; + condition_.notify_all(); + for(std::thread &worker: workers_) + worker.join(); +} + +ThreadPool::ThreadPool() + : stop_(false) +{ + for(unsigned int i = 0u; i< MAX_NB_THREADS ;++i) + workers_.emplace_back( + [this,i] + { + for(;;) + { + std::function task; + + { + std::unique_lock lock(this->queue_mutex_); + this->condition_.wait(lock, + [this]{ return this->stop_ || !this->tasks_.empty(); }); + if(this->stop_ && this->tasks_.empty()) + return; + task = std::move(this->tasks_.front()); + this->tasks_.pop(); + } + + task(i); + } + } + ); +} + +} // namespace cgogn + diff --git a/cgogn/core/utils/thread_pool.h b/cgogn/core/utils/thread_pool.h index 0f6abd3b..cd529798 100644 --- a/cgogn/core/utils/thread_pool.h +++ b/cgogn/core/utils/thread_pool.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -51,16 +52,12 @@ class ThreadPool { auto enqueue(F&& f, Args&&... args) -> std::future::type>; - std::vector get_threads_ids() const - { - std::vector res; - res.reserve(workers_.size()); - for (const std::thread& w : workers_) - res.push_back(w.get_id()); - return res; - } + template + void enqueue_no_return(F&& f, Args&&... args); + std::vector get_threads_ids() const; virtual ~ThreadPool(); + private: // need to keep track of threads so we can join them std::vector< std::thread > workers_; @@ -70,36 +67,9 @@ class ThreadPool { // synchronization std::mutex queue_mutex_; std::condition_variable condition_; - bool stop_; + std::atomic_bool stop_; }; -// the constructor just launches some amount of workers -inline ThreadPool::ThreadPool() - : stop_(false) -{ - for(unsigned int i = 0u; i< MAX_NB_THREADS ;++i) - workers_.emplace_back( - [this,i] - { - for(;;) - { - std::function task; - - { - std::unique_lock lock(this->queue_mutex_); - this->condition_.wait(lock, - [this]{ return this->stop_ || !this->tasks_.empty(); }); - if(this->stop_ && this->tasks_.empty()) - return; - task = std::move(this->tasks_.front()); - this->tasks_.pop(); - } - - task(i); - } - } - ); -} // add new work item to the pool template @@ -108,36 +78,45 @@ auto ThreadPool::enqueue(F&& f, Args&&... args) { using return_type = typename std::result_of::type; + // don't allow enqueueing after stopping the pool + if(stop_) + cgogn_assert_not_reached("enqueue on stopped ThreadPool"); + auto task = std::make_shared< std::packaged_task >([&](unsigned int i) { return std::bind(std::forward(f), i, std::forward(args)...)(); } - ); + ); std::future res = task->get_future(); { std::unique_lock lock(queue_mutex_); - - // don't allow enqueueing after stopping the pool - if(stop_) - cgogn_assert_not_reached("enqueue on stopped ThreadPool"); - + // Push work back on the queue tasks_.emplace([task](unsigned int i){ (*task)(i); }); } + // Notify a thread that there is new work to perform condition_.notify_one(); return res; } -// the destructor joins all threads -inline ThreadPool::~ThreadPool() +template +void ThreadPool::enqueue_no_return(F&& f, Args&&... args) { + // don't allow enqueueing after stopping the pool + if(stop_) + cgogn_assert_not_reached("enqueue on stopped ThreadPool"); { std::unique_lock lock(queue_mutex_); - stop_ = true; + + // Push work back on the queue + tasks_.emplace ([&](unsigned int i) + { + std::bind(std::forward(f), i, std::forward(args)...)(); + }); } - condition_.notify_all(); - for(std::thread &worker: workers_) - worker.join(); + + // Notify a thread that there is new work to perform + condition_.notify_one (); } } // namespace cgogn From cb8900fe6edc3f26be96284df7ba4a8b0cc09f57 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Tue, 2 Feb 2016 00:41:26 +0100 Subject: [PATCH 023/402] enqueue_no_return was a bad idea. parallel_foreach_cell_cell_marking with thread pool. Signed-off-by: Etienne Schmitt --- cgogn/core/cmap/map_base.h | 94 +++++++++++++------------------- cgogn/core/utils/thread_pool.cpp | 9 ++- cgogn/core/utils/thread_pool.h | 33 ++--------- 3 files changed, 49 insertions(+), 87 deletions(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index acaec8ce..c827abcc 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -556,10 +556,15 @@ class MapBase : public MapBaseData static_assert(check_func_ith_parameter_type(FUNC, 0, Dart), "Wrong function first parameter type"); static_assert(check_func_ith_parameter_type(FUNC, 1, unsigned int), "Wrong function second parameter type"); + using Future = std::future< typename std::result_of::type >; + const unsigned int nb_chunks = this->nb_darts()/PARALLEL_BUFFER_SIZE + 1u; ThreadPool* thread_pool = cgogn::get_thread_pool(); std::vector> vd(nb_chunks); + std::vector futures; + futures.reserve(nb_chunks); + Dart it = Dart(this->topology_.begin()); const Dart end = Dart(this->topology_.end()); @@ -573,11 +578,16 @@ class MapBase : public MapBaseData darts.push_back(it); this->topology_.next(it.index); } - thread_pool->enqueue_no_return( [&](unsigned int i){ + futures.emplace_back(thread_pool->enqueue( [&](unsigned int i){ const std::vector& vec_darts = darts; for (auto d : vec_darts) f(d,i); - }); + })); + } + + for (auto& fu: futures) + { + fu.wait(); } } @@ -646,7 +656,7 @@ class MapBase : public MapBaseData parallel_foreach_cell_dart_marking(f, nb_threads); break; case FORCE_CELL_MARKING : - parallel_foreach_cell_cell_marking(f, nb_threads); + parallel_foreach_cell_cell_marking(f); break; case FORCE_TOPO_CACHE : parallel_foreach_cell_topo_cache(f, nb_threads); @@ -655,7 +665,7 @@ class MapBase : public MapBaseData if (is_topo_cache_enabled()) parallel_foreach_cell_topo_cache(f, nb_threads); else if (this->template is_orbit_embedded()) - parallel_foreach_cell_cell_marking(f, nb_threads); + parallel_foreach_cell_cell_marking(f); else parallel_foreach_cell_dart_marking(f, nb_threads); break; @@ -800,72 +810,46 @@ class MapBase : public MapBaseData } template - inline void parallel_foreach_cell_cell_marking(const FUNC& f, unsigned int nb_threads) const + inline void parallel_foreach_cell_cell_marking(const FUNC& f) const { - // these vectors will contain elements to be processed by the threads - // the first ones are passed to the threads - // the second ones are filled by this thread while the other are processed - std::vector>> vd1(nb_threads); - std::vector>> vd2(nb_threads); - for (unsigned int i = 0; i < nb_threads; ++i) - { - vd1[i].reserve(PARALLEL_BUFFER_SIZE); - vd2[i].reserve(PARALLEL_BUFFER_SIZE); - } + using VecCell = std::vector>; + using Future = std::future< typename std::result_of, unsigned int)>::type >; - bool finished = false; - - // creation of threads - Barrier sync1(nb_threads + 1); - Barrier sync2(nb_threads + 1); - - auto thread_deleter = [this] (std::thread* th) { const std::thread::id id = th->get_id(); th->join(); delete th; this->remove_thread(id); }; - - using thread_ptr = std::unique_ptr; - using ThreadFunc = ThreadFunction, FUNC>; - using tfs_ptr = std::unique_ptr; + const unsigned int nb_chunks = this->nb_cells()/PARALLEL_BUFFER_SIZE + 1u; + ThreadPool* thread_pool = cgogn::get_thread_pool(); - std::vector threads; - std::vector tfs; - threads.reserve(nb_threads); - tfs.reserve(nb_threads); - for (unsigned int i = 0; i < nb_threads; ++i) - { - tfs.emplace_back(tfs_ptr(new ThreadFunc(f, vd1[i], sync1, sync2, finished, i))); - threads.emplace_back(thread_ptr(new std::thread(std::ref( *(tfs[i]) )), thread_deleter)); - this->add_thread(threads.back()->get_id()); - } + std::vector vd(nb_chunks); + std::vector futures; + futures.reserve(nb_chunks); CellMarker cm(*to_concrete()); Dart it = Dart(this->topology_.begin()); - Dart end = Dart(this->topology_.end()); - while (it != end) - { - for (unsigned int i = 0; i < nb_threads; ++i) - vd2[i].clear(); + const Dart end = Dart(this->topology_.end()); - // fill vd2 vectors - unsigned int nb = 0; - while (it != end && nb < nb_threads * PARALLEL_BUFFER_SIZE) + for (unsigned int i = 0u; i < nb_chunks; ++i) + { + VecCell& cells = vd[i]; + cells.reserve(PARALLEL_BUFFER_SIZE); + for (unsigned int j = 0u; j < PARALLEL_BUFFER_SIZE && it != end;) { if (!cm.is_marked(it)) { cm.mark(it); - vd2[nb % nb_threads].push_back(Cell(it)); - ++nb; + cells.push_back(it); + ++j; } this->topology_.next(it.index); } - - for (unsigned int i = 0; i < nb_threads; ++i) - vd1[i].swap(vd2[i]); - - sync2.wait(); // vectors are ready for threads to process - sync1.wait(); // wait for all threads to finish their vector + futures.emplace_back(thread_pool->enqueue( [&](unsigned int i){ + const VecCell& vec_cells = cells; + for (auto d : vec_cells) + f(d,i); + })); + } + for (auto& fu: futures) + { + fu.wait(); } - - finished = true; // say finish to all threads - sync2.wait(); // last barrier wait } template diff --git a/cgogn/core/utils/thread_pool.cpp b/cgogn/core/utils/thread_pool.cpp index 160a4e6c..2d89c8ec 100644 --- a/cgogn/core/utils/thread_pool.cpp +++ b/cgogn/core/utils/thread_pool.cpp @@ -38,14 +38,17 @@ std::vector ThreadPool::get_threads_ids() const ThreadPool::~ThreadPool() { - stop_ = true; + { + std::unique_lock lock(queue_mutex_); + stop_ = true; + } condition_.notify_all(); for(std::thread &worker: workers_) worker.join(); } -ThreadPool::ThreadPool() - : stop_(false) + +ThreadPool::ThreadPool() : stop_(false) { for(unsigned int i = 0u; i< MAX_NB_THREADS ;++i) workers_.emplace_back( diff --git a/cgogn/core/utils/thread_pool.h b/cgogn/core/utils/thread_pool.h index cd529798..acff6776 100644 --- a/cgogn/core/utils/thread_pool.h +++ b/cgogn/core/utils/thread_pool.h @@ -32,7 +32,6 @@ #include #include #include -#include #include #include @@ -52,9 +51,6 @@ class ThreadPool { auto enqueue(F&& f, Args&&... args) -> std::future::type>; - template - void enqueue_no_return(F&& f, Args&&... args); - std::vector get_threads_ids() const; virtual ~ThreadPool(); @@ -67,7 +63,7 @@ class ThreadPool { // synchronization std::mutex queue_mutex_; std::condition_variable condition_; - std::atomic_bool stop_; + bool stop_; }; @@ -78,10 +74,6 @@ auto ThreadPool::enqueue(F&& f, Args&&... args) { using return_type = typename std::result_of::type; - // don't allow enqueueing after stopping the pool - if(stop_) - cgogn_assert_not_reached("enqueue on stopped ThreadPool"); - auto task = std::make_shared< std::packaged_task >([&](unsigned int i) { return std::bind(std::forward(f), i, std::forward(args)...)(); @@ -91,6 +83,9 @@ auto ThreadPool::enqueue(F&& f, Args&&... args) std::future res = task->get_future(); { std::unique_lock lock(queue_mutex_); + // don't allow enqueueing after stopping the pool + if(stop_) + cgogn_assert_not_reached("enqueue on stopped ThreadPool"); // Push work back on the queue tasks_.emplace([task](unsigned int i){ (*task)(i); }); } @@ -99,26 +94,6 @@ auto ThreadPool::enqueue(F&& f, Args&&... args) return res; } -template -void ThreadPool::enqueue_no_return(F&& f, Args&&... args) -{ - // don't allow enqueueing after stopping the pool - if(stop_) - cgogn_assert_not_reached("enqueue on stopped ThreadPool"); - { - std::unique_lock lock(queue_mutex_); - - // Push work back on the queue - tasks_.emplace ([&](unsigned int i) - { - std::bind(std::forward(f), i, std::forward(args)...)(); - }); - } - - // Notify a thread that there is new work to perform - condition_.notify_one (); -} - } // namespace cgogn #endif // CORE_UTILS_THREADPOOL_H_ From 093bc5ba24fe7dbef27374f3ec15c77579084ee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 2 Feb 2016 12:37:22 +0100 Subject: [PATCH 024/402] added CGOGN_STRONG_INLINE and CGOGN_ALWAYS_INLINE macros. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/utils/definitions.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/cgogn/core/utils/definitions.h b/cgogn/core/utils/definitions.h index 07bac26c..c76e3058 100644 --- a/cgogn/core/utils/definitions.h +++ b/cgogn/core/utils/definitions.h @@ -54,6 +54,26 @@ #define CGOGN_CONSTEXPR constexpr #endif +/* + * The macro CGOGN_STRONG_INLINE is useful to force inline functions in situations where MSVC needs forceinline + * but gcc or clang are still doing fine. +*/ +#if (defined _MSC_VER) || (defined __INTEL_COMPILER) +#define CGOGN_STRONG_INLINE __forceinline +#else +#define CGOGN_STRONG_INLINE inline +#endif + +/* + * The macro CGOGN_ALWAYS_INLINE is more powerfull than CGOGN_STRONG_INLINE when using clang or gcc. + * WARNING : use with caution, it can badly impact the compilation time. +*/ +#if (defined _MSC_VER) || (defined __INTEL_COMPILER) +#define CGOGN_ALWAYS_INLINE CGOGN_STRONG_INLINE +#else +#define CGOGN_ALWAYS_INLINE __attribute__((always_inline)) inline +#endif + /** * \brief No return declaration for CGOGN symbols. */ From 1ccc18318ebc1813b7c82609e9db24357e0cb783 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 2 Feb 2016 12:38:04 +0100 Subject: [PATCH 025/402] added missing "inline" keywords. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/basic/dart.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/cgogn/core/basic/dart.h b/cgogn/core/basic/dart.h index 1428adc0..cc2c1340 100644 --- a/cgogn/core/basic/dart.h +++ b/cgogn/core/basic/dart.h @@ -64,7 +64,7 @@ struct Dart * * \param[in] v the value of the new dart */ - explicit Dart(unsigned int v) : index(v) + inline explicit Dart(unsigned int v) : index(v) {} /** @@ -72,7 +72,7 @@ struct Dart * Creates a new Dart from an another one. * \param[in] d a dart */ - Dart(const Dart& d) : index(d.index) + inline Dart(const Dart& d) : index(d.index) {} /** @@ -80,7 +80,7 @@ struct Dart * \retval true if the dart is nil * \retval false otherwise */ - bool is_nil() const { return index == INVALID_INDEX; } + inline bool is_nil() const { return index == INVALID_INDEX; } /** * \brief Assigns to the left hand side dart the value @@ -88,7 +88,7 @@ struct Dart * \param[in] rhs the dart to assign * \return The dart with the assigned value */ - Dart operator=(Dart rhs) { index = rhs.index; return *this; } + inline Dart& operator=(Dart rhs) { index = rhs.index; return *this; } /** * \brief Tests whether the left hand side dart is equal @@ -97,7 +97,7 @@ struct Dart * \retval true if \p lhs is equal than \p rhs * \retval false otherwise */ - bool operator==(Dart rhs) const { return index == rhs.index; } + inline bool operator==(Dart rhs) const { return index == rhs.index; } /** * \brief Tests whether the left hand side dart is different @@ -106,23 +106,23 @@ struct Dart * \retval true if \p lhs is different than \p rhs * \retval false otherwise */ - bool operator!=(Dart rhs) const { return index != rhs.index; } + inline bool operator!=(Dart rhs) const { return index != rhs.index; } // operator < is needed if we want to use std::set - bool operator<(Dart rhs) const { return index < rhs.index; } + inline bool operator<(Dart rhs) const { return index < rhs.index; } /** * \brief Prints a dart to a stream. * \param[out] out the stream to print on * \param[in] rhs the dart to print */ - friend std::ostream& operator<<(std::ostream &out, const Dart& rhs) { return out << rhs.index; } + inline friend std::ostream& operator<<(std::ostream &out, const Dart& rhs) { return out << rhs.index; } /** * \brief Reads a dart from a stream. * \param[in] in the stream to read from * \param[out] rhs the dart read */ - friend std::istream& operator>>(std::istream &in, Dart& rhs) { in >> rhs.index; return in; } + inline friend std::istream& operator>>(std::istream &in, Dart& rhs) { in >> rhs.index; return in; } }; } // namespace cgogn From 50546856f3bf28489d308aebfe92e83a4b614c5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 2 Feb 2016 12:39:30 +0100 Subject: [PATCH 026/402] using Buffers in parallel foreach dart. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/map_base.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index c827abcc..cfb8cb27 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -561,9 +561,11 @@ class MapBase : public MapBaseData const unsigned int nb_chunks = this->nb_darts()/PARALLEL_BUFFER_SIZE + 1u; ThreadPool* thread_pool = cgogn::get_thread_pool(); - std::vector> vd(nb_chunks); + Buffers* dbuffs = cgogn::get_dart_buffers(); + std::vector*> dart_buffers; std::vector futures; futures.reserve(nb_chunks); + dart_buffers.reserve(nb_chunks); Dart it = Dart(this->topology_.begin()); @@ -571,16 +573,16 @@ class MapBase : public MapBaseData for (unsigned int i = 0u; i < nb_chunks; ++i) { - std::vector& darts = vd[i]; + dart_buffers.push_back(dbuffs->get_buffer()); + std::vector& darts(*dart_buffers.back()); darts.reserve(PARALLEL_BUFFER_SIZE); for (unsigned j = 0; j < PARALLEL_BUFFER_SIZE && it != end; ++j) { darts.push_back(it); this->topology_.next(it.index); } - futures.emplace_back(thread_pool->enqueue( [&](unsigned int i){ - const std::vector& vec_darts = darts; - for (auto d : vec_darts) + futures.emplace_back(thread_pool->enqueue( [&darts,&f](unsigned int i){ + for (auto d : darts) f(d,i); })); } @@ -589,6 +591,8 @@ class MapBase : public MapBaseData { fu.wait(); } + for (auto &b : dart_buffers) + dbuffs->release_buffer(b); } /** From fe27749b69614647208710c4722f4f4d0f5f3c7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 2 Feb 2016 13:45:36 +0100 Subject: [PATCH 027/402] No need of unique_ptr to store the thread pool. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/utils/thread.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cgogn/core/utils/thread.cpp b/cgogn/core/utils/thread.cpp index 1e656995..b234f9fe 100644 --- a/cgogn/core/utils/thread.cpp +++ b/cgogn/core/utils/thread.cpp @@ -64,8 +64,9 @@ CGOGN_UTILS_API Buffers* get_uint_buffers() CGOGN_UTILS_API ThreadPool* get_thread_pool() { - static std::unique_ptr pool(new ThreadPool); - return pool.get(); + // thread safe accoring to http://stackoverflow.com/questions/8102125/is-local-static-variable-initialization-thread-safe-in-c11 + static ThreadPool pool; + return &pool; } } // namespace cgogn From e8ea53accd92adc217bf1b641cadba85cc1a0ca5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 2 Feb 2016 13:46:12 +0100 Subject: [PATCH 028/402] Added missing thread_start() and thread_stop() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/utils/thread_pool.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cgogn/core/utils/thread_pool.cpp b/cgogn/core/utils/thread_pool.cpp index 2d89c8ec..f131ce86 100644 --- a/cgogn/core/utils/thread_pool.cpp +++ b/cgogn/core/utils/thread_pool.cpp @@ -47,13 +47,13 @@ ThreadPool::~ThreadPool() worker.join(); } - ThreadPool::ThreadPool() : stop_(false) { for(unsigned int i = 0u; i< MAX_NB_THREADS ;++i) workers_.emplace_back( [this,i] { + cgogn::thread_start(); for(;;) { std::function task; @@ -63,7 +63,11 @@ ThreadPool::ThreadPool() : stop_(false) this->condition_.wait(lock, [this]{ return this->stop_ || !this->tasks_.empty(); }); if(this->stop_ && this->tasks_.empty()) + { + cgogn::thread_stop(); return; + } + task = std::move(this->tasks_.front()); this->tasks_.pop(); } From 78371b4a66e16b9518a1edc88fba3e0d29b9fb23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 2 Feb 2016 17:10:35 +0100 Subject: [PATCH 029/402] added bench_multithreading MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- CMakeLists.txt | 5 +- benchmarks/CMakeLists.txt | 1 + benchmarks/multithreading/CMakeLists.txt | 11 + .../multithreading/bench_multithreading.cpp | 238 ++++++++++++++++++ 4 files changed, 254 insertions(+), 1 deletion(-) create mode 100644 benchmarks/CMakeLists.txt create mode 100644 benchmarks/multithreading/CMakeLists.txt create mode 100644 benchmarks/multithreading/bench_multithreading.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b27c3cbb..90a3433e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,7 @@ set(CGOGN_THIRDPARTY_DIR ${CMAKE_SOURCE_DIR}/thirdparty) option(CGOGN_PROVIDE_EIGEN "Use the version of eigen that is packaged with CGoGN." ON) option(CGOGN_PROVIDE_TINYXML2 "Use the version of tinyxml2 that is packaged with CGoGN." ON) option(CGOGN_BUILD_TESTS "Build cgogn unit tests using google test framework." ON) +option(CGOGN_BUILD_BENCHS "Build the benchmarks" ON) option(CGOGN_USE_OPENMP "Activate openMP directives." OFF) if (NOT MSVC) option(CGOGN_USE_PARALLEL_GLIBCXX "Highly experimental : compiles using the parallel mode." OFF) @@ -107,7 +108,9 @@ endif(CGOGN_BUILD_TESTS) add_subdirectory(${CGOGN_THIRDPARTY_DIR}) add_subdirectory(${CGOGN_SOURCE_DIR}) - +if(${CGOGN_BUILD_BENCHS}) + add_subdirectory(benchmarks) +endif(${CGOGN_BUILD_BENCHS}) ## TODO a mettre dans un fichier cmake particulier diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt new file mode 100644 index 00000000..1045f8a9 --- /dev/null +++ b/benchmarks/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(multithreading) diff --git a/benchmarks/multithreading/CMakeLists.txt b/benchmarks/multithreading/CMakeLists.txt new file mode 100644 index 00000000..48b1218e --- /dev/null +++ b/benchmarks/multithreading/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.0 FATAL_ERROR) + +project(bench_multithreading + LANGUAGES CXX +) + +set(CGOGN_TEST_MESHES_PATH "${CMAKE_SOURCE_DIR}/data/meshes/") +add_definitions("-DCGOGN_TEST_MESHES_PATH=${CGOGN_TEST_MESHES_PATH}") + +add_executable(${PROJECT_NAME} bench_multithreading.cpp) +target_link_libraries(${PROJECT_NAME} cgogn_core cgogn_io cgogn_geometry) diff --git a/benchmarks/multithreading/bench_multithreading.cpp b/benchmarks/multithreading/bench_multithreading.cpp new file mode 100644 index 00000000..5e021072 --- /dev/null +++ b/benchmarks/multithreading/bench_multithreading.cpp @@ -0,0 +1,238 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#include +#include + +#include +#include +#include +#include + + +#define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) + +struct MyMapTraits : public cgogn::DefaultMapTraits +{ + static const unsigned int CHUNK_SIZE = 8192; +}; + +using Map2 = cgogn::CMap2; +const cgogn::Orbit FACE = Map2::FACE; +using Face = cgogn::Cell; + +const unsigned int ITERATIONS = 10000u; + +using Vec3 = Eigen::Vector3d; +//using Vec3 = cgogn::geometry::Vec_T>; + +template +using VertexAttributeHandler = Map2::VertexAttributeHandler; +template +using FaceAttributeHandler = Map2::FaceAttributeHandler; + +int main(int argc, char** argv) +{ + std::string surfaceMesh; + if (argc < 2) + { + std::cout << "USAGE: " << argv[0] << " [filename]" << std::endl; + surfaceMesh = std::string(DEFAULT_MESH_PATH) + std::string("aneurysm3D_1.off"); + std::cout << "Using default mesh : " << surfaceMesh << std::endl; + } + else + surfaceMesh = std::string(argv[1]); + + Map2 map; + cgogn::io::import_surface(map, surfaceMesh); + + { + // COUNTING DARTS SINGLE THREAD + unsigned int nb_darts = 0u; + { + std::chrono::time_point start, end; + start = std::chrono::system_clock::now(); + for (unsigned int i = 0u; i < ITERATIONS; ++i) + { + nb_darts = 0u; + map.foreach_dart([&nb_darts] (cgogn::Dart) { nb_darts++; }); + } + end = std::chrono::system_clock::now(); + std::chrono::duration elapsed_seconds = end - start; + std::cout << std::fixed << "SINGLE THREAD "<< elapsed_seconds.count() << "s || nb darts :" << nb_darts << std::endl; + } + // END COUNTING DARTS SINGLE THREAD + + // COUNTING DARTS MULTI-THREADS + unsigned int nb_darts_2 = 0u; + std::vector nb_darts_per_thread(cgogn::get_thread_pool()->get_nb_threads()); + { + std::chrono::time_point start, end; + start = std::chrono::system_clock::now(); + + for (unsigned int i = 0u; i < ITERATIONS; ++i) + { + for (auto& n : nb_darts_per_thread) + n = 0u; + nb_darts_2 = 0u; + // clock_gettime(CLOCK_REALTIME,&tbegin); + map.parallel_foreach_dart([&nb_darts_per_thread] (cgogn::Dart, unsigned int thread_index) + { + cgogn_assert(thread_index< 7); + nb_darts_per_thread[thread_index]++; + }); + // clock_gettime(CLOCK_REALTIME,&tend); + // std::cout << __FILE__ << ":" << __LINE__ << " : " << (1000000000u*(tend.tv_sec - tbegin.tv_sec) +tend.tv_nsec - tbegin.tv_nsec)/1000u << " microseconds."< elapsed_seconds = end - start; + std::cout << std::fixed << cgogn::NB_THREADS << " THREADS "<< elapsed_seconds.count() << "s || nb darts :" << nb_darts_2 << std::endl; + } + // END COUNTING DARTS MULTI-THREADS + + VertexAttributeHandler vertex_position = map.get_attribute("position"); + FaceAttributeHandler face_normal = map.add_attribute("normal"); + + + + // DART MARKING + { + std::chrono::time_point start, end; + start = std::chrono::system_clock::now(); + + for (unsigned int i = 0u ; i < ITERATIONS; ++i) + { + map.template foreach_cell([&] (Face f) + { + face_normal[f] = cgogn::geometry::face_normal(map, f, vertex_position); + }); + } + end = std::chrono::system_clock::now(); + std::chrono::duration elapsed_seconds = end - start; + std::cout << std::fixed << "SINGLE THREAD "<< elapsed_seconds.count() << "s || compute_normal_faces dart marking" << std::endl; + } + + { + std::chrono::time_point start, end; + start = std::chrono::system_clock::now(); + for (unsigned int i = 0u ; i < ITERATIONS; ++i) + { + map.template parallel_foreach_cell([&] (Face f, unsigned int) + { + face_normal[f] = cgogn::geometry::face_normal(map, f, vertex_position); + }); + } + + + end = std::chrono::system_clock::now(); + std::chrono::duration elapsed_seconds = end - start; + std::cout << std::fixed << cgogn::NB_THREADS << " THREADS "<< elapsed_seconds.count() << "s || compute_normal_faces dart marking" << std::endl; + } + + // END DART MARKING + + // CELL MARKING + + { + std::chrono::time_point start, end; + start = std::chrono::system_clock::now(); + + for (unsigned int i = 0u ; i < ITERATIONS; ++i) + { + map.template foreach_cell([&] (Face f) + { + face_normal[f] = cgogn::geometry::face_normal(map, f, vertex_position); + }); + } + end = std::chrono::system_clock::now(); + std::chrono::duration elapsed_seconds = end - start; + std::cout << std::fixed << "SINGLE THREAD "<< elapsed_seconds.count() << "s || compute_normal_faces cell marking" << std::endl; + } + + { + std::chrono::time_point start, end; + start = std::chrono::system_clock::now(); + for (unsigned int i = 0u ; i < ITERATIONS; ++i) + { + map.template parallel_foreach_cell([&] (Face f, unsigned int) + { + face_normal[f] = cgogn::geometry::face_normal(map, f, vertex_position); + }); + } + + + end = std::chrono::system_clock::now(); + std::chrono::duration elapsed_seconds = end - start; + std::cout << std::fixed << cgogn::NB_THREADS << " THREADS "<< elapsed_seconds.count() << "s || compute_normal_faces cell marking" << std::endl; + } + + // END CELL MARKING + + map.enable_topo_cache(); + + +// // TOPO CACHE + + { + std::chrono::time_point start, end; + start = std::chrono::system_clock::now(); + + for (unsigned int i = 0u ; i < ITERATIONS; ++i) + { + map.template foreach_cell([&] (Face f) + { + face_normal[f] = cgogn::geometry::face_normal(map, f, vertex_position); + }); + } + end = std::chrono::system_clock::now(); + std::chrono::duration elapsed_seconds = end - start; + std::cout << std::fixed << "SINGLE THREAD "<< elapsed_seconds.count() << "s || compute_normal_faces topo cache" << std::endl; + } + + { + std::chrono::time_point start, end; + start = std::chrono::system_clock::now(); + for (unsigned int i = 0u ; i < ITERATIONS; ++i) + { + map.template parallel_foreach_cell([&] (Face f, unsigned int) + { + face_normal[f] = cgogn::geometry::face_normal(map, f, vertex_position); + }); + } + + + end = std::chrono::system_clock::now(); + std::chrono::duration elapsed_seconds = end - start; + std::cout << std::fixed << cgogn::NB_THREADS << " THREADS "<< elapsed_seconds.count() << "s || compute_normal_faces topo cache" << std::endl; + } + } + + // END TOPO CACHE + + return 0; +} From dc3ba9145f2c2e5a03baabfeb6d62e4e74bed92a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 2 Feb 2016 17:12:20 +0100 Subject: [PATCH 030/402] fixed a bug in thread_pool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/utils/thread_pool.cpp | 6 +++--- cgogn/core/utils/thread_pool.h | 13 +++++++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/cgogn/core/utils/thread_pool.cpp b/cgogn/core/utils/thread_pool.cpp index f131ce86..faac692a 100644 --- a/cgogn/core/utils/thread_pool.cpp +++ b/cgogn/core/utils/thread_pool.cpp @@ -47,9 +47,10 @@ ThreadPool::~ThreadPool() worker.join(); } -ThreadPool::ThreadPool() : stop_(false) +ThreadPool::ThreadPool() + : stop_(false) { - for(unsigned int i = 0u; i< MAX_NB_THREADS ;++i) + for(unsigned int i = 0u; i< cgogn::get_nb_threads() -1u;++i) workers_.emplace_back( [this,i] { @@ -71,7 +72,6 @@ ThreadPool::ThreadPool() : stop_(false) task = std::move(this->tasks_.front()); this->tasks_.pop(); } - task(i); } } diff --git a/cgogn/core/utils/thread_pool.h b/cgogn/core/utils/thread_pool.h index acff6776..b8cca98b 100644 --- a/cgogn/core/utils/thread_pool.h +++ b/cgogn/core/utils/thread_pool.h @@ -48,12 +48,17 @@ class ThreadPool { ThreadPool& operator=(ThreadPool&&) = delete; template - auto enqueue(F&& f, Args&&... args) + auto enqueue(const F& f, Args&&... args) -> std::future::type>; std::vector get_threads_ids() const; virtual ~ThreadPool(); + inline std::size_t get_nb_threads() const + { + return workers_.size(); + } + private: // need to keep track of threads so we can join them std::vector< std::thread > workers_; @@ -69,14 +74,14 @@ class ThreadPool { // add new work item to the pool template -auto ThreadPool::enqueue(F&& f, Args&&... args) +auto ThreadPool::enqueue(const F& f, Args&&... args) -> std::future::type> { using return_type = typename std::result_of::type; - auto task = std::make_shared< std::packaged_task >([&](unsigned int i) + auto task = std::make_shared< std::packaged_task >([f,&args...](unsigned int i) { - return std::bind(std::forward(f), i, std::forward(args)...)(); + std::bind(std::cref(f),i, std::forward(args)...)(); } ); From 6d3439876017bcf870a23f6b221853c41f3a74f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 2 Feb 2016 17:12:40 +0100 Subject: [PATCH 031/402] using the thread pool everywhere ! MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/map_base.h | 206 ++++++++++++++++--------------------- 1 file changed, 88 insertions(+), 118 deletions(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index cfb8cb27..3b6804ab 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -567,24 +567,25 @@ class MapBase : public MapBaseData futures.reserve(nb_chunks); dart_buffers.reserve(nb_chunks); - Dart it = Dart(this->topology_.begin()); const Dart end = Dart(this->topology_.end()); - for (unsigned int i = 0u; i < nb_chunks; ++i) + for (unsigned int i = 0u; i < nb_chunks && it != end; ++i) { dart_buffers.push_back(dbuffs->get_buffer()); - std::vector& darts(*dart_buffers.back()); - darts.reserve(PARALLEL_BUFFER_SIZE); - for (unsigned j = 0; j < PARALLEL_BUFFER_SIZE && it != end; ++j) + std::vector* darts = dart_buffers.back(); + darts->reserve(PARALLEL_BUFFER_SIZE); + for (unsigned j = 0u; j < PARALLEL_BUFFER_SIZE && it != end; ++j) { - darts.push_back(it); + darts->push_back(it); this->topology_.next(it.index); } - futures.emplace_back(thread_pool->enqueue( [&darts,&f](unsigned int i){ - for (auto d : darts) - f(d,i); + + futures.push_back(thread_pool->enqueue( [darts ,&f](unsigned int k){ + for (auto d : (*darts)) + f(d,k); })); + } for (auto& fu: futures) @@ -649,7 +650,7 @@ class MapBase : public MapBaseData } template - inline void parallel_foreach_cell(const FUNC& f, unsigned int nb_threads = NB_THREADS - 1) const + inline void parallel_foreach_cell(const FUNC& f) const { static_assert(check_func_ith_parameter_type(FUNC, 0, Cell), "Wrong function first parameter type"); static_assert(check_func_ith_parameter_type(FUNC, 1, unsigned int), "Wrong function second parameter type"); @@ -657,21 +658,21 @@ class MapBase : public MapBaseData switch (STRATEGY) { case FORCE_DART_MARKING : - parallel_foreach_cell_dart_marking(f, nb_threads); + parallel_foreach_cell_dart_marking(f); break; case FORCE_CELL_MARKING : parallel_foreach_cell_cell_marking(f); break; case FORCE_TOPO_CACHE : - parallel_foreach_cell_topo_cache(f, nb_threads); + parallel_foreach_cell_topo_cache(f); break; case AUTO : if (is_topo_cache_enabled()) - parallel_foreach_cell_topo_cache(f, nb_threads); + parallel_foreach_cell_topo_cache(f); else if (this->template is_orbit_embedded()) parallel_foreach_cell_cell_marking(f); else - parallel_foreach_cell_dart_marking(f, nb_threads); + parallel_foreach_cell_dart_marking(f); break; } } @@ -729,72 +730,51 @@ class MapBase : public MapBaseData } template - inline void parallel_foreach_cell_dart_marking(const FUNC& f, unsigned int nb_threads) const + inline void parallel_foreach_cell_dart_marking(const FUNC& f) const { - // these vectors will contain elements to be processed by the threads - // the first ones are passed to the threads - // the second ones are filled by this thread while the other are processed - std::vector>> vd1(nb_threads); - std::vector>> vd2(nb_threads); - for (unsigned int i = 0; i < nb_threads; ++i) - { - vd1[i].reserve(PARALLEL_BUFFER_SIZE); - vd2[i].reserve(PARALLEL_BUFFER_SIZE); - } - - bool finished = false; - - // creation of threads - Barrier sync1(nb_threads + 1); - Barrier sync2(nb_threads + 1); - - auto thread_deleter = [this] (std::thread* th) { const std::thread::id id = th->get_id(); th->join(); delete th; this->remove_thread(id); }; + using VecCell = std::vector>; + using Future = std::future< typename std::result_of, unsigned int)>::type >; - using thread_ptr = std::unique_ptr; - using ThreadFunc = ThreadFunction, FUNC>; - using tfs_ptr = std::unique_ptr; + std::vector cells_buffers; + std::vector futures; + cells_buffers.reserve(512u); + futures.reserve(512u); - std::vector threads; - std::vector tfs; - threads.reserve(nb_threads); - tfs.reserve(nb_threads); - for (unsigned int i = 0u; i < nb_threads; ++i) - { - tfs.emplace_back(tfs_ptr(new ThreadFunc(f, vd1[i], sync1, sync2, finished, i))); - threads.emplace_back(thread_ptr(new std::thread(std::ref( *(tfs[i]) )), thread_deleter)); - this->add_thread(threads.back()->get_id()); - } + ThreadPool* thread_pool = cgogn::get_thread_pool(); + Buffers* dbuffs = cgogn::get_dart_buffers(); DartMarker dm(*to_concrete()); Dart it = Dart(this->topology_.begin()); - Dart end = Dart(this->topology_.end()); + const Dart end = Dart(this->topology_.end()); + while (it != end) { - for (unsigned int i = 0; i < nb_threads; ++i) - vd2[i].clear(); + const unsigned int index = cells_buffers.size(); + cells_buffers.push_back(dbuffs->template get_cell_buffer>()); + VecCell& cells = *cells_buffers.back(); + cells.reserve(PARALLEL_BUFFER_SIZE); - // fill vd2 vectors - unsigned int nb = 0; - while (it != end && nb < nb_threads * PARALLEL_BUFFER_SIZE) + for (unsigned int j = 0u ; j < PARALLEL_BUFFER_SIZE && it != end;) { if (!dm.is_marked(it)) { dm.template mark_orbit(it); - vd2[nb % nb_threads].push_back(Cell(it)); - ++nb; + cells.push_back(Cell(it)); + ++j; } this->topology_.next(it.index); } - - for (unsigned int i = 0; i < nb_threads; ++i) - vd1[i].swap(vd2[i]); - - sync2.wait(); // vectors are ready for threads to process - sync1.wait(); // wait for all threads to finish their vector + futures.emplace_back(thread_pool->enqueue( [&cells_buffers,&f,index](unsigned int i){ + for (auto c : *(cells_buffers[index])) + f(c,i); + })); } - - finished = true; // say finish to all threads - sync2.wait(); // last barrier wait + for (auto& fu: futures) + { + fu.wait(); + } + for (auto &b : cells_buffers) + dbuffs->release_cell_buffer(b); } template @@ -820,20 +800,25 @@ class MapBase : public MapBaseData using Future = std::future< typename std::result_of, unsigned int)>::type >; const unsigned int nb_chunks = this->nb_cells()/PARALLEL_BUFFER_SIZE + 1u; - ThreadPool* thread_pool = cgogn::get_thread_pool(); - std::vector vd(nb_chunks); + std::vector cells_buffers; std::vector futures; + cells_buffers.reserve(nb_chunks); futures.reserve(nb_chunks); + ThreadPool* thread_pool = cgogn::get_thread_pool(); + Buffers* dbuffs = cgogn::get_dart_buffers(); + CellMarker cm(*to_concrete()); Dart it = Dart(this->topology_.begin()); const Dart end = Dart(this->topology_.end()); for (unsigned int i = 0u; i < nb_chunks; ++i) { - VecCell& cells = vd[i]; + cells_buffers.push_back(dbuffs->template get_cell_buffer>()); + VecCell& cells = *cells_buffers.back(); cells.reserve(PARALLEL_BUFFER_SIZE); + for (unsigned int j = 0u; j < PARALLEL_BUFFER_SIZE && it != end;) { if (!cm.is_marked(it)) @@ -844,16 +829,18 @@ class MapBase : public MapBaseData } this->topology_.next(it.index); } - futures.emplace_back(thread_pool->enqueue( [&](unsigned int i){ - const VecCell& vec_cells = cells; - for (auto d : vec_cells) - f(d,i); + futures.emplace_back(thread_pool->enqueue( [&cells,&f](unsigned int i){ + for (auto c : cells) + f(c,i); })); } + for (auto& fu: futures) { fu.wait(); } + for (auto &b : cells_buffers) + dbuffs->release_cell_buffer(b); } template @@ -868,67 +855,50 @@ class MapBase : public MapBaseData } template - inline void parallel_foreach_cell_topo_cache(const FUNC& f, unsigned int nb_threads) const + inline void parallel_foreach_cell_topo_cache(const FUNC& f) const { - // these vectors will contain elements to be processed by the threads - // the first ones are passed to the threads - // the second ones are filled by this thread while the other are processed - std::vector>> vd1(nb_threads); - std::vector>> vd2(nb_threads); - for (unsigned int i = 0; i < nb_threads; ++i) - { - vd1[i].reserve(PARALLEL_BUFFER_SIZE); - vd2[i].reserve(PARALLEL_BUFFER_SIZE); - } + using VecCell = std::vector>; + using Future = std::future< typename std::result_of, unsigned int)>::type >; - bool finished = false; + const unsigned int nb_chunks = this->nb_cells()/PARALLEL_BUFFER_SIZE + 1u; - // creation of threads - Barrier sync1(nb_threads + 1); - Barrier sync2(nb_threads + 1); + std::vector cells_buffers; + std::vector futures; + cells_buffers.reserve(nb_chunks); + futures.reserve(nb_chunks); - auto thread_deleter = [this] (std::thread* th) { const std::thread::id id = th->get_id(); th->join(); delete th; this->remove_thread(id); }; + ThreadPool* thread_pool = cgogn::get_thread_pool(); + Buffers* dbuffs = cgogn::get_dart_buffers(); - using thread_ptr = std::unique_ptr; - using ThreadFunc = ThreadFunction, FUNC>; - using tfs_ptr = std::unique_ptr; + unsigned int it = this->attributes_[ORBIT].begin(); + const unsigned int end = this->attributes_[ORBIT].end(); - std::vector threads; - std::vector tfs; - threads.reserve(nb_threads); - tfs.reserve(nb_threads); - for (unsigned int i = 0; i < nb_threads; ++i) - { - tfs.emplace_back(tfs_ptr(new ThreadFunc(f, vd1[i], sync1, sync2, finished, i))); - threads.emplace_back(thread_ptr(new std::thread(std::ref( *(tfs[i]) )), thread_deleter)); - this->add_thread(threads.back()->get_id()); - } + const auto& cache = *(this->global_topo_cache_[ORBIT]); + const auto& attr = this->attributes_[ORBIT]; - unsigned int it = this->attributes_[ORBIT].begin(); - unsigned int end = this->attributes_[ORBIT].end(); - while (it != end) + for (unsigned int i = 0u; i < nb_chunks; ++i) { - for (unsigned int i = 0; i < nb_threads; ++i) - vd2[i].clear(); + cells_buffers.push_back(dbuffs->template get_cell_buffer>()); + VecCell& cells = *cells_buffers.back(); + cells.reserve(PARALLEL_BUFFER_SIZE); - // fill vd2 vectors - unsigned int nb = 0; - while (it != end && nb < nb_threads * PARALLEL_BUFFER_SIZE) + for (unsigned int j = 0u; j < PARALLEL_BUFFER_SIZE && it != end; ++j) { - vd2[nb % nb_threads].push_back(Cell((*this->global_topo_cache_[ORBIT])[it])); - ++nb; - this->attributes_[ORBIT].next(it); + cells.push_back(cache[it]); + attr.next(it); } - - for (unsigned int i = 0; i < nb_threads; ++i) - vd1[i].swap(vd2[i]); - - sync2.wait(); // vectors are ready for threads to process - sync1.wait(); // wait for all threads to finish their vector + futures.emplace_back(thread_pool->enqueue( [&cells,&f](unsigned int i){ + for (auto c : cells) + f(c,i); + })); } - finished = true; // say finish to all threads - sync2.wait(); // last barrier wait + for (auto& fu: futures) + { + fu.wait(); + } + for (auto &b : cells_buffers) + dbuffs->release_cell_buffer(b); } template From 2facd984e70e320e208fe3d8d93e386a9023fcad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 2 Feb 2016 17:23:09 +0100 Subject: [PATCH 032/402] checking normals in the multithreading bench MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- .../multithreading/bench_multithreading.cpp | 57 +++++++++++++++++-- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/benchmarks/multithreading/bench_multithreading.cpp b/benchmarks/multithreading/bench_multithreading.cpp index 5e021072..ab3c7a66 100644 --- a/benchmarks/multithreading/bench_multithreading.cpp +++ b/benchmarks/multithreading/bench_multithreading.cpp @@ -117,6 +117,7 @@ int main(int argc, char** argv) VertexAttributeHandler vertex_position = map.get_attribute("position"); FaceAttributeHandler face_normal = map.add_attribute("normal"); + FaceAttributeHandler face_normal_mt = map.add_attribute("normal_mt"); @@ -144,7 +145,7 @@ int main(int argc, char** argv) { map.template parallel_foreach_cell([&] (Face f, unsigned int) { - face_normal[f] = cgogn::geometry::face_normal(map, f, vertex_position); + face_normal_mt[f] = cgogn::geometry::face_normal(map, f, vertex_position); }); } @@ -154,9 +155,23 @@ int main(int argc, char** argv) std::cout << std::fixed << cgogn::NB_THREADS << " THREADS "<< elapsed_seconds.count() << "s || compute_normal_faces dart marking" << std::endl; } - // END DART MARKING + // END DART MARKING + + { + // CHECKING NORMALS + map.template foreach_cell([&] (Face f) + { + Vec3 error = face_normal[f] - face_normal_mt[f]; + if (!cgogn::almost_equal_absolute(error.squaredNorm(), 0., 1e-9 )) + { + std::cerr << __FILE__ << ":" << __LINE__ << " : there was an error during computation of normals" << std::endl; + std::abort; + } + + }); + } - // CELL MARKING + // CELL MARKING { std::chrono::time_point start, end; @@ -181,7 +196,7 @@ int main(int argc, char** argv) { map.template parallel_foreach_cell([&] (Face f, unsigned int) { - face_normal[f] = cgogn::geometry::face_normal(map, f, vertex_position); + face_normal_mt[f] = cgogn::geometry::face_normal(map, f, vertex_position); }); } @@ -193,6 +208,21 @@ int main(int argc, char** argv) // END CELL MARKING + + { + // CHECKING NORMALS + map.template foreach_cell([&] (Face f) + { + Vec3 error = face_normal[f] - face_normal_mt[f]; + if (!cgogn::almost_equal_absolute(error.squaredNorm(), 0., 1e-9 )) + { + std::cerr << __FILE__ << ":" << __LINE__ << " : there was an error during computation of normals" << std::endl; + std::abort; + } + + }); + } + map.enable_topo_cache(); @@ -221,7 +251,7 @@ int main(int argc, char** argv) { map.template parallel_foreach_cell([&] (Face f, unsigned int) { - face_normal[f] = cgogn::geometry::face_normal(map, f, vertex_position); + face_normal_mt[f] = cgogn::geometry::face_normal(map, f, vertex_position); }); } @@ -230,9 +260,24 @@ int main(int argc, char** argv) std::chrono::duration elapsed_seconds = end - start; std::cout << std::fixed << cgogn::NB_THREADS << " THREADS "<< elapsed_seconds.count() << "s || compute_normal_faces topo cache" << std::endl; } + + // END TOPO CACHE + { + // CHECKING NORMALS + map.template foreach_cell([&] (Face f) + { + Vec3 error = face_normal[f] - face_normal_mt[f]; + if (!cgogn::almost_equal_absolute(error.squaredNorm(), 0., 1e-9 )) + { + std::cerr << __FILE__ << ":" << __LINE__ << " : there was an error during computation of normals" << std::endl; + std::abort; + } + + }); + } } - // END TOPO CACHE + return 0; } From 87254fdbc8886a2c04ac8af83370b46815eec498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 2 Feb 2016 18:05:00 +0100 Subject: [PATCH 033/402] thread_pool license MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/utils/thread_pool.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/cgogn/core/utils/thread_pool.h b/cgogn/core/utils/thread_pool.h index b8cca98b..e48c8f25 100644 --- a/cgogn/core/utils/thread_pool.h +++ b/cgogn/core/utils/thread_pool.h @@ -21,6 +21,38 @@ * * *******************************************************************************/ +/* + * IMPORTANT : The ThreadPool code (thread_pool.h and thread_pool.cpp) is + * based on "A Simple c++11 threadpool implementation" found on github + * (https://github.com/progschj/ThreadPool, latest commit : 9a42ec1 ) + * (c) 2012 Jakob Progsch, Václav Zeman + * It has been modified to fit to our purposes. + * A copy of its license is provided in the following lines. + */ + +/**************************************************************************** +*Copyright (c) 2012 Jakob Progsch, Václav Zeman * +* * +*This software is provided 'as-is', without any express or implied * +*warranty. In no event will the authors be held liable for any damages * +*arising from the use of this software. * +* * +*Permission is granted to anyone to use this software for any purpose, * +*including commercial applications, and to alter it and redistribute it * +*freely, subject to the following restrictions: * +* * +*1. The origin of this software must not be misrepresented; you must not * +*claim that you wrote the original software. If you use this software * +*in a product, an acknowledgment in the product documentation would be * +*appreciated but is not required. * +* * +*2. Altered source versions must be plainly marked as such, and must not be * +*misrepresented as being the original software. * +* * +*3. This notice may not be removed or altered from any source * +*distribution. * +****************************************************************************/ + #ifndef CORE_UTILS_THREADPOOL_H_ #define CORE_UTILS_THREADPOOL_H_ From c75175f391f42c1c31079f301fa7c964453da46a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 2 Feb 2016 18:37:49 +0100 Subject: [PATCH 034/402] added CGOGN_UTILS_API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/utils/thread_pool.cpp | 2 ++ cgogn/core/utils/thread_pool.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/cgogn/core/utils/thread_pool.cpp b/cgogn/core/utils/thread_pool.cpp index faac692a..b806e0f6 100644 --- a/cgogn/core/utils/thread_pool.cpp +++ b/cgogn/core/utils/thread_pool.cpp @@ -21,6 +21,8 @@ * * *******************************************************************************/ +#define CGOGN_UTILS_DLL_EXPORT + #include namespace cgogn diff --git a/cgogn/core/utils/thread_pool.h b/cgogn/core/utils/thread_pool.h index e48c8f25..caa81728 100644 --- a/cgogn/core/utils/thread_pool.h +++ b/cgogn/core/utils/thread_pool.h @@ -71,7 +71,7 @@ namespace cgogn { -class ThreadPool { +class CGOGN_UTILS_API ThreadPool { public: ThreadPool(); ThreadPool(const ThreadPool&) = delete; From 0333bc99bbdeb8b5f9d92267ceb050db8031e4d4 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Wed, 3 Feb 2016 14:28:42 +0100 Subject: [PATCH 035/402] added function normalize_safe Signed-off-by: Etienne Schmitt --- cgogn/geometry/algos/normal.h | 90 ++++++++++++++++--------------- cgogn/geometry/functions/basics.h | 53 ++++++++++++++++++ 2 files changed, 100 insertions(+), 43 deletions(-) create mode 100644 cgogn/geometry/functions/basics.h diff --git a/cgogn/geometry/algos/normal.h b/cgogn/geometry/algos/normal.h index fd164361..a00a8799 100644 --- a/cgogn/geometry/algos/normal.h +++ b/cgogn/geometry/algos/normal.h @@ -24,113 +24,117 @@ #ifndef GEOMETRY_ALGOS_NORMAL_H_ #define GEOMETRY_ALGOS_NORMAL_H_ +#include #include + #include +#include #include + namespace cgogn { namespace geometry { -template -inline VEC3_T triangle_normal(const MAP& map, Cell f, const typename MAP::template VertexAttributeHandler& position) +template +inline VEC3 triangle_normal(const MAP& map, Cell f, const typename MAP::template VertexAttributeHandler& position) { - VEC3_T n = triangle_normal( + VEC3 n = triangle_normal( position[f.dart], position[map.phi1(f.dart)], position[map.phi_1(f.dart)] ); - n.normalize(); + normalize_safe(n); return n; } -template -inline VEC3_T newell_normal(const MAP& map, Cell f, const typename MAP::template VertexAttributeHandler& position) +template +inline VEC3 newell_normal(const MAP& map, Cell f, const typename MAP::template VertexAttributeHandler& position) { - VEC3_T n{0.,0.,0.}; + VEC3 n{0.,0.,0.}; map.foreach_incident_vertex(f, [&] (Cell v) { - const VEC3_T& p = position[v.dart]; - const VEC3_T& q = position[map.phi1(v.dart)]; + const VEC3& p = position[v.dart]; + const VEC3& q = position[map.phi1(v.dart)]; n[0] += (p[1] - q[1]) * (p[2] + q[2]); n[1] += (p[2] - q[2]) * (p[0] + q[0]); n[2] += (p[0] - q[0]) * (p[1] + q[1]); }); - n.normalize(); + normalize_safe(n); return n; } -template -inline VEC3_T face_normal(const MAP& map, Cell f, const typename MAP::template VertexAttributeHandler& position) +template +inline VEC3 face_normal(const MAP& map, Cell f, const typename MAP::template VertexAttributeHandler& position) { if (map.degree(f) == 3) - return triangle_normal(map, f, position); + return triangle_normal(map, f, position); else - return newell_normal(map, f, position); + return newell_normal(map, f, position); } -template -inline VEC3_T vertex_normal(const MAP& map, Cell v, const typename MAP::template VertexAttributeHandler& position) +template +inline VEC3 vertex_normal(const MAP& map, Cell v, const typename MAP::template VertexAttributeHandler& position) { - VEC3_T n{0,0,0}; - const VEC3_T& p = position[v.dart]; + VEC3 n{0,0,0}; + const VEC3& p = position[v.dart]; map.foreach_incident_face(v, [&] (Cell f) { - VEC3_T facen = face_normal(map, f, position); - const VEC3_T& p1 = position[map.phi1(f.dart)]; - const VEC3_T& p2 = position[map.phi_1(f.dart)]; - typename VEC3_T::Scalar l = (p1-p).squaredNorm() * (p2-p).squaredNorm(); - facen *= convex_face_area(map, f, position) / l; + VEC3 facen = face_normal(map, f, position); + const VEC3& p1 = position[map.phi1(f.dart)]; + const VEC3& p2 = position[map.phi_1(f.dart)]; + typename VEC3::Scalar l = (p1-p).squaredNorm() * (p2-p).squaredNorm(); + facen *= convex_face_area(map, f, position) / l; n += facen; }); - n.normalize(); + normalize_safe(n); return n; } -template -inline VEC3_T vertex_normal(const MAP& map, Cell v, const typename MAP::template VertexAttributeHandler& position, const typename MAP::template AttributeHandler& fnormal) +template +inline VEC3 vertex_normal(const MAP& map, Cell v, const typename MAP::template VertexAttributeHandler& position, const typename MAP::template AttributeHandler& fnormal) { - VEC3_T n{0,0,0}; - const VEC3_T& p = position[v.dart]; + VEC3 n{0,0,0}; + const VEC3& p = position[v.dart]; map.foreach_incident_face(v, [&] (Cell f) { - VEC3_T facen = fnormal[f]; - const VEC3_T& p1 = position[map.phi1(f.dart)]; - const VEC3_T& p2 = position[map.phi_1(f.dart)]; - typename VEC3_T::Scalar l = (p1-p).squaredNorm() * (p2-p).squaredNorm(); - facen *= convex_face_area(map, f, position) / l; + VEC3 facen = fnormal[f]; + const VEC3& p1 = position[map.phi1(f.dart)]; + const VEC3& p2 = position[map.phi_1(f.dart)]; + typename VEC3::Scalar l = (p1-p).squaredNorm() * (p2-p).squaredNorm(); + facen *= convex_face_area(map, f, position) / l; n += facen; }); - n.normalize(); + normalize_safe(n); return n; } -template -inline void compute_normal_faces(MAP& map, const typename MAP::template VertexAttributeHandler& position, typename MAP::template AttributeHandler& normal) +template +inline void compute_normal_faces(MAP& map, const typename MAP::template VertexAttributeHandler& position, typename MAP::template AttributeHandler& normal) { map.template parallel_foreach_cell([&] (Cell f, unsigned int) { - normal[f] = face_normal(map, f, position); + normal[f] = face_normal(map, f, position); }); } -template -inline void compute_normal_vertices(MAP& map, const typename MAP::template VertexAttributeHandler& position, typename MAP::template AttributeHandler& normal) +template +inline void compute_normal_vertices(MAP& map, const typename MAP::template VertexAttributeHandler& position, typename MAP::template AttributeHandler& normal) { map.template parallel_foreach_cell([&] (Cell v, unsigned int) { - normal[v] = vertex_normal(map, v, position); + normal[v] = vertex_normal(map, v, position); }); } -template -inline void compute_normal_vertices(MAP& map, const typename MAP::template VertexAttributeHandler& position, const typename MAP::template AttributeHandler& fnormal, typename MAP::template AttributeHandler& normal) +template +inline void compute_normal_vertices(MAP& map, const typename MAP::template VertexAttributeHandler& position, const typename MAP::template AttributeHandler& fnormal, typename MAP::template AttributeHandler& normal) { map.template parallel_foreach_cell([&] (Cell v, unsigned int) { - normal[v] = vertex_normal(map, v, position, fnormal); + normal[v] = vertex_normal(map, v, position, fnormal); }); } diff --git a/cgogn/geometry/functions/basics.h b/cgogn/geometry/functions/basics.h new file mode 100644 index 00000000..225cd7a9 --- /dev/null +++ b/cgogn/geometry/functions/basics.h @@ -0,0 +1,53 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef GEOMETRY_FUNCTIONS_BASICS_H_ +#define GEOMETRY_FUNCTIONS_BASICS_H_ + +#include + +namespace cgogn +{ + +namespace geometry +{ + +/** + * @brief normalize_safe, normalize a non-zero vector + * @param v + */ +template +inline void normalize_safe(VEC3& v) +{ + using Scalar = typename VEC3::Scalar; + + const Scalar norm2 = v.squaredNorm(); + if (norm2 > Scalar(0)) + v/=std::sqrt(norm2); +} + +} // namespace geometry + +} // namespace cgogn + +#endif // GEOMETRY_FUNCTIONS_BASICS_H_ From baa19e6344cb1dd51a8fac5f0dcf342833a28c55 Mon Sep 17 00:00:00 2001 From: Lionel Untereiner Date: Thu, 4 Feb 2016 10:58:32 +0100 Subject: [PATCH 036/402] moving cph out of the core. The core should not be so big and MULTIR should not pollute MONOR people. --- cgogn/multiresolution/CMakeLists.txt | 43 ++++++++ .../cph/attribute_handler_cph.h | 0 cgogn/{core => multiresolution}/cph/ihcmap2.h | 0 .../cph/ihcmap2_adaptive.h | 0 .../cph/ihcmap2_regular.h | 0 cgogn/multiresolution/cph/ihcmap_base.cpp | 29 +++++ .../cph/ihcmap_base.h | 0 cgogn/multiresolution/examples/CMakeLists.txt | 11 ++ .../examples/cph/CMakeLists.txt | 6 + cgogn/multiresolution/examples/cph/cph2.cpp | 78 +++++++++++++ .../mranalysis/lerp_triquad_mra.h | 103 ++++++++++++++++++ 11 files changed, 270 insertions(+) create mode 100644 cgogn/multiresolution/CMakeLists.txt rename cgogn/{core => multiresolution}/cph/attribute_handler_cph.h (100%) rename cgogn/{core => multiresolution}/cph/ihcmap2.h (100%) rename cgogn/{core => multiresolution}/cph/ihcmap2_adaptive.h (100%) rename cgogn/{core => multiresolution}/cph/ihcmap2_regular.h (100%) create mode 100644 cgogn/multiresolution/cph/ihcmap_base.cpp rename cgogn/{core => multiresolution}/cph/ihcmap_base.h (100%) create mode 100644 cgogn/multiresolution/examples/CMakeLists.txt create mode 100644 cgogn/multiresolution/examples/cph/CMakeLists.txt create mode 100644 cgogn/multiresolution/examples/cph/cph2.cpp create mode 100644 cgogn/multiresolution/mranalysis/lerp_triquad_mra.h diff --git a/cgogn/multiresolution/CMakeLists.txt b/cgogn/multiresolution/CMakeLists.txt new file mode 100644 index 00000000..ced12802 --- /dev/null +++ b/cgogn/multiresolution/CMakeLists.txt @@ -0,0 +1,43 @@ +project(cgogn_multiresolution + LANGUAGES CXX +) + +set(HEADER_FILES + cph/attribute_handler_cph.h + cph/ihcmap_base.h + cph/ihcmap2.h + cph/ihcmap2_adaptive.h + cph/ihcmap2_regular.h + + mranalysis/lerp_triquad_mra.h +) + +set(SOURCE_FILES + cph/ihcmap_base.cpp +) + +add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) + +set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "_d") + +target_include_directories(${PROJECT_NAME} PUBLIC + $ + $ + $ +) + +target_link_libraries(${PROJECT_NAME} cgogn_core cgogn_geometry) + +install(DIRECTORY . + DESTINATION include/cgogn/multiresolution + FILES_MATCHING PATTERN "*.h" +) + +install(TARGETS ${PROJECT_NAME} + EXPORT ${PROJECT_NAME}Targets + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib +) + +add_subdirectory(examples) diff --git a/cgogn/core/cph/attribute_handler_cph.h b/cgogn/multiresolution/cph/attribute_handler_cph.h similarity index 100% rename from cgogn/core/cph/attribute_handler_cph.h rename to cgogn/multiresolution/cph/attribute_handler_cph.h diff --git a/cgogn/core/cph/ihcmap2.h b/cgogn/multiresolution/cph/ihcmap2.h similarity index 100% rename from cgogn/core/cph/ihcmap2.h rename to cgogn/multiresolution/cph/ihcmap2.h diff --git a/cgogn/core/cph/ihcmap2_adaptive.h b/cgogn/multiresolution/cph/ihcmap2_adaptive.h similarity index 100% rename from cgogn/core/cph/ihcmap2_adaptive.h rename to cgogn/multiresolution/cph/ihcmap2_adaptive.h diff --git a/cgogn/core/cph/ihcmap2_regular.h b/cgogn/multiresolution/cph/ihcmap2_regular.h similarity index 100% rename from cgogn/core/cph/ihcmap2_regular.h rename to cgogn/multiresolution/cph/ihcmap2_regular.h diff --git a/cgogn/multiresolution/cph/ihcmap_base.cpp b/cgogn/multiresolution/cph/ihcmap_base.cpp new file mode 100644 index 00000000..99fde37e --- /dev/null +++ b/cgogn/multiresolution/cph/ihcmap_base.cpp @@ -0,0 +1,29 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +namespace cgogn +{ + + + +} // namespace cgogn diff --git a/cgogn/core/cph/ihcmap_base.h b/cgogn/multiresolution/cph/ihcmap_base.h similarity index 100% rename from cgogn/core/cph/ihcmap_base.h rename to cgogn/multiresolution/cph/ihcmap_base.h diff --git a/cgogn/multiresolution/examples/CMakeLists.txt b/cgogn/multiresolution/examples/CMakeLists.txt new file mode 100644 index 00000000..c3c91cb9 --- /dev/null +++ b/cgogn/multiresolution/examples/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.0 FATAL_ERROR) + +project(cgogn_multiresolution_examples + LANGUAGES CXX +) + +set(CGOGN_TEST_PREFIX "test_") +set(CGOGN_TEST_MESHES_PATH "${CMAKE_SOURCE_DIR}/data/") +add_definitions("-DCGOGN_TEST_MESHES_PATH=${CGOGN_TEST_MESHES_PATH}") + +add_subdirectory(cph) diff --git a/cgogn/multiresolution/examples/cph/CMakeLists.txt b/cgogn/multiresolution/examples/cph/CMakeLists.txt new file mode 100644 index 00000000..c6c62399 --- /dev/null +++ b/cgogn/multiresolution/examples/cph/CMakeLists.txt @@ -0,0 +1,6 @@ +project(${CGOGN_TEST_PREFIX}cph2 + LANGUAGES CXX +) + +add_executable(cph2 cph2.cpp) +target_link_libraries(cph2 cgogn_core cgogn_io cgogn_multiresolution) diff --git a/cgogn/multiresolution/examples/cph/cph2.cpp b/cgogn/multiresolution/examples/cph/cph2.cpp new file mode 100644 index 00000000..a6618dd9 --- /dev/null +++ b/cgogn/multiresolution/examples/cph/cph2.cpp @@ -0,0 +1,78 @@ + +#include + +using namespace cgogn; + +using IHMap2 = IHCMap2Regular; + + +template +using VertexAttributeHandler = IHMap2::VertexAttributeHandler; + + +int main() +{ + IHMap2 map; + + // VertexAttributeHandler vertex_position_ = map.get_attribute("position"); + + map.add_face(4); + + std::cout << "before add level Faces :" << std::endl; + map.template foreach_cell([&] (typename IHMap2::Face v) + { + std::cout << v << std::endl; + }); + std::cout << "End Faces" << std::endl; + + + { + map.add_mixed_level(); + + std::cout << "after add level Faces :" << std::endl; + map.template foreach_cell([&] (typename IHMap2::Face f) + { + std::cout << f << " | " << map.get_dart_level(f.dart) << std::endl; + }); + std::cout << "End Faces" << std::endl; + + + unsigned int cur = map.get_current_level(); + + std::cout << "current level = " << cur << std::endl; + map.set_current_level(cur - 1); + + std::cout << "after add level Faces :" << std::endl; + map.template foreach_cell([&] (typename IHMap2::Face f) + { + std::cout << f << " | " << map.get_dart_level(f.dart) << std::endl; + }); + std::cout << "End Vertices" << std::endl; + } + + { + map.add_mixed_level(); + + std::cout << "after add level Faces :" << std::endl; + map.template foreach_cell([&] (typename IHMap2::Face f) + { + std::cout << f << " | " << map.get_dart_level(f.dart) << std::endl; + }); + std::cout << "End Faces" << std::endl; + + + unsigned int cur = map.get_current_level(); + + std::cout << "current level = " << cur << std::endl; + map.set_current_level(cur - 1); + + std::cout << "after add level Faces :" << std::endl; + map.template foreach_cell([&] (typename IHMap2::Face f) + { + std::cout << f << " | " << map.get_dart_level(f.dart) << std::endl; + }); + std::cout << "End Vertices" << std::endl; + } + + return 0; +} diff --git a/cgogn/multiresolution/mranalysis/lerp_triquad_mra.h b/cgogn/multiresolution/mranalysis/lerp_triquad_mra.h new file mode 100644 index 00000000..0b9e3da6 --- /dev/null +++ b/cgogn/multiresolution/mranalysis/lerp_triquad_mra.h @@ -0,0 +1,103 @@ +#ifndef MRA_H +#define MRA_H + + +template +class LerpTriQuadMRAnalysis +{ + + MRMAP& map_; + typename MRMAP::VertexAttribute va_; + + LerpTriQuadMRAnalysis(MRMAP& map): + map_(map) + { + synthesis_filters_.emplace_back(lerp_quad_odd_synthesis_); + } + +protected: + std::vector> synthesis_filters_; + std::vector> analysis_filters_; + +protected: + + std::function lerp_tri_quad_odd_synthesis_ = [] () + { + map_.template foreach_cell([&] (typename MRMAP::Face f) + { + if(map_.degree(f) != 3) + { + VEC3 vf(0.0); + VEC3 ef(0.0); + + unsigned int count = 0; + + map_.template foreach_incident_edge(f, [&] (typename MRMAP::Edge e) + { + vf += v[e]; + map_.incCurrentLevel(); + ef += v[map_.phi1(e)]; + map_.decCurrentLevel(); + ++count; + }); + + ef /= count; + ef *= 2.0; + + vf /= count; + + map_.incCurrentLevel() ; + Dart midF = map_.phi1(map_.phi1(f)); + m_position[midF] += vf + ef ; + map_.decCurrentLevel() ; + } + }); + + map_.template foreach_cell([&] (typename MRMAP::Edge e) + { + VEC3 ve = (v[e] + v[map_.phi1(e)]) * typename VEC3::TYPE(0.5); + + map_.incCurrentLevel() ; + Dart midV = map_.phi1(e) ; + m_position[midV] += ve ; + map_.decCurrentLevel() ; + }); + }; + +public: + + inline set_attribute(typename MRMAP::VertexAttribute& v) + { + va_ = v; + } + + void analysis() + { + cgogn_message_assert(map_.get_current_level() > 0, "analysis : called on level 0") ; + + map_.dec_current_level() ; + + for(unsigned int i = 0; i < analysis_filters_.size(); ++i) + (*analysis_filters_[i])() ; + } + + void synthesis() + { + cgogn_message_assert(map_.getCurrentLevel() < map_.getMaxLevel(), "synthesis : called on max level") ; + + for(unsigned int i = 0; i < synthesis_filters_.size(); ++i) + (*synthesis_filters_[i])() ; + + map_.incCurrentLevel(); + } + + void add_level() + { + map_.add_mixed_level(); + } + +}; + + +#endif // MRA_H + From f383c077b579d64bb02aeeb04fece5f8bca5c634 Mon Sep 17 00:00:00 2001 From: Lionel Untereiner Date: Thu, 4 Feb 2016 11:00:35 +0100 Subject: [PATCH 037/402] changes to structure next --- cgogn/CMakeLists.txt | 1 + cgogn/core/CMakeLists.txt | 6 - cgogn/core/examples/CMakeLists.txt | 1 - cgogn/core/examples/cph/CMakeLists.txt | 9 - cgogn/core/examples/cph/cph2.cpp | 78 -- .../cph/attribute_handler_cph.h | 130 +-- cgogn/multiresolution/cph/ihcmap2.h | 213 ++-- cgogn/multiresolution/cph/ihcmap2_adaptive.h | 916 +++++++++--------- cgogn/multiresolution/cph/ihcmap2_regular.h | 364 +++---- cgogn/multiresolution/cph/ihcmap_base.h | 48 +- cgogn/multiresolution/examples/cph/cph2.cpp | 2 +- 11 files changed, 860 insertions(+), 908 deletions(-) delete mode 100644 cgogn/core/examples/cph/CMakeLists.txt delete mode 100644 cgogn/core/examples/cph/cph2.cpp diff --git a/cgogn/CMakeLists.txt b/cgogn/CMakeLists.txt index 4c57e9db..0e58899a 100644 --- a/cgogn/CMakeLists.txt +++ b/cgogn/CMakeLists.txt @@ -6,3 +6,4 @@ if(CGOGN_USE_QT) add_subdirectory(rendering) endif(CGOGN_USE_QT) +add_subdirectory(multiresolution) diff --git a/cgogn/core/CMakeLists.txt b/cgogn/core/CMakeLists.txt index 765161a4..510871e4 100644 --- a/cgogn/core/CMakeLists.txt +++ b/cgogn/core/CMakeLists.txt @@ -27,12 +27,6 @@ set(HEADER_FILES container/chunk_array.h container/chunk_stack.h - cph/attribute_handler_cph.h - cph/ihcmap_base.h - cph/ihcmap2.h - cph/ihcmap2_adaptive.h - cph/ihcmap2_regular.h - utils/assert.h utils/buffers.h utils/definitions.h diff --git a/cgogn/core/examples/CMakeLists.txt b/cgogn/core/examples/CMakeLists.txt index 8aa69c86..f9e165df 100644 --- a/cgogn/core/examples/CMakeLists.txt +++ b/cgogn/core/examples/CMakeLists.txt @@ -10,4 +10,3 @@ add_definitions("-DCGOGN_TEST_MESHES_PATH=${CGOGN_TEST_MESHES_PATH}") add_subdirectory(chunk_array) add_subdirectory(map) -add_subdirectory(cph) diff --git a/cgogn/core/examples/cph/CMakeLists.txt b/cgogn/core/examples/cph/CMakeLists.txt deleted file mode 100644 index 14698500..00000000 --- a/cgogn/core/examples/cph/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -project(${CGOGN_TEST_PREFIX}map - LANGUAGES CXX -) - -set(CGOGN_TEST_MESHES_PATH "${CMAKE_SOURCE_DIR}/data/meshes/") -add_definitions("-DCGOGN_TEST_MESHES_PATH=${CGOGN_TEST_MESHES_PATH}") - -add_executable(cph2 cph2.cpp) -target_link_libraries(cph2 cgogn_core cgogn_io) diff --git a/cgogn/core/examples/cph/cph2.cpp b/cgogn/core/examples/cph/cph2.cpp deleted file mode 100644 index 58199ca0..00000000 --- a/cgogn/core/examples/cph/cph2.cpp +++ /dev/null @@ -1,78 +0,0 @@ - -#include - -using namespace cgogn; - -using IHMap2 = IHCMap2Regular; - - -template -using VertexAttributeHandler = IHMap2::VertexAttributeHandler; - - -int main() -{ - IHMap2 map; - - // VertexAttributeHandler vertex_position_ = map.get_attribute("position"); - - map.add_face(4); - - std::cout << "before add level Faces :" << std::endl; - map.template foreach_cell([&] (typename IHMap2::Face v) - { - std::cout << v << std::endl; - }); - std::cout << "End Faces" << std::endl; - - - { - map.add_mixed_level(); - - std::cout << "after add level Faces :" << std::endl; - map.template foreach_cell([&] (typename IHMap2::Face f) - { - std::cout << f << " | " << map.get_dart_level(f.dart) << std::endl; - }); - std::cout << "End Faces" << std::endl; - - - unsigned int cur = map.get_current_level(); - - std::cout << "current level = " << cur << std::endl; - map.set_current_level(cur - 1); - - std::cout << "after add level Faces :" << std::endl; - map.template foreach_cell([&] (typename IHMap2::Face f) - { - std::cout << f << " | " << map.get_dart_level(f.dart) << std::endl; - }); - std::cout << "End Vertices" << std::endl; - } - - { - map.add_mixed_level(); - - std::cout << "after add level Faces :" << std::endl; - map.template foreach_cell([&] (typename IHMap2::Face f) - { - std::cout << f << " | " << map.get_dart_level(f.dart) << std::endl; - }); - std::cout << "End Faces" << std::endl; - - - unsigned int cur = map.get_current_level(); - - std::cout << "current level = " << cur << std::endl; - map.set_current_level(cur - 1); - - std::cout << "after add level Faces :" << std::endl; - map.template foreach_cell([&] (typename IHMap2::Face f) - { - std::cout << f << " | " << map.get_dart_level(f.dart) << std::endl; - }); - std::cout << "End Vertices" << std::endl; - } - - return 0; -} diff --git a/cgogn/multiresolution/cph/attribute_handler_cph.h b/cgogn/multiresolution/cph/attribute_handler_cph.h index 279dacc2..ed26ef10 100644 --- a/cgogn/multiresolution/cph/attribute_handler_cph.h +++ b/cgogn/multiresolution/cph/attribute_handler_cph.h @@ -21,8 +21,8 @@ * * *******************************************************************************/ -#ifndef CORE_CPH_ATTRIBUTE_HANDLER_CPH_H_ -#define CORE_CPH_ATTRIBUTE_HANDLER_CPH_H_ +#ifndef MULTIRESOLUTION_CPH_ATTRIBUTE_HANDLER_CPH_H_ +#define MULTIRESOLUTION_CPH_ATTRIBUTE_HANDLER_CPH_H_ #include #include @@ -34,16 +34,20 @@ namespace cgogn * \brief AttributeHandler class * @TPARAM T the data type of the attribute to handlde */ -template +template class AttributeHandlerCPH : public AttributeHandler { public: typedef AttributeHandler Inherit; - typedef AttributeHandlerCPH Self; + typedef AttributeHandlerCPH Self; typedef T value_type; + using MapData = typename Inherit::MapData; + using TChunkArray = typename Inherit::template ChunkArray; + + AttributeHandlerCPH() : Inherit() {} @@ -70,78 +74,78 @@ class AttributeHandlerCPH : public AttributeHandler return Inherit::is_valid(); } - T& operator[](Dart d) + T& operator[](Cell c) { - switch(ORBIT) - { - case Orbit::PHI1: return vertex_embedding(d); break; - default: edge_face_embedding(d); break; - } - - ImplicitHierarchicalMap2* m = reinterpret_cast(this->m_map) ; - assert(m->m_dartLevel[d] <= m->m_curLevel || !"Access to a dart introduced after current level") ; - assert(m->vertexInsertionLevel(d) <= m->m_curLevel || !"Access to the embedding of a vertex inserted after current level") ; - - unsigned int orbit = this->getOrbit() ; - unsigned int nbSteps = m->m_curLevel - m->vertexInsertionLevel(d) ; - unsigned int index = m->getEmbedding(d) ; - - if(index == EMBNULL) - { - index = Algo::Topo::setOrbitEmbeddingOnNewCell(m, d) ; - m->m_nextLevelCell[orbit]->operator[](index) = EMBNULL ; - } - - AttributeContainer& cont = m->getAttributeContainer() ; - unsigned int step = 0 ; - while(step < nbSteps) - { - step++ ; - unsigned int nextIdx = m->m_nextLevelCell[orbit]->operator[](index) ; - if (nextIdx == EMBNULL) - { - nextIdx = m->newCell() ; - m->copyCell(nextIdx, index) ; - m->m_nextLevelCell[orbit]->operator[](index) = nextIdx ; - m->m_nextLevelCell[orbit]->operator[](nextIdx) = EMBNULL ; - cont.refLine(index) ; - } - index = nextIdx ; - } - return this->m_attrib->operator[](index); - } + cgogn_message_assert(is_valid(), "Invalid AttributeHandler"); + return this->chunk_array_->operator[](this->map_->get_embedding(c)); + } +// switch(ORBIT) +// { +// case Orbit::PHI1: return vertex_embedding(d); break; +// default: edge_face_embedding(d); break; +// } + +// cgogn_message_assert(m->get_dart_level(d) <= m->get_current_level(), +// "Access to a dart introduced after current level") ; +// cgogn_message_assert(m->vertexInsertionLevel(d) <= m->m_curLevel, +// "Access to the embedding of a vertex inserted after current level") ; + +// unsigned int orbit = this->getOrbit() ; +// unsigned int nbSteps = m->m_curLevel - m->vertexInsertionLevel(d) ; +// unsigned int index = m->getEmbedding(d) ; + +// AttributeContainer& cont = m->getAttributeContainer() ; +// unsigned int step = 0 ; +// while(step < nbSteps) +// { +// step++ ; +// unsigned int nextIdx = m->m_nextLevelCell[orbit]->operator[](index) ; +// if (nextIdx == EMBNULL) +// { +// nextIdx = m->newCell() ; +// m->copyCell(nextIdx, index) ; +// m->m_nextLevelCell[orbit]->operator[](index) = nextIdx ; +// m->m_nextLevelCell[orbit]->operator[](nextIdx) = EMBNULL ; +// cont.refLine(index) ; +// } +// index = nextIdx ; +// } +// return this->m_attrib->operator[](index); const T& operator[](Dart d) const { - ImplicitHierarchicalMap2* m = reinterpret_cast(this->m_map) ; - assert(m->m_dartLevel[d] <= m->m_curLevel || !"Access to a dart introduced after current level") ; - assert(m->vertexInsertionLevel(d) <= m->m_curLevel || !"Access to the embedding of a vertex inserted after current level") ; - - unsigned int orbit = this->getOrbit() ; - unsigned int nbSteps = m->m_curLevel - m->vertexInsertionLevel(d) ; - unsigned int index = m->getEmbedding(d) ; - - unsigned int step = 0 ; - while(step < nbSteps) - { - step++ ; - unsigned int next = m->m_nextLevelCell[orbit]->operator[](index) ; - if(next != EMBNULL) index = next ; - else break ; - } - return this->m_attrib->operator[](index); +// ImplicitHierarchicalMap2* m = reinterpret_cast(this->m_map) ; +// cgogn_message_assert(m->m_dartLevel[d] <= m->m_curLevel, +// "Access to a dart introduced after current level") ; +// cgogn_message_assert(m->vertexInsertionLevel(d) <= m->m_curLevel, +// "Access to the embedding of a vertex inserted after current level") ; + +// unsigned int orbit = this->getOrbit() ; +// unsigned int nbSteps = m->m_curLevel - m->vertexInsertionLevel(d) ; +// unsigned int index = m->getEmbedding(d) ; + +// unsigned int step = 0 ; +// while(step < nbSteps) +// { +// step++ ; +// unsigned int next = m->m_nextLevelCell[orbit]->operator[](index) ; +// if(next != EMBNULL) index = next ; +// else break ; +// } +// return this->m_attrib->operator[](index); } T& operator[](unsigned int a) { - return AttributeHandler::operator[](a) ; + return AttributeHandler::operator[](a) ; } const T& operator[](unsigned int a) const { - return AttributeHandler::operator[](a) ; + return AttributeHandler::operator[](a) ; } +}; } // namespace cgogn -#endif // CORE_CPH_ATTRIBUTE_HANDLER_CPH_H_ +#endif // MULTIRESOLUTION_CPH_ATTRIBUTE_HANDLER_CPH_H_ diff --git a/cgogn/multiresolution/cph/ihcmap2.h b/cgogn/multiresolution/cph/ihcmap2.h index 5dc6a536..f986c040 100644 --- a/cgogn/multiresolution/cph/ihcmap2.h +++ b/cgogn/multiresolution/cph/ihcmap2.h @@ -21,13 +21,12 @@ * * *******************************************************************************/ -#ifndef CORE_CPH_IHCMAP2_H_ -#define CORE_CPH_IHCMAP2_H_ - +#ifndef MULTIRESOLUTION_CPH_IHCMAP2_H_ +#define MULTIRESOLUTION_CPH_IHCMAP2_H_ #include -#include -// #include +#include +//#include namespace cgogn { @@ -35,23 +34,23 @@ namespace cgogn template class ContainerCPHBrowser : public ContainerBrowser { - const CONTAINER& cac_; - const MAP* map_; + const CONTAINER& cac_; + const MAP* map_; public: - ContainerCPHBrowser(const CONTAINER& cac, const MAP* map) : cac_(cac), map_(map) {} - virtual unsigned int begin() const { return cac_.real_begin(); } - virtual unsigned int end() const { return cac_.real_end(); } - virtual void next(unsigned int &it) const - { - cac_.real_next(it); - if(map_->get_dart_level(Dart(it)) > map_->get_current_level()) - it = cac_.real_end(); - } - virtual void next_primitive(unsigned int &it, unsigned int primSz) const { cac_.real_next_primitive(it,primSz); } - virtual void enable() {} - virtual void disable() {} - virtual ~ContainerCPHBrowser() {} + ContainerCPHBrowser(const CONTAINER& cac, const MAP* map) : cac_(cac), map_(map) {} + virtual unsigned int begin() const { return cac_.real_begin(); } + virtual unsigned int end() const { return cac_.real_end(); } + virtual void next(unsigned int &it) const + { + cac_.real_next(it); + if(map_->get_dart_level(Dart(it)) > map_->get_current_level()) + it = cac_.real_end(); + } + virtual void next_primitive(unsigned int &it, unsigned int primSz) const { cac_.real_next_primitive(it,primSz); } + virtual void enable() {} + virtual void disable() {} + virtual ~ContainerCPHBrowser() {} }; template @@ -60,11 +59,11 @@ class IHCMap2_T : public CMap2_T, public IHCMapBase Inherit_CMAP; - typedef IHCMapBase Inherit_CPH; + typedef IHCMapBase Inherit_CPH; typedef IHCMap2_T Self; - friend typename Self::Inherit_CMAP; -// friend typename Inherit::Inherit; + friend typename Self::Inherit_CMAP; + // friend typename Inherit::Inherit; friend class DartMarker_T; @@ -80,12 +79,12 @@ class IHCMap2_T : public CMap2_T, public IHCMapBase Volume; template - using ChunkArray = typename Inherit_CMAP::template ChunkArray; - template - using ChunkArrayContainer = typename Inherit_CMAP::template ChunkArrayContainer; + using ChunkArray = typename Inherit_CMAP::template ChunkArray; + template + using ChunkArrayContainer = typename Inherit_CMAP::template ChunkArrayContainer; template - using AttributeHandler = typename Inherit_CMAP::template AttributeHandler; + using AttributeHandler = typename Inherit_CMAP::template AttributeHandler; template using DartAttributeHandler = AttributeHandler; template @@ -97,24 +96,29 @@ class IHCMap2_T : public CMap2_T, public IHCMapBase using VolumeAttributeHandler = AttributeHandler; +// template +// using VertexAttributeHandlerCPH = AttributeHandlerCPH; + using DartMarker = typename cgogn::DartMarker; using DartMarkerStore = typename cgogn::DartMarkerStore; + ChunkArray* next_level_cell[NB_ORBITS]; + protected: - ContainerCPHBrowser, Self>* cph_browser; + ContainerCPHBrowser, Self>* cph_browser; inline void init() { cph_browser = new ContainerCPHBrowser, Self>(this->topology_, this); - this->topology_.set_current_browser(cph_browser); + this->topology_.set_current_browser(cph_browser); - // Inherit_CPH::new_level_darts(); + // Inherit_CPH::new_level_darts(); } public: - IHCMap2_T() : Inherit_CMAP(), Inherit_CPH(this->topology_) + IHCMap2_T() : Inherit_CMAP(), Inherit_CPH(this->topology_) { - init(); + init(); } ~IHCMap2_T() override @@ -132,10 +136,10 @@ class IHCMap2_T : public CMap2_T, public IHCMapBase, public IHCMapBase, public IHCMapBase Inherit_CPH::get_maximum_level()) + if(Inherit_CPH::get_current_level() > Inherit_CPH::get_maximum_level()) { - Inherit_CPH::set_maximum_level(Inherit_CPH::get_current_level()); + Inherit_CPH::set_maximum_level(Inherit_CPH::get_current_level()); // Inherit_CPH::new_level_darts(); } -// Inherit_CPH::inc_nb_darts(get_current_level()); + // Inherit_CPH::inc_nb_darts(get_current_level()); return d ; } +// template +// inline unsigned int get_embedding_cph(Cell c) const +// { +// static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); +// cgogn_message_assert(Inherit::is_orbit_embedded(), "Invalid parameter: orbit not embedded"); + +// unsigned int nb_steps = Inherit::get_current_level() - Inherit::get_dart_level(c.dart); +// unsigned int index = Inherit::get_embedding(c); + +// unsigned int step = 0; +// while(step < nb_steps) +// { +// step++; +// unsigned int next = next_level_cell_[ORBIT]->operator[](index); +// //index = next; +// if(next != EMBNULL) index = next; +// else break; +// } + +// return index; +// } + protected: /******************************************************************************* * Orbits traversal *******************************************************************************/ - template - inline void foreach_dart_of_DART(Dart d, const FUNC& f) const - { - f(d); - } - - template - inline void foreach_dart_of_PHI1(Dart d, const FUNC& f) const - { - Dart it = d; - do - { - f(it); - it = phi1(it); - } while (it != d); - } - - template - inline void foreach_dart_of_PHI2(Dart d, const FUNC& f) const - { - f(d); - Dart d2 = phi2(d); - if (d2 != d) - f(d2); - } + template + inline void foreach_dart_of_DART(Dart d, const FUNC& f) const + { + f(d); + } + + template + inline void foreach_dart_of_PHI1(Dart d, const FUNC& f) const + { + Dart it = d; + do + { + f(it); + it = phi1(it); + } while (it != d); + } + + template + inline void foreach_dart_of_PHI2(Dart d, const FUNC& f) const + { + f(d); + Dart d2 = phi2(d); + if (d2 != d) + f(d2); + } template - inline void foreach_dart_of_PHI21(Dart d, const FUNC& f) const + inline void foreach_dart_of_PHI21(Dart d, const FUNC& f) const { Dart it = d; do { f(it); - it = Inherit_CMAP::phi2(Inherit_CMAP::phi_1(it)); + it = Inherit_CMAP::phi2(Inherit_CMAP::phi_1(it)); } while (it != d); } template - void foreach_dart_of_PHI1_PHI2(Dart d, const FUNC& f) const + void foreach_dart_of_PHI1_PHI2(Dart d, const FUNC& f) const { DartMarkerStore marker(*this); @@ -292,32 +318,47 @@ class IHCMap2_T : public CMap2_T, public IHCMapBase +// inline AttributeHandlerCPH add_attribute(const std::string& attribute_name = "") +// { +// static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); + +// } + +// template +// inline bool remove_attribute(AttributeHandlerCPH& ah) +// { +// static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); + +// } }; + template struct IHCMap2Type { @@ -329,5 +370,5 @@ using IHCMap2 = IHCMap2_T>; } // namespace cgogn -#endif // CORE_CPH_IHCMAP2_H_ +#endif // MULTIRESOLUTION_CPH_IHCMAP2_H_ diff --git a/cgogn/multiresolution/cph/ihcmap2_adaptive.h b/cgogn/multiresolution/cph/ihcmap2_adaptive.h index 14f5ba35..a561b229 100644 --- a/cgogn/multiresolution/cph/ihcmap2_adaptive.h +++ b/cgogn/multiresolution/cph/ihcmap2_adaptive.h @@ -21,10 +21,10 @@ * * *******************************************************************************/ -#ifndef CORE_CPH_IHCMAP2_ADAPTIVE_H_ -#define CORE_CPH_IHCMAP2_ADAPTIVE_H_ +#ifndef MULTIRESOLUTION_CPH_IHCMAP2_ADAPTIVE_H_ +#define MULTIRESOLUTION_CPH_IHCMAP2_ADAPTIVE_H_ -#include +#include namespace cgogn { @@ -50,271 +50,271 @@ class IHCMap2Adaptive : IHCMap2 inline ~IHCMap2Adaptive() = default; public: - /*************************************************** - * CELLS INFORMATION * - ***************************************************/ - - /** - * Return the level of the edge of d in the current level map - * \details The level of an edge is the maximum of the levels of - * its darts. As phi1(d) and phi2(d) are from the same level we can - * optimize by checking phi1(d) instead of phi2(d) - */ - unsigned int edge_level(Dart d) - { - cgogn_message_assert(Inherit::getDartLevel(d) <= Inherit::getCurrentLevel(), - "Access to a dart introduced after current level"); - - unsigned int ld = Inherit::getDartLevel(d); - unsigned int ldd = Inherit::getDartLevel(Inherit::phi1(d)); - return ld < ldd ? ldd : ld; - } - - /** - * Return the level of the face of d in the current level map - * \details The level of a face is the minimum of the levels of its edges - * but a specific treatment has to be done in the particular case of a - * face with all neighboring faces are regularly subdivided - * but not the face itself - */ - unsigned int face_level(Dart d) - { - cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), - "Access to a dart introduced after current level"); - - if(Inherit::get_current_level() == 0) - return 0; - - Dart it = d; - Dart old = it; - unsigned int l_old = Inherit::get_dart_level(old); - unsigned int fLevel = edge_level(it); - do - { - it = Inherit::phi1(it); - unsigned int dl = Inherit::get_dart_level(it); - - // compute the oldest dart of the face in the same time - if(dl < l_old) - { - old = it; - l_old = dl; - } - unsigned int l = edge_level(it); - fLevel = l < fLevel ? l : fLevel; - } while(it != d); - - unsigned int cur = Inherit::get_current_level(); - Inherit::set_current_level(fLevel); - - unsigned int nbSubd = 0; - it = old; - unsigned int eId = Inherit::get_edge_id(old); - do - { - ++nbSubd; - it = Inherit::phi1(it); - } while(Inherit::get_edge_id(it) == eId); - - while(nbSubd > 1) - { - nbSubd /= 2; - --fLevel; - } - - Inherit::set_current_level(cur) ; - return fLevel ; - } - - /** - * Given the face of d in the current level map, - * return a level 0 dart of its origin face - */ - Dart face_origin(Dart d) - { - cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), - "Access to a dart introduced after current level"); - - unsigned int cur = Inherit::get_current_level(); - Dart p = d; - unsigned int pLevel = Inherit::get_dart_level(p); - while(pLevel > 0) - { - p = face_oldest_dart(p); - pLevel = Inherit::get_dart_level(p); - Inherit::set_current_level(pLevel); - } - Inherit::set_current_level(cur); - return p; - } - - /** - * Return the oldest dart of the face of d in the current level map - */ - Dart face_oldest_dart(Dart d) - { - cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), - "Access to a dart introduced after current level"); - - Dart it = d ; - Dart oldest = it ; - unsigned int l_old = Inherit::get_dart_level(oldest); - do - { - unsigned int l = Inherit::get_dart_level(it); - if(l == 0) - return it; - - if(l < l_old) - // if(l < l_old || (l == l_old && it < oldest)) - { - oldest = it; - l_old = l; - } - it = Inherit::phi1(it); - } while(it != d); - - return oldest; - } - - /** - * Return true if the edge of d in the current level map - * has already been subdivided to the next level - * As before testing phi2(d) or phi1(d) is the same - */ - bool edge_is_subdivided(Dart d) - { - cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), - "Access to a dart introduced after current level"); - - if(Inherit::get_current_level() == Inherit::get_maximum_level()) - return false ; - - Dart d1 = Inherit::phi1(d); - unsigned int cur = Inherit::get_current_level(); - Inherit::set_current_level(cur + 1); - Dart d1_l = Inherit::phi1(d); - Inherit::set_current_level(cur); - if(d1 != d1_l) - return true; - else - return false; - } - - /** - * Return true if the edge of d in the current level map - * is subdivided to the next level, - * none of its resulting edges is in turn subdivided to the next level - * and the middle vertex is of degree 2 - */ - bool edge_can_be_coarsened(Dart d) - { - cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), - "Access to a dart introduced after current level"); - - bool subd = false ; - bool subdOnce = true ; - bool degree2 = false ; - if(edge_is_subdivided(d)) - { - subd = true ; - Dart d2 = Inherit::phi2(d) ; - unsigned int cur = Inherit::get_current_level(); - Inherit::set_current_level(cur + 1); - if(Inherit::vertexDegree(Inherit::phi1(d)) == 2) - { - degree2 = true ; - if(edge_is_subdivided(d) || edge_is_subdivided(d2)) - subdOnce = false ; - } - Inherit::set_current_level(cur); - - } - return subd && degree2 && subdOnce ; - } - - /** - * Return true if the face of d in the current level map - * has already been subdivided to the next level - */ - bool face_is_subdivided(Dart d) - { - cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), - "Access to a dart introduced after current level"); - - unsigned int fLevel = face_level(d) ; - if(fLevel <= Inherit::get_current_level()) - return false ; - - bool subd = false ; - - unsigned int cur = Inherit::get_current_level(); - Inherit::set_current_level(cur + 1); - if(Inherit::get_dart_level(Inherit::phi1(d)) == Inherit::get_current_level() - && Inherit::get_edge_id(Inherit::phi1(d)) != Inherit::get_edge_id(d)) - subd = true; - Inherit::set_current_level(cur); - - return subd; - } - - /** - * Return true if the face of d in the current level map - * is subdivided to the next level - * and none of its resulting faces is in turn subdivided to the next level - * \details - * A face whose level in the current level map is lower than the current - * level can not be subdivided to higher levels - */ - bool face_is_subdivided_once(Dart d) - { - cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), - "Access to a dart introduced after current level"); - - unsigned int fLevel = face_level(d); - if(fLevel < Inherit::get_current_level()) - return false; - - unsigned int degree = 0 ; - bool subd = false ; - bool subdOnce = true ; - Dart fit = d ; - do - { - unsigned int cur = Inherit::get_current_level(); - Inherit::set_current_level(cur + 1); - if(Inherit::get_dart_level(Inherit::phi1(fit)) == Inherit::get_current_level() - && Inherit::get_edge_id(Inherit::phi1(fit)) != Inherit::get_edge_id(fit)) - { - subd = true ; - unsigned int cur2 = Inherit::get_current_level(); - Inherit::set_current_level(cur2 + 1); - if(Inherit::get_dart_level(Inherit::phi1(fit)) == Inherit::get_current_level() - && Inherit::get_edge_id(m_map.phi1(fit)) != Inherit::get_edge_id(fit)) - subdOnce = false ; - Inherit::set_current_level(cur2); - } - Inherit::set_current_level(cur); - ++degree ; - fit = Inherit::phi1(fit) ; - } while(subd && subdOnce && fit != d) ; - - if(degree == 3 && subd) - { - unsigned int cur = Inherit::get_current_level(); - Inherit::set_current_level(cur + 1); - Dart cf = Inherit::phi2(Inherit::phi1(d)) ; - unsigned int cur2 = Inherit::get_current_level(); - Inherit::set_current_level(cur2 + 1); - if(Inherit::get_dart_level(Inherit::phi1(cf)) == Inherit::get_current_level() - && Inherit::get_edge_id(Inherit::phi1(cf)) != Inherit::get_edge_id(cf)) - subdOnce = false ; - Inherit::set_current_level(cur2); - Inherit::set_current_level(cur); - } - - return subd && subdOnce ; - } + /*************************************************** + * CELLS INFORMATION * + ***************************************************/ + + /** + * Return the level of the edge of d in the current level map + * \details The level of an edge is the maximum of the levels of + * its darts. As phi1(d) and phi2(d) are from the same level we can + * optimize by checking phi1(d) instead of phi2(d) + */ + unsigned int edge_level(Dart d) + { + cgogn_message_assert(Inherit::getDartLevel(d) <= Inherit::getCurrentLevel(), + "Access to a dart introduced after current level"); + + unsigned int ld = Inherit::getDartLevel(d); + unsigned int ldd = Inherit::getDartLevel(Inherit::phi1(d)); + return ld < ldd ? ldd : ld; + } + + /** + * Return the level of the face of d in the current level map + * \details The level of a face is the minimum of the levels of its edges + * but a specific treatment has to be done in the particular case of a + * face with all neighboring faces are regularly subdivided + * but not the face itself + */ + unsigned int face_level(Dart d) + { + cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), + "Access to a dart introduced after current level"); + + if(Inherit::get_current_level() == 0) + return 0; + + Dart it = d; + Dart old = it; + unsigned int l_old = Inherit::get_dart_level(old); + unsigned int fLevel = edge_level(it); + do + { + it = Inherit::phi1(it); + unsigned int dl = Inherit::get_dart_level(it); + + // compute the oldest dart of the face in the same time + if(dl < l_old) + { + old = it; + l_old = dl; + } + unsigned int l = edge_level(it); + fLevel = l < fLevel ? l : fLevel; + } while(it != d); + + unsigned int cur = Inherit::get_current_level(); + Inherit::set_current_level(fLevel); + + unsigned int nbSubd = 0; + it = old; + unsigned int eId = Inherit::get_edge_id(old); + do + { + ++nbSubd; + it = Inherit::phi1(it); + } while(Inherit::get_edge_id(it) == eId); + + while(nbSubd > 1) + { + nbSubd /= 2; + --fLevel; + } + + Inherit::set_current_level(cur) ; + return fLevel ; + } + + /** + * Given the face of d in the current level map, + * return a level 0 dart of its origin face + */ + Dart face_origin(Dart d) + { + cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), + "Access to a dart introduced after current level"); + + unsigned int cur = Inherit::get_current_level(); + Dart p = d; + unsigned int pLevel = Inherit::get_dart_level(p); + while(pLevel > 0) + { + p = face_oldest_dart(p); + pLevel = Inherit::get_dart_level(p); + Inherit::set_current_level(pLevel); + } + Inherit::set_current_level(cur); + return p; + } + + /** + * Return the oldest dart of the face of d in the current level map + */ + Dart face_oldest_dart(Dart d) + { + cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), + "Access to a dart introduced after current level"); + + Dart it = d ; + Dart oldest = it ; + unsigned int l_old = Inherit::get_dart_level(oldest); + do + { + unsigned int l = Inherit::get_dart_level(it); + if(l == 0) + return it; + + if(l < l_old) + // if(l < l_old || (l == l_old && it < oldest)) + { + oldest = it; + l_old = l; + } + it = Inherit::phi1(it); + } while(it != d); + + return oldest; + } + + /** + * Return true if the edge of d in the current level map + * has already been subdivided to the next level + * As before testing phi2(d) or phi1(d) is the same + */ + bool edge_is_subdivided(Dart d) + { + cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), + "Access to a dart introduced after current level"); + + if(Inherit::get_current_level() == Inherit::get_maximum_level()) + return false ; + + Dart d1 = Inherit::phi1(d); + unsigned int cur = Inherit::get_current_level(); + Inherit::set_current_level(cur + 1); + Dart d1_l = Inherit::phi1(d); + Inherit::set_current_level(cur); + if(d1 != d1_l) + return true; + else + return false; + } + + /** + * Return true if the edge of d in the current level map + * is subdivided to the next level, + * none of its resulting edges is in turn subdivided to the next level + * and the middle vertex is of degree 2 + */ + bool edge_can_be_coarsened(Dart d) + { + cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), + "Access to a dart introduced after current level"); + + bool subd = false ; + bool subdOnce = true ; + bool degree2 = false ; + if(edge_is_subdivided(d)) + { + subd = true ; + Dart d2 = Inherit::phi2(d) ; + unsigned int cur = Inherit::get_current_level(); + Inherit::set_current_level(cur + 1); + if(Inherit::vertexDegree(Inherit::phi1(d)) == 2) + { + degree2 = true ; + if(edge_is_subdivided(d) || edge_is_subdivided(d2)) + subdOnce = false ; + } + Inherit::set_current_level(cur); + + } + return subd && degree2 && subdOnce ; + } + + /** + * Return true if the face of d in the current level map + * has already been subdivided to the next level + */ + bool face_is_subdivided(Dart d) + { + cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), + "Access to a dart introduced after current level"); + + unsigned int fLevel = face_level(d) ; + if(fLevel <= Inherit::get_current_level()) + return false ; + + bool subd = false ; + + unsigned int cur = Inherit::get_current_level(); + Inherit::set_current_level(cur + 1); + if(Inherit::get_dart_level(Inherit::phi1(d)) == Inherit::get_current_level() + && Inherit::get_edge_id(Inherit::phi1(d)) != Inherit::get_edge_id(d)) + subd = true; + Inherit::set_current_level(cur); + + return subd; + } + + /** + * Return true if the face of d in the current level map + * is subdivided to the next level + * and none of its resulting faces is in turn subdivided to the next level + * \details + * A face whose level in the current level map is lower than the current + * level can not be subdivided to higher levels + */ + bool face_is_subdivided_once(Dart d) + { + cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), + "Access to a dart introduced after current level"); + + unsigned int fLevel = face_level(d); + if(fLevel < Inherit::get_current_level()) + return false; + + unsigned int degree = 0 ; + bool subd = false ; + bool subdOnce = true ; + Dart fit = d ; + do + { + unsigned int cur = Inherit::get_current_level(); + Inherit::set_current_level(cur + 1); + if(Inherit::get_dart_level(Inherit::phi1(fit)) == Inherit::get_current_level() + && Inherit::get_edge_id(Inherit::phi1(fit)) != Inherit::get_edge_id(fit)) + { + subd = true ; + unsigned int cur2 = Inherit::get_current_level(); + Inherit::set_current_level(cur2 + 1); + if(Inherit::get_dart_level(Inherit::phi1(fit)) == Inherit::get_current_level() + && Inherit::get_edge_id(m_map.phi1(fit)) != Inherit::get_edge_id(fit)) + subdOnce = false ; + Inherit::set_current_level(cur2); + } + Inherit::set_current_level(cur); + ++degree ; + fit = Inherit::phi1(fit) ; + } while(subd && subdOnce && fit != d) ; + + if(degree == 3 && subd) + { + unsigned int cur = Inherit::get_current_level(); + Inherit::set_current_level(cur + 1); + Dart cf = Inherit::phi2(Inherit::phi1(d)) ; + unsigned int cur2 = Inherit::get_current_level(); + Inherit::set_current_level(cur2 + 1); + if(Inherit::get_dart_level(Inherit::phi1(cf)) == Inherit::get_current_level() + && Inherit::get_edge_id(Inherit::phi1(cf)) != Inherit::get_edge_id(cf)) + subdOnce = false ; + Inherit::set_current_level(cur2); + Inherit::set_current_level(cur); + } + + return subd && subdOnce ; + } protected: /*************************************************** @@ -324,222 +324,222 @@ class IHCMap2Adaptive : IHCMap2 /** * subdivide the edge of d to the next level */ - void subdivide_edge(Dart d) + void subdivide_edge(Dart d) { - cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), - "subdivideEdge : called with a dart inserted after current level") ; - cgogn_message_assert(!edge_is_subdivided(d), "Trying to subdivide an already subdivided edge"); + cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), + "subdivideEdge : called with a dart inserted after current level") ; + cgogn_message_assert(!edge_is_subdivided(d), "Trying to subdivide an already subdivided edge"); + + unsigned int eLevel = edge_level(d); - unsigned int eLevel = edge_level(d); + unsigned int cur = Inherit::get_current_level(); + Inherit::set_current_level(eLevel); - unsigned int cur = Inherit::get_current_level(); - Inherit::set_current_level(eLevel); + Dart dd = Inherit::phi2(d); - Dart dd = Inherit::phi2(d); + Inherit::set_current_level(eLevel + 1); - Inherit::set_current_level(eLevel + 1); + Inherit::cut_edge(d); + unsigned int eId = Inherit::get_edge_id(d); + Inherit::set_edge_id(Inherit::phi1(d), eId); + Inherit::set_edge_id(Inherit::phi1(dd), eId); - Inherit::cut_edge(d); - unsigned int eId = Inherit::get_edge_id(d); - Inherit::set_edge_id(Inherit::phi1(d), eId); - Inherit::set_edge_id(Inherit::phi1(dd), eId); - -// if(Inherit::template is_orbit_embedded()) -// { -// (*edgeVertexFunctor)(Inherit::phi1(d)); -// } + // if(Inherit::template is_orbit_embedded()) + // { + // (*edgeVertexFunctor)(Inherit::phi1(d)); + // } -// //quid des autres cellules ? -// (*edgeEdgeFunctor)(Inherit::phi1(d)); -// (*edgeEdgeFunctor)(d); + // //quid des autres cellules ? + // (*edgeEdgeFunctor)(Inherit::phi1(d)); + // (*edgeEdgeFunctor)(d); - Inherit::set_current_level(cur); + Inherit::set_current_level(cur); } /** * coarsen the edge of d from the next level */ - void coarsen_edge(Dart d) + void coarsen_edge(Dart d) { - cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), - "coarsenEdge : called with a dart inserted after current level"); - cgogn_message_assert(edge_can_be_coarsened(d), "Trying to coarsen an edge that can not be coarsened"); - - - unsigned int cur = Inherit::get_current_level(); - // Dart e = Inherit::phi2(d); - Inherit::set_current_level(cur + 1); - // unsigned int dl = Inherit::get_dart_level(e); - // Inherit::set_dart_level(Inherit::phi1(e), dl); - // Inherit::collapseEdge(e); - Inherit::uncut_edge(d); - Inherit::set_current_level(cur); + cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), + "coarsenEdge : called with a dart inserted after current level"); + cgogn_message_assert(edge_can_be_coarsened(d), "Trying to coarsen an edge that can not be coarsened"); + + + unsigned int cur = Inherit::get_current_level(); + // Dart e = Inherit::phi2(d); + Inherit::set_current_level(cur + 1); + // unsigned int dl = Inherit::get_dart_level(e); + // Inherit::set_dart_level(Inherit::phi1(e), dl); + // Inherit::collapseEdge(e); + Inherit::uncut_edge(d); + Inherit::set_current_level(cur); } public: /** * subdivide the face of d to the next level */ - unsigned int subdivide_face(Dart d, bool triQuad = true, bool OneLevelDifference = true) - { - cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), - "coarsenEdge : called with a dart inserted after current level"); - cgogn_message_assert(!face_is_subdivided(d), "Trying to coarsen an edge that can not be coarsened"); - - unsigned int fLevel = face_level(d); - Dart old = face_oldest_dart(d); - - unsigned int cur = Inherit::get_current_level(); - Inherit::set_current_level(fLevel); // go to the level of the face to subdivide its edges - - unsigned int degree = 0; - Dart it = old; - do - { - ++degree; // compute the degree of the face - - if(OneLevelDifference) - { - Dart nf = Inherit::phi2(it); - if(face_level(nf) == fLevel - 1) // check if neighboring faces have to be subdivided first - subdivide_face(nf,triQuad); - } - - if(!edge_is_subdivided(it)) - subdivide_edge(it); // and cut the edges (if they are not already) - it = Inherit::phi1(it); - } while(it != old); - - Inherit::setCurrentLevel(fLevel + 1); // go to the next level to perform face subdivision - - if((degree == 3) && triQuad) // if subdividing a triangle - { - Dart dd = Inherit::phi1(old); - Dart e = Inherit::phi1(dd); -// (*vertexVertexFunctor)(e) ; - - e = Inherit::phi1(e); - Inherit::split_face(dd, e); - - unsigned int id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); - Inherit::set_edge_id(Inherit::phi_1(dd), id); // set the edge id of the inserted - Inherit::set_edge_id(Inherit::phi_1(e), id); // edge to the next available id - - dd = e ; - e = Inherit::phi1(dd); -// (*vertexVertexFunctor)(e); - e = Inherit::phi1(e); - Inherit::split_face(dd, e); - id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); - Inherit::set_edge_id(Inherit::phi_1(dd), id); - Inherit::set_edge_id(Inherit::phi_1(e), id); - - dd = e ; - e = Inherit::phi1(dd); -// (*vertexVertexFunctor)(e); - e = Inherit::phi1(e); - Inherit::split_face(dd, e); - id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); - Inherit::set_edge_id(Inherit::phi_1(dd), id); - Inherit::set_edge_id(Inherit::phi_1(e), id); - } - else // if subdividing a polygonal face - { - Dart dd = Inherit::phi1(old); - Dart next = m_map.phi1(dd); -// (*vertexVertexFunctor)(next); - next = Inherit::phi1(next); - Inherit::splitFace(dd, next); // insert a first edge - Dart ne = Inherit::phi2(Inherit::phi_1(dd)); - Dart ne2 = Inherit::phi2(ne); - Inherit::cut_edge(ne); // cut the new edge to insert the central vertex - - unsigned int id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(ne))); - Inherit::set_edge_id(ne, id); - Inherit::set_edge_id(Inherit::phi2(ne), id); // set the edge id of the inserted - - id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(ne2)); - Inherit::set_edge_id(ne2, id); // edges to the next available ids - Inherit::set_edge_id(Inherit::phi2(ne2), id); - - - dd = Inherit::phi1(next); -// (*vertexVertexFunctor)(dd); - dd = Inherit::phi1(dd); - while(dd != ne) // turn around the face and insert new edges - { // linked to the central vertex - Inherit::splitFace(Inherit::phi1(ne), dd); - Dart nne = Inherit::phi2(Inherit::phi_1(dd)); - - id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(nne))); - Inherit::set_edge_id(nne, id) ; - Inherit::set_edge_id(Inherit::phi2(nne), id); - - dd = Inherit::phi1(dd); -// (*vertexVertexFunctor)(dd); - dd = Inherit::phi1(dd); - } - -// (*faceVertexFunctor)(Inherit::phi1(ne)); - } - - Inherit::set_current_level(cur); - - return fLevel ; - } + unsigned int subdivide_face(Dart d, bool triQuad = true, bool OneLevelDifference = true) + { + cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), + "coarsenEdge : called with a dart inserted after current level"); + cgogn_message_assert(!face_is_subdivided(d), "Trying to coarsen an edge that can not be coarsened"); + + unsigned int fLevel = face_level(d); + Dart old = face_oldest_dart(d); + + unsigned int cur = Inherit::get_current_level(); + Inherit::set_current_level(fLevel); // go to the level of the face to subdivide its edges + + unsigned int degree = 0; + Dart it = old; + do + { + ++degree; // compute the degree of the face + + if(OneLevelDifference) + { + Dart nf = Inherit::phi2(it); + if(face_level(nf) == fLevel - 1) // check if neighboring faces have to be subdivided first + subdivide_face(nf,triQuad); + } + + if(!edge_is_subdivided(it)) + subdivide_edge(it); // and cut the edges (if they are not already) + it = Inherit::phi1(it); + } while(it != old); + + Inherit::setCurrentLevel(fLevel + 1); // go to the next level to perform face subdivision + + if((degree == 3) && triQuad) // if subdividing a triangle + { + Dart dd = Inherit::phi1(old); + Dart e = Inherit::phi1(dd); + // (*vertexVertexFunctor)(e) ; + + e = Inherit::phi1(e); + Inherit::split_face(dd, e); + + unsigned int id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); + Inherit::set_edge_id(Inherit::phi_1(dd), id); // set the edge id of the inserted + Inherit::set_edge_id(Inherit::phi_1(e), id); // edge to the next available id + + dd = e ; + e = Inherit::phi1(dd); + // (*vertexVertexFunctor)(e); + e = Inherit::phi1(e); + Inherit::split_face(dd, e); + id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); + Inherit::set_edge_id(Inherit::phi_1(dd), id); + Inherit::set_edge_id(Inherit::phi_1(e), id); + + dd = e ; + e = Inherit::phi1(dd); + // (*vertexVertexFunctor)(e); + e = Inherit::phi1(e); + Inherit::split_face(dd, e); + id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); + Inherit::set_edge_id(Inherit::phi_1(dd), id); + Inherit::set_edge_id(Inherit::phi_1(e), id); + } + else // if subdividing a polygonal face + { + Dart dd = Inherit::phi1(old); + Dart next = m_map.phi1(dd); + // (*vertexVertexFunctor)(next); + next = Inherit::phi1(next); + Inherit::splitFace(dd, next); // insert a first edge + Dart ne = Inherit::phi2(Inherit::phi_1(dd)); + Dart ne2 = Inherit::phi2(ne); + Inherit::cut_edge(ne); // cut the new edge to insert the central vertex + + unsigned int id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(ne))); + Inherit::set_edge_id(ne, id); + Inherit::set_edge_id(Inherit::phi2(ne), id); // set the edge id of the inserted + + id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(ne2)); + Inherit::set_edge_id(ne2, id); // edges to the next available ids + Inherit::set_edge_id(Inherit::phi2(ne2), id); + + + dd = Inherit::phi1(next); + // (*vertexVertexFunctor)(dd); + dd = Inherit::phi1(dd); + while(dd != ne) // turn around the face and insert new edges + { // linked to the central vertex + Inherit::splitFace(Inherit::phi1(ne), dd); + Dart nne = Inherit::phi2(Inherit::phi_1(dd)); + + id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(nne))); + Inherit::set_edge_id(nne, id) ; + Inherit::set_edge_id(Inherit::phi2(nne), id); + + dd = Inherit::phi1(dd); + // (*vertexVertexFunctor)(dd); + dd = Inherit::phi1(dd); + } + + // (*faceVertexFunctor)(Inherit::phi1(ne)); + } + + Inherit::set_current_level(cur); + + return fLevel ; + } /** * coarsen the face of d from the next level */ - void coarsen_face(Dart d) - { - cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), - "coarsenEdge : called with a dart inserted after current level"); - cgogn_message_assert(face_is_subdivided_once(d), "Trying to coarsen an edge that can not be coarsened"); - - unsigned int cur = Inherit::get_current_level(); - - unsigned int degree = 0; - Dart fit = d; - do - { - ++degree; - fit = Inherit::phi1(fit); - } while(fit != d); - - if(degree == 3) - { - fit = d ; - do - { - Inherit::set_current_level(cur + 1); - Dart innerEdge = Inherit::phi1(fit); - Inherit::set_current_level(Inherit::get_maximum_level()); - Inherit::merge_faces(innerEdge); - Inherit::set_current_level(cur); - fit = m_map.phi1(fit); - } while(fit != d); - } - else - { - Inherit::set_current_level(cur + 1); - Dart centralV = Inherit::phi1(Inherit::phi1(d)); - Inherit::set_current_level(Inherit::get_maximum_level()); - Inherit::delete_vertex(centralV); - Inherit::set_current_level(cur); - } - - fit = d ; - do - { - if(edge_can_be_coarsened(fit)) - coarsen_edge(fit); - fit = Inherit::phi1(fit); - } while(fit != d); - } + void coarsen_face(Dart d) + { + cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), + "coarsenEdge : called with a dart inserted after current level"); + cgogn_message_assert(face_is_subdivided_once(d), "Trying to coarsen an edge that can not be coarsened"); + + unsigned int cur = Inherit::get_current_level(); + + unsigned int degree = 0; + Dart fit = d; + do + { + ++degree; + fit = Inherit::phi1(fit); + } while(fit != d); + + if(degree == 3) + { + fit = d ; + do + { + Inherit::set_current_level(cur + 1); + Dart innerEdge = Inherit::phi1(fit); + Inherit::set_current_level(Inherit::get_maximum_level()); + Inherit::merge_faces(innerEdge); + Inherit::set_current_level(cur); + fit = m_map.phi1(fit); + } while(fit != d); + } + else + { + Inherit::set_current_level(cur + 1); + Dart centralV = Inherit::phi1(Inherit::phi1(d)); + Inherit::set_current_level(Inherit::get_maximum_level()); + Inherit::delete_vertex(centralV); + Inherit::set_current_level(cur); + } + + fit = d ; + do + { + if(edge_can_be_coarsened(fit)) + coarsen_edge(fit); + fit = Inherit::phi1(fit); + } while(fit != d); + } }; } // namespace cgogn -#endif // CORE_CPH_IHCMAP2_ADAPTIVE_H_ +#endif // MULTIRESOLUTION_CPH_IHCMAP2_ADAPTIVE_H_ diff --git a/cgogn/multiresolution/cph/ihcmap2_regular.h b/cgogn/multiresolution/cph/ihcmap2_regular.h index aab8a2d3..22e64953 100644 --- a/cgogn/multiresolution/cph/ihcmap2_regular.h +++ b/cgogn/multiresolution/cph/ihcmap2_regular.h @@ -21,10 +21,10 @@ * * *******************************************************************************/ -#ifndef CORE_CPH_IHCMAP2_REGULAR_H_ -#define CORE_CPH_IHCMAP2_REGULAR_H_ +#ifndef MULTIRESOLUTION_CPH_IHCMAP2_REGULAR_H_ +#define MULTIRESOLUTION_CPH_IHCMAP2_REGULAR_H_ -#include +#include namespace cgogn { @@ -51,208 +51,208 @@ class IHCMap2Regular : public IHCMap2 inline void add_triangular_level() { - unsigned int cur = Inherit::get_current_level() ; - - Inherit::set_current_level(Inherit::get_maximum_level() + 1) ; - - //cut edges - Inherit::template foreach_cell([&] (typename Inherit::Edge e) - { - Dart dd = Inherit::phi2(e); - Inherit::cut_edge(e); - - unsigned int eid = Inherit::get_edge_id(e); - Inherit::set_edge_id(Inherit::phi1(e), eid); - Inherit::set_edge_id(Inherit::phi1(dd), eid); - }); - - //cut faces - Inherit::template foreach_cell([&] (typename Inherit::Face d) - { - Dart old = d ; - - if(Inherit::get_dart_level(old) == Inherit::get_maximum_level()) - old = Inherit::phi1(old) ; - - Dart dd = Inherit::phi1(old) ; - Dart e = Inherit::phi1(Inherit::phi1(dd)) ; - // insert a new edge - Inherit::split_face(dd, e) ; - - unsigned int id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); - Inherit::set_edge_id(Inherit::phi_1(dd), id) ; // set the edge id of the inserted - Inherit::set_edge_id(Inherit::phi_1(e), id) ; // edge to the next available id - - dd = e ; - e = Inherit::phi1(Inherit::phi1(dd)) ; - Inherit::split_face(dd, e) ; - id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); - Inherit::set_edge_id(Inherit::phi_1(dd), id) ; - Inherit::set_edge_id(Inherit::phi_1(e), id) ; - - dd = e ; - e = Inherit::phi1(Inherit::phi1(dd)) ; - Inherit::split_face(dd, e) ; - id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); - Inherit::set_edge_id(Inherit::phi_1(dd), id) ; - Inherit::set_edge_id(Inherit::phi_1(e), id) ; - }); - - Inherit::set_current_level(cur) ; + unsigned int cur = Inherit::get_current_level() ; + + Inherit::set_current_level(Inherit::get_maximum_level() + 1) ; + + //cut edges + Inherit::template foreach_cell([&] (typename Inherit::Edge e) + { + Dart dd = Inherit::phi2(e); + Inherit::cut_edge(e); + + unsigned int eid = Inherit::get_edge_id(e); + Inherit::set_edge_id(Inherit::phi1(e), eid); + Inherit::set_edge_id(Inherit::phi1(dd), eid); + }); + + //cut faces + Inherit::template foreach_cell([&] (typename Inherit::Face d) + { + Dart old = d ; + + if(Inherit::get_dart_level(old) == Inherit::get_maximum_level()) + old = Inherit::phi1(old) ; + + Dart dd = Inherit::phi1(old) ; + Dart e = Inherit::phi1(Inherit::phi1(dd)) ; + // insert a new edge + Inherit::split_face(dd, e) ; + + unsigned int id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); + Inherit::set_edge_id(Inherit::phi_1(dd), id) ; // set the edge id of the inserted + Inherit::set_edge_id(Inherit::phi_1(e), id) ; // edge to the next available id + + dd = e ; + e = Inherit::phi1(Inherit::phi1(dd)) ; + Inherit::split_face(dd, e) ; + id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); + Inherit::set_edge_id(Inherit::phi_1(dd), id) ; + Inherit::set_edge_id(Inherit::phi_1(e), id) ; + + dd = e ; + e = Inherit::phi1(Inherit::phi1(dd)) ; + Inherit::split_face(dd, e) ; + id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); + Inherit::set_edge_id(Inherit::phi_1(dd), id) ; + Inherit::set_edge_id(Inherit::phi_1(e), id) ; + }); + + Inherit::set_current_level(cur) ; } inline void add_quadrangular_level() { - unsigned int cur = Inherit::get_current_level() ; + unsigned int cur = Inherit::get_current_level() ; - Inherit::set_current_level(Inherit::get_maximum_level() + 1) ; + Inherit::set_current_level(Inherit::get_maximum_level() + 1) ; - //cut edges - Inherit::template foreach_cell([&] (typename Inherit::Edge e) - { - Dart dd = Inherit::phi2(e); - Inherit::cut_edge(e); + //cut edges + Inherit::template foreach_cell([&] (typename Inherit::Edge e) + { + Dart dd = Inherit::phi2(e); + Inherit::cut_edge(e); - unsigned int eid = Inherit::get_edge_id(e); - Inherit::set_edge_id(Inherit::phi1(e), eid); - Inherit::set_edge_id(Inherit::phi1(dd), eid); - }); + unsigned int eid = Inherit::get_edge_id(e); + Inherit::set_edge_id(Inherit::phi1(e), eid); + Inherit::set_edge_id(Inherit::phi1(dd), eid); + }); - //cut faces - Inherit::template foreach_cell([&] (typename Inherit::Face d) - { - Dart old = d ; + //cut faces + Inherit::template foreach_cell([&] (typename Inherit::Face d) + { + Dart old = d ; - if(Inherit::get_dart_level(old) == Inherit::get_maximum_level()) - old = Inherit::phi1(old) ; + if(Inherit::get_dart_level(old) == Inherit::get_maximum_level()) + old = Inherit::phi1(old) ; - Dart dd = Inherit::phi1(old) ; - Dart next = Inherit::phi1(Inherit::phi1(dd)) ; - Inherit::split_face(dd, next) ; // insert a first edge + Dart dd = Inherit::phi1(old) ; + Dart next = Inherit::phi1(Inherit::phi1(dd)) ; + Inherit::split_face(dd, next) ; // insert a first edge - Dart ne = Inherit::phi2(Inherit::phi_1(dd)) ; - Dart ne2 = Inherit::phi2(ne) ; - Inherit::cut_edge(ne) ; // cut the new edge to insert the central vertex + Dart ne = Inherit::phi2(Inherit::phi_1(dd)) ; + Dart ne2 = Inherit::phi2(ne) ; + Inherit::cut_edge(ne) ; // cut the new edge to insert the central vertex - unsigned int id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(ne))); - Inherit::set_edge_id(ne, id) ; - Inherit::set_edge_id(Inherit::phi2(ne), id) ; // set the edge id of the inserted + unsigned int id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(ne))); + Inherit::set_edge_id(ne, id) ; + Inherit::set_edge_id(Inherit::phi2(ne), id) ; // set the edge id of the inserted - id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(ne2)); - Inherit::set_edge_id(ne2, id) ; // edges to the next available ids - Inherit::set_edge_id(Inherit::phi2(ne2), id) ; + id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(ne2)); + Inherit::set_edge_id(ne2, id) ; // edges to the next available ids + Inherit::set_edge_id(Inherit::phi2(ne2), id) ; - dd = Inherit::phi1(Inherit::phi1(next)) ; - while(dd != ne) // turn around the face and insert new edges - { // linked to the central vertex - Dart tmp = Inherit::phi1(ne) ; - Inherit::split_face(tmp, dd) ; + dd = Inherit::phi1(Inherit::phi1(next)) ; + while(dd != ne) // turn around the face and insert new edges + { // linked to the central vertex + Dart tmp = Inherit::phi1(ne) ; + Inherit::split_face(tmp, dd) ; - Dart nne = Inherit::phi2(Inherit::phi_1(dd)) ; + Dart nne = Inherit::phi2(Inherit::phi_1(dd)) ; - id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(nne))); - Inherit::set_edge_id(nne, id) ; - Inherit::set_edge_id(Inherit::phi2(nne), id) ; - dd = Inherit::phi1(Inherit::phi1(dd)) ; - } - }); + id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(nne))); + Inherit::set_edge_id(nne, id) ; + Inherit::set_edge_id(Inherit::phi2(nne), id) ; + dd = Inherit::phi1(Inherit::phi1(dd)) ; + } + }); - Inherit::set_current_level(cur) ; + Inherit::set_current_level(cur) ; } inline void add_mixed_level() { - unsigned int cur = Inherit::get_current_level() ; - - Inherit::set_current_level(Inherit::get_maximum_level() + 1) ; - - //cut edges - Inherit::template foreach_cell([&] (typename Inherit::Edge e) - { - Dart dd = Inherit::phi2(e); - Inherit::cut_edge(e); - - unsigned int eid = Inherit::get_edge_id(e); - Inherit::set_edge_id(Inherit::phi1(e), eid); - Inherit::set_edge_id(Inherit::phi1(dd), eid); - }); - - //cut faces - Inherit::template foreach_cell([&] (typename Inherit::Face d) - { - Dart old = d ; - - if(Inherit::get_dart_level(old) == Inherit::get_maximum_level()) - old = Inherit::phi1(old) ; - - unsigned int cur = Inherit::get_current_level(); - Inherit::set_current_level(cur - 1); - unsigned int degree = Inherit::face_degree(old) ; - Inherit::set_current_level(cur); - - if(degree == 3) - { - Dart dd = Inherit::phi1(old) ; - Dart e = Inherit::phi1(Inherit::phi1(dd)) ; - // insert a new edge - Inherit::split_face(dd, e) ; - - unsigned int id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); - Inherit::set_edge_id(Inherit::phi_1(dd), id) ; // set the edge id of the inserted - Inherit::set_edge_id(Inherit::phi_1(e), id) ; // edge to the next available id - - dd = e ; - e = Inherit::phi1(Inherit::phi1(dd)) ; - Inherit::split_face(dd, e) ; - id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); - Inherit::set_edge_id(Inherit::phi_1(dd), id) ; - Inherit::set_edge_id(Inherit::phi_1(e), id) ; - - dd = e ; - e = Inherit::phi1(Inherit::phi1(dd)) ; - Inherit::split_face(dd, e) ; - id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); - Inherit::set_edge_id(Inherit::phi_1(dd), id) ; - Inherit::set_edge_id(Inherit::phi_1(e), id) ; - } - else - { - Dart dd = Inherit::phi1(old) ; - Dart next = Inherit::phi1(Inherit::phi1(dd)) ; - Inherit::split_face(dd, next) ; // insert a first edge - - Dart ne = Inherit::phi2(Inherit::phi_1(dd)) ; - Dart ne2 = Inherit::phi2(ne) ; - Inherit::cut_edge(ne) ; // cut the new edge to insert the central vertex - - unsigned int id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(ne))); - Inherit::set_edge_id(ne, id) ; - Inherit::set_edge_id(Inherit::phi2(ne), id) ; // set the edge id of the inserted - - id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(ne2)); - Inherit::set_edge_id(ne2, id) ; // edges to the next available ids - Inherit::set_edge_id(Inherit::phi2(ne2), id) ; - - dd = Inherit::phi1(Inherit::phi1(next)) ; - while(dd != ne) // turn around the face and insert new edges - { // linked to the central vertex - Dart tmp = Inherit::phi1(ne) ; - Inherit::split_face(tmp, dd) ; - - Dart nne = Inherit::phi2(Inherit::phi_1(dd)) ; - - id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(nne))); - Inherit::set_edge_id(nne, id) ; - Inherit::set_edge_id(Inherit::phi2(nne), id) ; - dd = Inherit::phi1(Inherit::phi1(dd)) ; - } - } - }); - -// Inherit::set_current_level(cur) ; + unsigned int cur = Inherit::get_current_level() ; + + Inherit::set_current_level(Inherit::get_maximum_level() + 1) ; + + //cut edges + Inherit::template foreach_cell([&] (typename Inherit::Edge e) + { + Dart dd = Inherit::phi2(e); + Inherit::cut_edge(e); + + unsigned int eid = Inherit::get_edge_id(e); + Inherit::set_edge_id(Inherit::phi1(e), eid); + Inherit::set_edge_id(Inherit::phi1(dd), eid); + }); + + //cut faces + Inherit::template foreach_cell([&] (typename Inherit::Face d) + { + Dart old = d ; + + if(Inherit::get_dart_level(old) == Inherit::get_maximum_level()) + old = Inherit::phi1(old) ; + + unsigned int cur = Inherit::get_current_level(); + Inherit::set_current_level(cur - 1); + unsigned int degree = Inherit::face_degree(old) ; + Inherit::set_current_level(cur); + + if(degree == 3) + { + Dart dd = Inherit::phi1(old) ; + Dart e = Inherit::phi1(Inherit::phi1(dd)) ; + // insert a new edge + Inherit::split_face(dd, e) ; + + unsigned int id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); + Inherit::set_edge_id(Inherit::phi_1(dd), id) ; // set the edge id of the inserted + Inherit::set_edge_id(Inherit::phi_1(e), id) ; // edge to the next available id + + dd = e ; + e = Inherit::phi1(Inherit::phi1(dd)) ; + Inherit::split_face(dd, e) ; + id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); + Inherit::set_edge_id(Inherit::phi_1(dd), id) ; + Inherit::set_edge_id(Inherit::phi_1(e), id) ; + + dd = e ; + e = Inherit::phi1(Inherit::phi1(dd)) ; + Inherit::split_face(dd, e) ; + id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); + Inherit::set_edge_id(Inherit::phi_1(dd), id) ; + Inherit::set_edge_id(Inherit::phi_1(e), id) ; + } + else + { + Dart dd = Inherit::phi1(old) ; + Dart next = Inherit::phi1(Inherit::phi1(dd)) ; + Inherit::split_face(dd, next) ; // insert a first edge + + Dart ne = Inherit::phi2(Inherit::phi_1(dd)) ; + Dart ne2 = Inherit::phi2(ne) ; + Inherit::cut_edge(ne) ; // cut the new edge to insert the central vertex + + unsigned int id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(ne))); + Inherit::set_edge_id(ne, id) ; + Inherit::set_edge_id(Inherit::phi2(ne), id) ; // set the edge id of the inserted + + id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(ne2)); + Inherit::set_edge_id(ne2, id) ; // edges to the next available ids + Inherit::set_edge_id(Inherit::phi2(ne2), id) ; + + dd = Inherit::phi1(Inherit::phi1(next)) ; + while(dd != ne) // turn around the face and insert new edges + { // linked to the central vertex + Dart tmp = Inherit::phi1(ne) ; + Inherit::split_face(tmp, dd) ; + + Dart nne = Inherit::phi2(Inherit::phi_1(dd)) ; + + id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(nne))); + Inherit::set_edge_id(nne, id) ; + Inherit::set_edge_id(Inherit::phi2(nne), id) ; + dd = Inherit::phi1(Inherit::phi1(dd)) ; + } + } + }); + + // Inherit::set_current_level(cur) ; } }; } // namespace cgogn -#endif // CORE_CPH_IHCMAP2_REGULAR_H_ +#endif // MULTIRESOLUTION_CPH_IHCMAP2_REGULAR_H_ diff --git a/cgogn/multiresolution/cph/ihcmap_base.h b/cgogn/multiresolution/cph/ihcmap_base.h index aef5ee6d..b38e7174 100644 --- a/cgogn/multiresolution/cph/ihcmap_base.h +++ b/cgogn/multiresolution/cph/ihcmap_base.h @@ -21,8 +21,8 @@ * * *******************************************************************************/ -#ifndef CORE_CPH_CPH_H_ -#define CORE_CPH_CPH_H_ +#ifndef MULTIRESOLUTION_CPH_IHCMAP_BASE_H_ +#define MULTIRESOLUTION_CPH_IHCMAP_BASE_H_ #include #include @@ -37,8 +37,8 @@ class IHCMapBase template using ChunkArray = cgogn::ChunkArray; - template - using ChunkArrayContainer = cgogn::ChunkArrayContainer; + template + using ChunkArrayContainer = cgogn::ChunkArrayContainer; protected: unsigned int current_level_; @@ -46,26 +46,26 @@ class IHCMapBase // DartAttributeHandler dart_level_ ; // DartAttributeHandler edge_id_ ; - ChunkArray* dart_level_; - ChunkArray* edge_id_; + ChunkArray* dart_level_; + ChunkArray* edge_id_; std::vector nb_darts_per_level; - ChunkArrayContainer& topo_; + ChunkArrayContainer& topo_; public: - IHCMapBase(ChunkArrayContainer& topology): - topo_(topology), - current_level_(0), - maximum_level_(0) - { - init(); - } + IHCMapBase(ChunkArrayContainer& topology): + topo_(topology), + current_level_(0), + maximum_level_(0) + { + init(); + } ~IHCMapBase() { - topo_.remove_attribute(dart_level_); - topo_.remove_attribute(edge_id_); + topo_.remove_attribute(dart_level_); + topo_.remove_attribute(edge_id_); } IHCMapBase(Self const&) = delete; @@ -77,8 +77,8 @@ class IHCMapBase void init() { - dart_level_ = topo_.template add_attribute("dartLevel") ; - edge_id_ = topo_.template add_attribute("edgeId"); + dart_level_ = topo_.template add_attribute("dartLevel") ; + edge_id_ = topo_.template add_attribute("edgeId"); } /*************************************************** @@ -107,12 +107,12 @@ class IHCMapBase inline unsigned int get_dart_level(Dart d) const { - return (*dart_level_)[d.index] ; + return (*dart_level_)[d.index] ; } inline void set_dart_level(Dart d, unsigned int l) { - (*dart_level_)[d.index] = l ; + (*dart_level_)[d.index] = l ; } /*************************************************** @@ -121,12 +121,12 @@ class IHCMapBase inline unsigned int get_edge_id(Dart d) const { - return (*edge_id_)[d.index] ; + return (*edge_id_)[d.index] ; } inline void set_edge_id(Dart d, unsigned int i) { - (*edge_id_)[d.index] = i ; + (*edge_id_)[d.index] = i ; } inline unsigned int get_tri_refinement_edge_id(Dart d, Dart e) const @@ -153,7 +153,7 @@ class IHCMapBase } inline unsigned int get_quad_refinement_edge_id(Dart d) const - { + { unsigned int e_id = get_edge_id(d); if(e_id == 0u) @@ -179,4 +179,4 @@ class IHCMapBase } // namespace cgogn -#endif // CORE_CPH_CPH_H_ +#endif // MULTIRESOLUTION_CPH_IHCMAP_BASE_H_ diff --git a/cgogn/multiresolution/examples/cph/cph2.cpp b/cgogn/multiresolution/examples/cph/cph2.cpp index a6618dd9..08b10a88 100644 --- a/cgogn/multiresolution/examples/cph/cph2.cpp +++ b/cgogn/multiresolution/examples/cph/cph2.cpp @@ -1,5 +1,5 @@ -#include +#include using namespace cgogn; From 0574e24e2462a6aadb4d3165f0ac837920129b90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Thu, 4 Feb 2016 11:16:02 +0100 Subject: [PATCH 038/402] avoid dividing by zero when computing vertex_normal ! MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/geometry/algos/normal.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/cgogn/geometry/algos/normal.h b/cgogn/geometry/algos/normal.h index a00a8799..2a94734c 100644 --- a/cgogn/geometry/algos/normal.h +++ b/cgogn/geometry/algos/normal.h @@ -78,6 +78,8 @@ inline VEC3 face_normal(const MAP& map, Cell f, const typename MAP: template inline VEC3 vertex_normal(const MAP& map, Cell v, const typename MAP::template VertexAttributeHandler& position) { + using Scalar = typename VEC3::Scalar; + VEC3 n{0,0,0}; const VEC3& p = position[v.dart]; map.foreach_incident_face(v, [&] (Cell f) @@ -85,8 +87,9 @@ inline VEC3 vertex_normal(const MAP& map, Cell v, const typename M VEC3 facen = face_normal(map, f, position); const VEC3& p1 = position[map.phi1(f.dart)]; const VEC3& p2 = position[map.phi_1(f.dart)]; - typename VEC3::Scalar l = (p1-p).squaredNorm() * (p2-p).squaredNorm(); - facen *= convex_face_area(map, f, position) / l; + const Scalar l = (p1-p).squaredNorm() * (p2-p).squaredNorm(); + if (l != Scalar(0)) + facen *= convex_face_area(map, f, position) / l; n += facen; }); normalize_safe(n); @@ -96,6 +99,8 @@ inline VEC3 vertex_normal(const MAP& map, Cell v, const typename M template inline VEC3 vertex_normal(const MAP& map, Cell v, const typename MAP::template VertexAttributeHandler& position, const typename MAP::template AttributeHandler& fnormal) { + using Scalar = typename VEC3::Scalar; + VEC3 n{0,0,0}; const VEC3& p = position[v.dart]; map.foreach_incident_face(v, [&] (Cell f) @@ -103,8 +108,9 @@ inline VEC3 vertex_normal(const MAP& map, Cell v, const typename M VEC3 facen = fnormal[f]; const VEC3& p1 = position[map.phi1(f.dart)]; const VEC3& p2 = position[map.phi_1(f.dart)]; - typename VEC3::Scalar l = (p1-p).squaredNorm() * (p2-p).squaredNorm(); - facen *= convex_face_area(map, f, position) / l; + const Scalar l = (p1-p).squaredNorm() * (p2-p).squaredNorm(); + if (l != Scalar(0)) + facen *= convex_face_area(map, f, position) / l; n += facen; }); normalize_safe(n); From f32d1ae434450b8b83b8d8e3bb51cc861a6f7158 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Thu, 4 Feb 2016 11:19:27 +0100 Subject: [PATCH 039/402] Using the "sliding windows" technique. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/map_base.h | 251 +++++++++++++++++++++---------------- 1 file changed, 144 insertions(+), 107 deletions(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 3b6804ab..c2dd7e14 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -148,12 +148,12 @@ class MapBase : public MapBaseData } /** - * \brief Removes a topological element of PRIM_SIZE + * \brief Removes a topological element of PRIM_SIZE * from the topology container * \details Removing a topological element consists in * removing PRIM_SIZE lines of the topological container starting - * from index - * + * from index + * * \param int [description] */ inline void remove_topology_element(unsigned int index) @@ -557,43 +557,53 @@ class MapBase : public MapBaseData static_assert(check_func_ith_parameter_type(FUNC, 1, unsigned int), "Wrong function second parameter type"); using Future = std::future< typename std::result_of::type >; + using VecDarts = std::vector; - const unsigned int nb_chunks = this->nb_darts()/PARALLEL_BUFFER_SIZE + 1u; ThreadPool* thread_pool = cgogn::get_thread_pool(); + const unsigned int nb_threads_pool = thread_pool->get_nb_threads(); + + std::array, 2> dart_buffers; + std::array, 2> futures; + dart_buffers[0].reserve(nb_threads_pool); + dart_buffers[1].reserve(nb_threads_pool); + futures[0].reserve(nb_threads_pool); + futures[1].reserve(nb_threads_pool); + Buffers* dbuffs = cgogn::get_dart_buffers(); - std::vector*> dart_buffers; - std::vector futures; - futures.reserve(nb_chunks); - dart_buffers.reserve(nb_chunks); Dart it = Dart(this->topology_.begin()); const Dart end = Dart(this->topology_.end()); - for (unsigned int i = 0u; i < nb_chunks && it != end; ++i) + while (it != end) { - dart_buffers.push_back(dbuffs->get_buffer()); - std::vector* darts = dart_buffers.back(); - darts->reserve(PARALLEL_BUFFER_SIZE); - for (unsigned j = 0u; j < PARALLEL_BUFFER_SIZE && it != end; ++j) + for (unsigned i = 0u; i < 2u; ++i) { - darts->push_back(it); - this->topology_.next(it.index); + for (unsigned int j = 0u; j < cgogn::MAX_NB_THREADS && it != end ; ++j) + { + dart_buffers[i].push_back(dbuffs->get_buffer()); + std::vector& darts = *dart_buffers[i].back(); + darts.reserve(PARALLEL_BUFFER_SIZE); + for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != end; ++k) + { + darts.push_back(it); + this->topology_.next(it.index); + } + futures[i].push_back(thread_pool->enqueue( [&darts ,&f](unsigned int th_id){ + for (auto d : darts) + f(d,th_id); + })); + } + const unsigned int id = (i+1u)%2u; + for (auto& fu: futures[id]) + fu.wait(); + for (auto &b : dart_buffers[id]) + dbuffs->release_cell_buffer(b); + + futures[id].clear(); + dart_buffers[id].clear(); } - - futures.push_back(thread_pool->enqueue( [darts ,&f](unsigned int k){ - for (auto d : (*darts)) - f(d,k); - })); - } - - for (auto& fu: futures) - { - fu.wait(); - } - for (auto &b : dart_buffers) - dbuffs->release_buffer(b); } /** @@ -735,12 +745,16 @@ class MapBase : public MapBaseData using VecCell = std::vector>; using Future = std::future< typename std::result_of, unsigned int)>::type >; - std::vector cells_buffers; - std::vector futures; - cells_buffers.reserve(512u); - futures.reserve(512u); - ThreadPool* thread_pool = cgogn::get_thread_pool(); + const unsigned int nb_threads_pool = thread_pool->get_nb_threads(); + + std::array, 2> cells_buffers; + std::array, 2> futures; + cells_buffers[0].reserve(nb_threads_pool); + cells_buffers[1].reserve(nb_threads_pool); + futures[0].reserve(nb_threads_pool); + futures[1].reserve(nb_threads_pool); + Buffers* dbuffs = cgogn::get_dart_buffers(); DartMarker dm(*to_concrete()); @@ -749,32 +763,38 @@ class MapBase : public MapBaseData while (it != end) { - const unsigned int index = cells_buffers.size(); - cells_buffers.push_back(dbuffs->template get_cell_buffer>()); - VecCell& cells = *cells_buffers.back(); - cells.reserve(PARALLEL_BUFFER_SIZE); - - for (unsigned int j = 0u ; j < PARALLEL_BUFFER_SIZE && it != end;) + for (unsigned i = 0u; i < 2u; ++i) { - if (!dm.is_marked(it)) + for (unsigned int j = 0u; j < nb_threads_pool && it != end ; ++j) { - dm.template mark_orbit(it); - cells.push_back(Cell(it)); - ++j; + cells_buffers[i].push_back(dbuffs->template get_cell_buffer>()); + VecCell& cells = *cells_buffers[i].back(); + cells.reserve(PARALLEL_BUFFER_SIZE); + for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != end; ) + { + if (!dm.is_marked(it)) + { + dm.template mark_orbit(it); + cells.push_back(Cell(it)); + ++k; + } + this->topology_.next(it.index); + } + futures[i].push_back(thread_pool->enqueue( [&cells,&f](unsigned int th_id){ + for (auto c : cells) + f(c,th_id); + })); } - this->topology_.next(it.index); + const unsigned int id = (i+1u)%2u; + for (auto& fu: futures[id]) + fu.wait(); + for (auto &b : cells_buffers[id]) + dbuffs->release_cell_buffer(b); + + futures[id].clear(); + cells_buffers[id].clear(); } - futures.emplace_back(thread_pool->enqueue( [&cells_buffers,&f,index](unsigned int i){ - for (auto c : *(cells_buffers[index])) - f(c,i); - })); - } - for (auto& fu: futures) - { - fu.wait(); } - for (auto &b : cells_buffers) - dbuffs->release_cell_buffer(b); } template @@ -799,48 +819,56 @@ class MapBase : public MapBaseData using VecCell = std::vector>; using Future = std::future< typename std::result_of, unsigned int)>::type >; - const unsigned int nb_chunks = this->nb_cells()/PARALLEL_BUFFER_SIZE + 1u; + ThreadPool* thread_pool = cgogn::get_thread_pool(); + const unsigned int nb_threads_pool = thread_pool->get_nb_threads(); - std::vector cells_buffers; - std::vector futures; - cells_buffers.reserve(nb_chunks); - futures.reserve(nb_chunks); + std::array, 2> cells_buffers; + std::array, 2> futures; + cells_buffers[0].reserve(nb_threads_pool); + cells_buffers[1].reserve(nb_threads_pool); + futures[0].reserve(nb_threads_pool); + futures[1].reserve(nb_threads_pool); - ThreadPool* thread_pool = cgogn::get_thread_pool(); Buffers* dbuffs = cgogn::get_dart_buffers(); CellMarker cm(*to_concrete()); Dart it = Dart(this->topology_.begin()); const Dart end = Dart(this->topology_.end()); - for (unsigned int i = 0u; i < nb_chunks; ++i) + while (it != end) { - cells_buffers.push_back(dbuffs->template get_cell_buffer>()); - VecCell& cells = *cells_buffers.back(); - cells.reserve(PARALLEL_BUFFER_SIZE); - - for (unsigned int j = 0u; j < PARALLEL_BUFFER_SIZE && it != end;) + for (unsigned i = 0u; i < 2u; ++i) { - if (!cm.is_marked(it)) + for (unsigned int j = 0u; j < nb_threads_pool && it != end ; ++j) { - cm.mark(it); - cells.push_back(it); - ++j; + cells_buffers[i].push_back(dbuffs->template get_cell_buffer>()); + VecCell& cells = *cells_buffers[i].back(); + cells.reserve(PARALLEL_BUFFER_SIZE); + for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != end; ) + { + if (!cm.is_marked(it)) + { + cm.mark(it); + cells.push_back(it); + ++k; + } + this->topology_.next(it.index); + } + futures[i].push_back(thread_pool->enqueue( [&cells,&f](unsigned int th_id){ + for (auto c : cells) + f(c,th_id); + })); } - this->topology_.next(it.index); + const unsigned int id = (i+1u)%2u; + for (auto& fu: futures[id]) + fu.wait(); + for (auto &b : cells_buffers[id]) + dbuffs->release_cell_buffer(b); + + futures[id].clear(); + cells_buffers[id].clear(); } - futures.emplace_back(thread_pool->enqueue( [&cells,&f](unsigned int i){ - for (auto c : cells) - f(c,i); - })); - } - - for (auto& fu: futures) - { - fu.wait(); } - for (auto &b : cells_buffers) - dbuffs->release_cell_buffer(b); } template @@ -860,14 +888,17 @@ class MapBase : public MapBaseData using VecCell = std::vector>; using Future = std::future< typename std::result_of, unsigned int)>::type >; - const unsigned int nb_chunks = this->nb_cells()/PARALLEL_BUFFER_SIZE + 1u; + ThreadPool* thread_pool = cgogn::get_thread_pool(); + const unsigned int nb_threads_pool = thread_pool->get_nb_threads(); + + std::array, 2> cells_buffers; + std::array, 2> futures; + cells_buffers[0].reserve(nb_threads_pool); + cells_buffers[1].reserve(nb_threads_pool); + futures[0].reserve(nb_threads_pool); + futures[1].reserve(nb_threads_pool); - std::vector cells_buffers; - std::vector futures; - cells_buffers.reserve(nb_chunks); - futures.reserve(nb_chunks); - ThreadPool* thread_pool = cgogn::get_thread_pool(); Buffers* dbuffs = cgogn::get_dart_buffers(); unsigned int it = this->attributes_[ORBIT].begin(); @@ -876,29 +907,35 @@ class MapBase : public MapBaseData const auto& cache = *(this->global_topo_cache_[ORBIT]); const auto& attr = this->attributes_[ORBIT]; - for (unsigned int i = 0u; i < nb_chunks; ++i) + while (it != end) { - cells_buffers.push_back(dbuffs->template get_cell_buffer>()); - VecCell& cells = *cells_buffers.back(); - cells.reserve(PARALLEL_BUFFER_SIZE); - - for (unsigned int j = 0u; j < PARALLEL_BUFFER_SIZE && it != end; ++j) + for (unsigned i = 0u; i < 2u; ++i) { - cells.push_back(cache[it]); - attr.next(it); + for (unsigned int j = 0u; j < nb_threads_pool && it != end ; ++j) + { + cells_buffers[i].push_back(dbuffs->template get_cell_buffer>()); + VecCell& cells = *cells_buffers[i].back(); + cells.reserve(PARALLEL_BUFFER_SIZE); + for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != end; ++k) + { + cells.push_back(cache[it]); + attr.next(it); + } + futures[i].push_back(thread_pool->enqueue( [&cells,&f](unsigned int th_id){ + for (auto c : cells) + f(c,th_id); + })); + } + const unsigned int id = (i+1u)%2u; + for (auto& fu: futures[id]) + fu.wait(); + for (auto &b : cells_buffers[id]) + dbuffs->release_cell_buffer(b); + + futures[id].clear(); + cells_buffers[id].clear(); } - futures.emplace_back(thread_pool->enqueue( [&cells,&f](unsigned int i){ - for (auto c : cells) - f(c,i); - })); - } - - for (auto& fu: futures) - { - fu.wait(); } - for (auto &b : cells_buffers) - dbuffs->release_cell_buffer(b); } template From 2fe05c4ccfbea59280d6dee6d7b54c0fcaf1d69f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Thu, 4 Feb 2016 11:25:23 +0100 Subject: [PATCH 040/402] Updated the multithreading bench : computing vertices normals. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- .../multithreading/bench_multithreading.cpp | 190 +++++++++++++++++- 1 file changed, 184 insertions(+), 6 deletions(-) diff --git a/benchmarks/multithreading/bench_multithreading.cpp b/benchmarks/multithreading/bench_multithreading.cpp index ab3c7a66..52a90355 100644 --- a/benchmarks/multithreading/bench_multithreading.cpp +++ b/benchmarks/multithreading/bench_multithreading.cpp @@ -32,16 +32,17 @@ #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) -struct MyMapTraits : public cgogn::DefaultMapTraits -{ - static const unsigned int CHUNK_SIZE = 8192; -}; -using Map2 = cgogn::CMap2; + +using Map2 = cgogn::CMap2; + +const cgogn::Orbit VERTEX = Map2::VERTEX; +using Vertex = cgogn::Cell; + const cgogn::Orbit FACE = Map2::FACE; using Face = cgogn::Cell; -const unsigned int ITERATIONS = 10000u; +const unsigned int ITERATIONS = 1u; using Vec3 = Eigen::Vector3d; //using Vec3 = cgogn::geometry::Vec_T>; @@ -275,6 +276,183 @@ int main(int argc, char** argv) }); } + + + + VertexAttributeHandler vertex_normal = map.add_attribute("normal"); + VertexAttributeHandler vertex_normal_mt = map.add_attribute("normal_mt"); + + + // VERTICES NORMALS + + + + // DART MARKING + + { + std::chrono::time_point start, end; + start = std::chrono::system_clock::now(); + + for (unsigned int i = 0u ; i < ITERATIONS; ++i) + { + map.template foreach_cell([&] (Vertex v) + { + vertex_normal[v] = cgogn::geometry::vertex_normal(map, v, vertex_position); + }); + } + end = std::chrono::system_clock::now(); + std::chrono::duration elapsed_seconds = end - start; + std::cout << std::fixed << "SINGLE THREAD "<< elapsed_seconds.count() << "s || compute_normal_vertices dart marking" << std::endl; + } + + { + std::chrono::time_point start, end; + start = std::chrono::system_clock::now(); + for (unsigned int i = 0u ; i < ITERATIONS; ++i) + { + map.template parallel_foreach_cell([&] (Vertex v, unsigned int) + { + vertex_normal_mt[v] = cgogn::geometry::vertex_normal(map, v, vertex_position); + }); + } + + // END DART MARKING + + end = std::chrono::system_clock::now(); + std::chrono::duration elapsed_seconds = end - start; + std::cout << std::fixed << cgogn::NB_THREADS << " THREADS "<< elapsed_seconds.count() << "s || compute_normal_vertices dart marking" << std::endl; + } + + + { + // CHECKING VERTEX NORMALS + map.template foreach_cell([&] (Vertex v) + { + Vec3 error = vertex_normal[v] - vertex_normal_mt[v]; + if (!cgogn::almost_equal_absolute(error.squaredNorm(), 0., 1e-9 )) + { + std::cerr << __FILE__ << ":" << __LINE__ << " : there was an error during computation of normals" << std::endl; + std::cerr << "vertex_normal " << vertex_normal[v] << std::endl; + std::cerr << "vertex_normal_mt " < start, end; + start = std::chrono::system_clock::now(); + + for (unsigned int i = 0u ; i < ITERATIONS; ++i) + { + map.template foreach_cell([&] (Vertex v) + { + vertex_normal[v] = cgogn::geometry::vertex_normal(map, v, vertex_position); + }); + } + end = std::chrono::system_clock::now(); + std::chrono::duration elapsed_seconds = end - start; + std::cout << std::fixed << "SINGLE THREAD "<< elapsed_seconds.count() << "s || compute_normal_vertices cell marking" << std::endl; + } + + { + std::chrono::time_point start, end; + start = std::chrono::system_clock::now(); + for (unsigned int i = 0u ; i < ITERATIONS; ++i) + { + map.template parallel_foreach_cell([&] (Vertex v, unsigned int) + { + vertex_normal_mt[v] = cgogn::geometry::vertex_normal(map, v, vertex_position); + }); + } + + + end = std::chrono::system_clock::now(); + std::chrono::duration elapsed_seconds = end - start; + std::cout << std::fixed << cgogn::NB_THREADS << " THREADS "<< elapsed_seconds.count() << "s || compute_normal_vertices cell marking" << std::endl; + } + + // END CELL MARKING + + + { + // CHECKING VERTEX NORMALS + map.template foreach_cell([&] (Vertex v) + { + Vec3 error = vertex_normal[v] - vertex_normal_mt[v]; + if (!cgogn::almost_equal_absolute(error.squaredNorm(), 0., 1e-9 )) + { + std::cerr << __FILE__ << ":" << __LINE__ << " : there was an error during computation of normals" << std::endl; + std::cerr << "vertex_normal " << vertex_normal[v] << std::endl; + std::cerr << "vertex_normal_mt " <(); + + { + std::chrono::time_point start, end; + start = std::chrono::system_clock::now(); + + for (unsigned int i = 0u ; i < ITERATIONS; ++i) + { + map.template foreach_cell([&] (Vertex v) + { + vertex_normal[v] = cgogn::geometry::vertex_normal(map, v, vertex_position); + }); + } + end = std::chrono::system_clock::now(); + std::chrono::duration elapsed_seconds = end - start; + std::cout << std::fixed << "SINGLE THREAD "<< elapsed_seconds.count() << "s || compute_normal_vertices topo cache" << std::endl; + } + + { + std::chrono::time_point start, end; + start = std::chrono::system_clock::now(); + for (unsigned int i = 0u ; i < ITERATIONS; ++i) + { + map.template parallel_foreach_cell([&] (Vertex v, unsigned int) + { + vertex_normal_mt[v] = cgogn::geometry::vertex_normal(map, v, vertex_position); + }); + } + + + end = std::chrono::system_clock::now(); + std::chrono::duration elapsed_seconds = end - start; + std::cout << std::fixed << cgogn::NB_THREADS << " THREADS "<< elapsed_seconds.count() << "s || compute_normal_vertices topo cache" << std::endl; + } + + + { + // CHECKING VERTEX NORMALS + map.template foreach_cell([&] (Vertex v) + { + Vec3 error = vertex_normal[v] - vertex_normal_mt[v]; + if (!cgogn::almost_equal_absolute(error.squaredNorm(), 0., 1e-9 )) + { + std::cerr << __FILE__ << ":" << __LINE__ << " : there was an error during computation of normals" << std::endl; + std::cerr << "vertex_normal " << vertex_normal[v] << std::endl; + std::cerr << "vertex_normal_mt " < Date: Thu, 4 Feb 2016 14:43:35 +0100 Subject: [PATCH 041/402] multiresolution analysis avoiding multiple functor declaration --- cgogn/multiresolution/cph/ihcmap2.h | 4 +- cgogn/multiresolution/cph/ihcmap2_regular.h | 2 +- cgogn/multiresolution/cph/ihcmap_base.h | 10 +++ cgogn/multiresolution/examples/cph/cph2.cpp | 39 +++++++++- .../mranalysis/lerp_triquad_mra.h | 72 ++++++++++--------- 5 files changed, 89 insertions(+), 38 deletions(-) diff --git a/cgogn/multiresolution/cph/ihcmap2.h b/cgogn/multiresolution/cph/ihcmap2.h index f986c040..4a3c2722 100644 --- a/cgogn/multiresolution/cph/ihcmap2.h +++ b/cgogn/multiresolution/cph/ihcmap2.h @@ -129,7 +129,7 @@ class IHCMap2_T : public CMap2_T, public IHCMapBase, public IHCMapBase, public IHCMapBaserelease_buffer(visited_faces); } +public: template inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const { diff --git a/cgogn/multiresolution/cph/ihcmap2_regular.h b/cgogn/multiresolution/cph/ihcmap2_regular.h index 22e64953..bedef434 100644 --- a/cgogn/multiresolution/cph/ihcmap2_regular.h +++ b/cgogn/multiresolution/cph/ihcmap2_regular.h @@ -249,7 +249,7 @@ class IHCMap2Regular : public IHCMap2 } }); - // Inherit::set_current_level(cur) ; + Inherit::set_current_level(cur) ; } }; diff --git a/cgogn/multiresolution/cph/ihcmap_base.h b/cgogn/multiresolution/cph/ihcmap_base.h index b38e7174..d53fa63e 100644 --- a/cgogn/multiresolution/cph/ihcmap_base.h +++ b/cgogn/multiresolution/cph/ihcmap_base.h @@ -115,6 +115,16 @@ class IHCMapBase (*dart_level_)[d.index] = l ; } + inline void inc_current_level() + { + set_current_level(get_current_level() + 1); + } + + inline void dec_current_level() + { + set_current_level(get_current_level() - 1); + } + /*************************************************** * EDGE ID MANAGEMENT * ***************************************************/ diff --git a/cgogn/multiresolution/examples/cph/cph2.cpp b/cgogn/multiresolution/examples/cph/cph2.cpp index 08b10a88..c2eb9ace 100644 --- a/cgogn/multiresolution/examples/cph/cph2.cpp +++ b/cgogn/multiresolution/examples/cph/cph2.cpp @@ -1,10 +1,16 @@ #include +#include + +#include + + using namespace cgogn; using IHMap2 = IHCMap2Regular; +using Vec3 = Eigen::Vector3d; template using VertexAttributeHandler = IHMap2::VertexAttributeHandler; @@ -12,9 +18,10 @@ using VertexAttributeHandler = IHMap2::VertexAttributeHandler; int main() { - IHMap2 map; + IHMap2 map; + VertexAttributeHandler position = map.get_attribute("position"); - // VertexAttributeHandler vertex_position_ = map.get_attribute("position"); + LerpTriQuadMRAnalysis lerp(map, position); map.add_face(4); @@ -26,6 +33,33 @@ int main() std::cout << "End Faces" << std::endl; + { + lerp.add_level(); + lerp.synthesis(); + + std::cout << "after add level Faces :" << std::endl; + map.template foreach_cell([&] (typename IHMap2::Face f) + { + std::cout << f << " | " << map.get_dart_level(f.dart) << std::endl; + }); + std::cout << "End Faces" << std::endl; + + + unsigned int cur = map.get_current_level(); + + std::cout << "current level = " << cur << std::endl; + map.set_current_level(cur - 1); + + std::cout << "after add level Faces :" << std::endl; + map.template foreach_cell([&] (typename IHMap2::Face f) + { + std::cout << f << " | " << map.get_dart_level(f.dart) << std::endl; + }); + std::cout << "End Vertices" << std::endl; + } + + /* + { map.add_mixed_level(); @@ -73,6 +107,7 @@ int main() }); std::cout << "End Vertices" << std::endl; } + */ return 0; } diff --git a/cgogn/multiresolution/mranalysis/lerp_triquad_mra.h b/cgogn/multiresolution/mranalysis/lerp_triquad_mra.h index 0b9e3da6..68cbc396 100644 --- a/cgogn/multiresolution/mranalysis/lerp_triquad_mra.h +++ b/cgogn/multiresolution/mranalysis/lerp_triquad_mra.h @@ -1,27 +1,37 @@ -#ifndef MRA_H -#define MRA_H +#ifndef MULTIRESOLUTION_MRANALYSIS_LERP_TRI_QUAD_MRANALYSIS_H_ +#define MULTIRESOLUTION_MRANALYSIS_LERP_TRI_QUAD_MRANALYSIS_H_ +#include + +namespace cgogn { template class LerpTriQuadMRAnalysis { - MRMAP& map_; - typename MRMAP::VertexAttribute va_; +public: + using Self = LerpTriQuadMRAnalysis; - LerpTriQuadMRAnalysis(MRMAP& map): - map_(map) - { - synthesis_filters_.emplace_back(lerp_quad_odd_synthesis_); - } + using VertexAttributeHandler = typename MRMAP::template VertexAttributeHandler; protected: std::vector> synthesis_filters_; std::vector> analysis_filters_; + MRMAP& map_; + VertexAttributeHandler& va_; + +public: + LerpTriQuadMRAnalysis(MRMAP& map, VertexAttributeHandler& v): + map_(map), + va_(v) + { + synthesis_filters_.push_back(lerp_tri_quad_odd_synthesis_); + } + protected: - std::function lerp_tri_quad_odd_synthesis_ = [] () + std::function lerp_tri_quad_odd_synthesis_ = [this] () { map_.template foreach_cell([&] (typename MRMAP::Face f) { @@ -34,11 +44,11 @@ class LerpTriQuadMRAnalysis map_.template foreach_incident_edge(f, [&] (typename MRMAP::Edge e) { - vf += v[e]; - map_.incCurrentLevel(); - ef += v[map_.phi1(e)]; - map_.decCurrentLevel(); - ++count; + vf += va_[e.dart]; + map_.inc_current_level(); + ef += va_[map_.phi1(e.dart)]; + map_.dec_current_level(); + ++count; }); ef /= count; @@ -46,31 +56,26 @@ class LerpTriQuadMRAnalysis vf /= count; - map_.incCurrentLevel() ; - Dart midF = map_.phi1(map_.phi1(f)); - m_position[midF] += vf + ef ; - map_.decCurrentLevel() ; + map_.inc_current_level() ; + Dart midF = map_.phi1(map_.phi1(f.dart)); + va_[midF] += vf + ef ; + map_.dec_current_level() ; } }); map_.template foreach_cell([&] (typename MRMAP::Edge e) { - VEC3 ve = (v[e] + v[map_.phi1(e)]) * typename VEC3::TYPE(0.5); + VEC3 ve = (va_[e.dart] + va_[map_.phi1(e)]) * 0.5; - map_.incCurrentLevel() ; + map_.inc_current_level() ; Dart midV = map_.phi1(e) ; - m_position[midV] += ve ; - map_.decCurrentLevel() ; + va_[midV] += ve ; + map_.dec_current_level() ; }); }; public: - inline set_attribute(typename MRMAP::VertexAttribute& v) - { - va_ = v; - } - void analysis() { cgogn_message_assert(map_.get_current_level() > 0, "analysis : called on level 0") ; @@ -78,17 +83,17 @@ class LerpTriQuadMRAnalysis map_.dec_current_level() ; for(unsigned int i = 0; i < analysis_filters_.size(); ++i) - (*analysis_filters_[i])() ; + analysis_filters_[i](); } void synthesis() { - cgogn_message_assert(map_.getCurrentLevel() < map_.getMaxLevel(), "synthesis : called on max level") ; + cgogn_message_assert(map_.get_current_level() < map_.get_maximum_level(), "synthesis : called on max level") ; for(unsigned int i = 0; i < synthesis_filters_.size(); ++i) - (*synthesis_filters_[i])() ; + synthesis_filters_[i](); - map_.incCurrentLevel(); + map_.inc_current_level(); } void add_level() @@ -98,6 +103,7 @@ class LerpTriQuadMRAnalysis }; +} //namespace cgogn -#endif // MRA_H +#endif // MULTIRESOLUTION_MRANALYSIS_LERP_TRI_QUAD_MRANALYSIS_H_ From 7fef9459f1ef4b97764f633bc6116604568034fb Mon Sep 17 00:00:00 2001 From: lionel untereiner Date: Thu, 4 Feb 2016 14:50:07 +0100 Subject: [PATCH 042/402] push_back -> emplace_back (?) --- cgogn/multiresolution/mranalysis/lerp_triquad_mra.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cgogn/multiresolution/mranalysis/lerp_triquad_mra.h b/cgogn/multiresolution/mranalysis/lerp_triquad_mra.h index 68cbc396..7a9f2de8 100644 --- a/cgogn/multiresolution/mranalysis/lerp_triquad_mra.h +++ b/cgogn/multiresolution/mranalysis/lerp_triquad_mra.h @@ -26,7 +26,7 @@ class LerpTriQuadMRAnalysis map_(map), va_(v) { - synthesis_filters_.push_back(lerp_tri_quad_odd_synthesis_); + synthesis_filters_.emplace_back(lerp_tri_quad_odd_synthesis_); } protected: From 5523caa56e5ed943847a8374fd9e0006fbd64ac1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Thu, 4 Feb 2016 15:51:59 +0100 Subject: [PATCH 043/402] added google benchmark MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- CMakeLists.txt | 3 +- thirdparty/CMakeLists.txt | 4 + thirdparty/google-benchmark/.gitignore | 46 + thirdparty/google-benchmark/.travis-setup.sh | 26 + thirdparty/google-benchmark/.travis.yml | 41 + .../google-benchmark/.ycm_extra_conf.py | 115 +++ thirdparty/google-benchmark/AUTHORS | 30 + thirdparty/google-benchmark/CMakeLists.txt | 108 ++ thirdparty/google-benchmark/CONTRIBUTING.md | 58 ++ thirdparty/google-benchmark/CONTRIBUTORS | 46 + thirdparty/google-benchmark/LICENSE | 202 ++++ thirdparty/google-benchmark/README.md | 295 ++++++ thirdparty/google-benchmark/appveyor.yml | 55 ++ .../cmake/AddCXXCompilerFlag.cmake | 37 + .../cmake/CXXFeatureCheck.cmake | 39 + .../cmake/GetGitVersion.cmake | 51 + .../cmake/gnu_posix_regex.cpp | 12 + .../google-benchmark/cmake/posix_regex.cpp | 12 + .../google-benchmark/cmake/std_regex.cpp | 10 + .../google-benchmark/cmake/steady_clock.cpp | 7 + .../cmake/thread_safety_attributes.cpp | 4 + .../include/benchmark/benchmark.h | 21 + .../include/benchmark/benchmark_api.h | 602 ++++++++++++ .../include/benchmark/macros.h | 48 + .../include/benchmark/reporter.h | 122 +++ thirdparty/google-benchmark/mingw.py | 320 ++++++ .../google-benchmark/src/CMakeLists.txt | 51 + thirdparty/google-benchmark/src/arraysize.h | 34 + thirdparty/google-benchmark/src/benchmark.cc | 919 ++++++++++++++++++ thirdparty/google-benchmark/src/check.h | 60 ++ thirdparty/google-benchmark/src/colorprint.cc | 116 +++ thirdparty/google-benchmark/src/colorprint.h | 19 + .../google-benchmark/src/commandlineflags.cc | 220 +++++ .../google-benchmark/src/commandlineflags.h | 76 ++ .../google-benchmark/src/console_reporter.cc | 116 +++ .../google-benchmark/src/csv_reporter.cc | 105 ++ thirdparty/google-benchmark/src/cycleclock.h | 137 +++ .../google-benchmark/src/internal_macros.h | 40 + .../google-benchmark/src/json_reporter.cc | 159 +++ thirdparty/google-benchmark/src/log.cc | 40 + thirdparty/google-benchmark/src/log.h | 28 + thirdparty/google-benchmark/src/mutex.h | 142 +++ thirdparty/google-benchmark/src/re.h | 60 ++ thirdparty/google-benchmark/src/re_posix.cc | 59 ++ thirdparty/google-benchmark/src/re_std.cc | 44 + thirdparty/google-benchmark/src/reporter.cc | 86 ++ thirdparty/google-benchmark/src/sleep.cc | 50 + thirdparty/google-benchmark/src/sleep.h | 17 + thirdparty/google-benchmark/src/stat.h | 307 ++++++ .../google-benchmark/src/string_util.cc | 169 ++++ thirdparty/google-benchmark/src/string_util.h | 44 + thirdparty/google-benchmark/src/sysinfo.cc | 416 ++++++++ thirdparty/google-benchmark/src/sysinfo.h | 12 + thirdparty/google-benchmark/src/walltime.cc | 263 +++++ thirdparty/google-benchmark/src/walltime.h | 17 + .../google-benchmark/test/CMakeLists.txt | 89 ++ .../google-benchmark/test/basic_test.cc | 102 ++ .../google-benchmark/test/benchmark_test.cc | 154 +++ .../google-benchmark/test/cxx03_test.cc | 31 + .../google-benchmark/test/filter_test.cc | 91 ++ .../google-benchmark/test/fixture_test.cc | 42 + .../google-benchmark/test/options_test.cc | 26 + 62 files changed, 6654 insertions(+), 1 deletion(-) create mode 100644 thirdparty/google-benchmark/.gitignore create mode 100644 thirdparty/google-benchmark/.travis-setup.sh create mode 100644 thirdparty/google-benchmark/.travis.yml create mode 100644 thirdparty/google-benchmark/.ycm_extra_conf.py create mode 100644 thirdparty/google-benchmark/AUTHORS create mode 100644 thirdparty/google-benchmark/CMakeLists.txt create mode 100644 thirdparty/google-benchmark/CONTRIBUTING.md create mode 100644 thirdparty/google-benchmark/CONTRIBUTORS create mode 100644 thirdparty/google-benchmark/LICENSE create mode 100644 thirdparty/google-benchmark/README.md create mode 100644 thirdparty/google-benchmark/appveyor.yml create mode 100644 thirdparty/google-benchmark/cmake/AddCXXCompilerFlag.cmake create mode 100644 thirdparty/google-benchmark/cmake/CXXFeatureCheck.cmake create mode 100644 thirdparty/google-benchmark/cmake/GetGitVersion.cmake create mode 100644 thirdparty/google-benchmark/cmake/gnu_posix_regex.cpp create mode 100644 thirdparty/google-benchmark/cmake/posix_regex.cpp create mode 100644 thirdparty/google-benchmark/cmake/std_regex.cpp create mode 100644 thirdparty/google-benchmark/cmake/steady_clock.cpp create mode 100644 thirdparty/google-benchmark/cmake/thread_safety_attributes.cpp create mode 100644 thirdparty/google-benchmark/include/benchmark/benchmark.h create mode 100644 thirdparty/google-benchmark/include/benchmark/benchmark_api.h create mode 100644 thirdparty/google-benchmark/include/benchmark/macros.h create mode 100644 thirdparty/google-benchmark/include/benchmark/reporter.h create mode 100644 thirdparty/google-benchmark/mingw.py create mode 100644 thirdparty/google-benchmark/src/CMakeLists.txt create mode 100644 thirdparty/google-benchmark/src/arraysize.h create mode 100644 thirdparty/google-benchmark/src/benchmark.cc create mode 100644 thirdparty/google-benchmark/src/check.h create mode 100644 thirdparty/google-benchmark/src/colorprint.cc create mode 100644 thirdparty/google-benchmark/src/colorprint.h create mode 100644 thirdparty/google-benchmark/src/commandlineflags.cc create mode 100644 thirdparty/google-benchmark/src/commandlineflags.h create mode 100644 thirdparty/google-benchmark/src/console_reporter.cc create mode 100644 thirdparty/google-benchmark/src/csv_reporter.cc create mode 100644 thirdparty/google-benchmark/src/cycleclock.h create mode 100644 thirdparty/google-benchmark/src/internal_macros.h create mode 100644 thirdparty/google-benchmark/src/json_reporter.cc create mode 100644 thirdparty/google-benchmark/src/log.cc create mode 100644 thirdparty/google-benchmark/src/log.h create mode 100644 thirdparty/google-benchmark/src/mutex.h create mode 100644 thirdparty/google-benchmark/src/re.h create mode 100644 thirdparty/google-benchmark/src/re_posix.cc create mode 100644 thirdparty/google-benchmark/src/re_std.cc create mode 100644 thirdparty/google-benchmark/src/reporter.cc create mode 100644 thirdparty/google-benchmark/src/sleep.cc create mode 100644 thirdparty/google-benchmark/src/sleep.h create mode 100644 thirdparty/google-benchmark/src/stat.h create mode 100644 thirdparty/google-benchmark/src/string_util.cc create mode 100644 thirdparty/google-benchmark/src/string_util.h create mode 100644 thirdparty/google-benchmark/src/sysinfo.cc create mode 100644 thirdparty/google-benchmark/src/sysinfo.h create mode 100644 thirdparty/google-benchmark/src/walltime.cc create mode 100644 thirdparty/google-benchmark/src/walltime.h create mode 100644 thirdparty/google-benchmark/test/CMakeLists.txt create mode 100644 thirdparty/google-benchmark/test/basic_test.cc create mode 100644 thirdparty/google-benchmark/test/benchmark_test.cc create mode 100644 thirdparty/google-benchmark/test/cxx03_test.cc create mode 100644 thirdparty/google-benchmark/test/filter_test.cc create mode 100644 thirdparty/google-benchmark/test/fixture_test.cc create mode 100644 thirdparty/google-benchmark/test/options_test.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 90a3433e..4c44ba6a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,7 +40,7 @@ set(CGOGN_THIRDPARTY_DIR ${CMAKE_SOURCE_DIR}/thirdparty) option(CGOGN_PROVIDE_EIGEN "Use the version of eigen that is packaged with CGoGN." ON) option(CGOGN_PROVIDE_TINYXML2 "Use the version of tinyxml2 that is packaged with CGoGN." ON) option(CGOGN_BUILD_TESTS "Build cgogn unit tests using google test framework." ON) -option(CGOGN_BUILD_BENCHS "Build the benchmarks" ON) +option(CGOGN_BUILD_BENCHS "Build the benchmarks using google benchmark framework" ON) option(CGOGN_USE_OPENMP "Activate openMP directives." OFF) if (NOT MSVC) option(CGOGN_USE_PARALLEL_GLIBCXX "Highly experimental : compiles using the parallel mode." OFF) @@ -108,6 +108,7 @@ endif(CGOGN_BUILD_TESTS) add_subdirectory(${CGOGN_THIRDPARTY_DIR}) add_subdirectory(${CGOGN_SOURCE_DIR}) + if(${CGOGN_BUILD_BENCHS}) add_subdirectory(benchmarks) endif(${CGOGN_BUILD_BENCHS}) diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index 0fc31de3..d37e96ba 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -13,3 +13,7 @@ endif(CGOGN_BUILD_TESTS) if(CGOGN_USE_QT) add_subdirectory(libQGLViewer/QOGLViewer) endif(CGOGN_USE_QT) + +if (CGOGN_BUILD_BENCHS) + add_subdirectory(google-benchmark) +endif(CGOGN_BUILD_BENCHS) diff --git a/thirdparty/google-benchmark/.gitignore b/thirdparty/google-benchmark/.gitignore new file mode 100644 index 00000000..3c1b4f21 --- /dev/null +++ b/thirdparty/google-benchmark/.gitignore @@ -0,0 +1,46 @@ +*.a +*.so +*.so.?* +*.dll +*.exe +*.dylib +*.cmake +!/cmake/*.cmake +*~ +*.pyc +__pycache__ + +# lcov +*.lcov +/lcov + +# cmake files. +/Testing +CMakeCache.txt +CMakeFiles/ +cmake_install.cmake + +# makefiles. +Makefile + +# in-source build. +bin/ +lib/ +/test/*_test + +# exuberant ctags. +tags + +# YouCompleteMe configuration. +.ycm_extra_conf.pyc + +# ninja generated files. +.ninja_deps +.ninja_log +build.ninja +install_manifest.txt +rules.ninja + +# out-of-source build top-level folders. +build/ +_build/ diff --git a/thirdparty/google-benchmark/.travis-setup.sh b/thirdparty/google-benchmark/.travis-setup.sh new file mode 100644 index 00000000..c900fa93 --- /dev/null +++ b/thirdparty/google-benchmark/.travis-setup.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +# Before install + +sudo add-apt-repository -y ppa:kalakris/cmake +if [ "$STD" = "c++11" ]; then + sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test + if [ "$CXX" = "clang++" ]; then + wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key | sudo apt-key add - + sudo add-apt-repository -y "deb http://llvm.org/apt/precise/ llvm-toolchain-precise-3.6 main" + fi +fi +sudo apt-get update -qq + +# Install +sudo apt-get install -qq cmake +if [ "$STD" = "c++11" ] && [ "$CXX" = "g++" ]; then + sudo apt-get install -qq gcc-4.8 g++-4.8 + sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 90 + sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 90 +elif [ "$CXX" = "clang++" ]; then + sudo apt-get install -qq clang-3.6 + sudo update-alternatives --install /usr/local/bin/clang clang /usr/bin/clang-3.6 90 + sudo update-alternatives --install /usr/local/bin/clang++ clang++ /usr/bin/clang++-3.6 90 + export PATH=/usr/local/bin:$PATH +fi diff --git a/thirdparty/google-benchmark/.travis.yml b/thirdparty/google-benchmark/.travis.yml new file mode 100644 index 00000000..8b138ce1 --- /dev/null +++ b/thirdparty/google-benchmark/.travis.yml @@ -0,0 +1,41 @@ +language: cpp + +# NOTE: The COMPILER variable is unused. It simply makes the display on +# travis-ci.org more readable. +matrix: + include: + - compiler: gcc + env: COMPILER=g++-4.6 STD=c++0x BUILD_TYPE=Coverage + - compiler: gcc + env: COMPILER=g++-4.6 STD=c++0x BUILD_TYPE=Debug + - compiler: gcc + env: COMPILER=g++-4.6 STD=c++0x BUILD_TYPE=Release + - compiler: gcc + env: COMPILER=g++-4.8 STD=c++11 BUILD_TYPE=Debug + - compiler: gcc + env: COMPILER=g++-4.8 STD=c++11 BUILD_TYPE=Release + - compiler: clang + env: COMPILER=clang++-3.6 STD=c++11 BUILD_TYPE=Debug + - compiler: clang + env: COMPILER=clang++-3.6 STD=c++11 BUILD_TYPE=Release + +before_script: + - source .travis-setup.sh + - mkdir build && cd build + +install: + - if [ "${BUILD_TYPE}" == "Coverage" -a "${TRAVIS_OS_NAME}" == "linux" ]; then + PATH=~/.local/bin:${PATH}; + pip install --user --upgrade pip; + pip install --user cpp-coveralls; + fi + +script: + - cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCMAKE_CXX_FLAGS="-std=${STD}" + - make + - make CTEST_OUTPUT_ON_FAILURE=1 test + +after_success: + - if [ "${BUILD_TYPE}" == "Coverage" -a "${TRAVIS_OS_NAME}" == "linux" ]; then + coveralls --include src --include include --gcov-options '\-lp' --root .. --build-root .; + fi diff --git a/thirdparty/google-benchmark/.ycm_extra_conf.py b/thirdparty/google-benchmark/.ycm_extra_conf.py new file mode 100644 index 00000000..86194357 --- /dev/null +++ b/thirdparty/google-benchmark/.ycm_extra_conf.py @@ -0,0 +1,115 @@ +import os +import ycm_core + +# These are the compilation flags that will be used in case there's no +# compilation database set (by default, one is not set). +# CHANGE THIS LIST OF FLAGS. YES, THIS IS THE DROID YOU HAVE BEEN LOOKING FOR. +flags = [ +'-Wall', +'-Werror', +'-pendantic-errors', +'-std=c++0x', +'-fno-strict-aliasing', +'-O3', +'-DNDEBUG', +# ...and the same thing goes for the magic -x option which specifies the +# language that the files to be compiled are written in. This is mostly +# relevant for c++ headers. +# For a C project, you would set this to 'c' instead of 'c++'. +'-x', 'c++', +'-I', 'include', +'-isystem', '/usr/include', +'-isystem', '/usr/local/include', +] + + +# Set this to the absolute path to the folder (NOT the file!) containing the +# compile_commands.json file to use that instead of 'flags'. See here for +# more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html +# +# Most projects will NOT need to set this to anything; you can just change the +# 'flags' list of compilation flags. Notice that YCM itself uses that approach. +compilation_database_folder = '' + +if os.path.exists( compilation_database_folder ): + database = ycm_core.CompilationDatabase( compilation_database_folder ) +else: + database = None + +SOURCE_EXTENSIONS = [ '.cc' ] + +def DirectoryOfThisScript(): + return os.path.dirname( os.path.abspath( __file__ ) ) + + +def MakeRelativePathsInFlagsAbsolute( flags, working_directory ): + if not working_directory: + return list( flags ) + new_flags = [] + make_next_absolute = False + path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ] + for flag in flags: + new_flag = flag + + if make_next_absolute: + make_next_absolute = False + if not flag.startswith( '/' ): + new_flag = os.path.join( working_directory, flag ) + + for path_flag in path_flags: + if flag == path_flag: + make_next_absolute = True + break + + if flag.startswith( path_flag ): + path = flag[ len( path_flag ): ] + new_flag = path_flag + os.path.join( working_directory, path ) + break + + if new_flag: + new_flags.append( new_flag ) + return new_flags + + +def IsHeaderFile( filename ): + extension = os.path.splitext( filename )[ 1 ] + return extension in [ '.h', '.hxx', '.hpp', '.hh' ] + + +def GetCompilationInfoForFile( filename ): + # The compilation_commands.json file generated by CMake does not have entries + # for header files. So we do our best by asking the db for flags for a + # corresponding source file, if any. If one exists, the flags for that file + # should be good enough. + if IsHeaderFile( filename ): + basename = os.path.splitext( filename )[ 0 ] + for extension in SOURCE_EXTENSIONS: + replacement_file = basename + extension + if os.path.exists( replacement_file ): + compilation_info = database.GetCompilationInfoForFile( + replacement_file ) + if compilation_info.compiler_flags_: + return compilation_info + return None + return database.GetCompilationInfoForFile( filename ) + + +def FlagsForFile( filename, **kwargs ): + if database: + # Bear in mind that compilation_info.compiler_flags_ does NOT return a + # python list, but a "list-like" StringVec object + compilation_info = GetCompilationInfoForFile( filename ) + if not compilation_info: + return None + + final_flags = MakeRelativePathsInFlagsAbsolute( + compilation_info.compiler_flags_, + compilation_info.compiler_working_dir_ ) + else: + relative_to = DirectoryOfThisScript() + final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to ) + + return { + 'flags': final_flags, + 'do_cache': True + } diff --git a/thirdparty/google-benchmark/AUTHORS b/thirdparty/google-benchmark/AUTHORS new file mode 100644 index 00000000..5a4b3553 --- /dev/null +++ b/thirdparty/google-benchmark/AUTHORS @@ -0,0 +1,30 @@ +# This is the official list of benchmark authors for copyright purposes. +# This file is distinct from the CONTRIBUTORS files. +# See the latter for an explanation. +# +# Names should be added to this file as: +# Name or Organization +# The email address is not required for organizations. +# +# Please keep the list sorted. + +Arne Beer +Christopher Seymour +David Coeurjolly +Dominic Hamon +Eugene Zhuk +Evgeny Safronov +Felix Homann +Google Inc. +JianXiong Zhou +Kaito Udagawa +Lei Xu +Matt Clarkson +Oleksandr Sochka +Paul Redmond +Radoslav Yovchev +Shuo Chen +Yusuke Suzuki +Dirac Research +Zbigniew Skowron +Dominik Czarnota diff --git a/thirdparty/google-benchmark/CMakeLists.txt b/thirdparty/google-benchmark/CMakeLists.txt new file mode 100644 index 00000000..71fa5549 --- /dev/null +++ b/thirdparty/google-benchmark/CMakeLists.txt @@ -0,0 +1,108 @@ +cmake_minimum_required (VERSION 3.0) +project (benchmark) + +option(BENCHMARK_ENABLE_TESTING "Enable testing of the benchmark library." ON) +option(BENCHMARK_ENABLE_LTO "Enable link time optimisation of the benchmark library." OFF) +# Make sure we can import out CMake functions +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + +## Read the git tags to determine the project version +#include(GetGitVersion) +#get_git_version(GIT_VERSION) + +## Tell the user what versions we are using +#string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" VERSION ${GIT_VERSION}) +#message("-- Version: ${VERSION}") + +# The version of the libraries +#set(GENERIC_LIB_VERSION ${VERSION}) +#string(SUBSTRING ${VERSION} 0 1 GENERIC_LIB_SOVERSION) + +# Import our CMake modules +include(CheckCXXCompilerFlag) +include(AddCXXCompilerFlag) +include(CXXFeatureCheck) + +# Try and enable C++11. Don't use C++14 because it doesn't work in some +# configurations. +add_cxx_compiler_flag(-std=c++11) +if (NOT HAVE_CXX_FLAG_STD_CXX11) + add_cxx_compiler_flag(-std=c++0x) +endif() + +# Turn compiler warnings up to 11 +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + add_cxx_compiler_flag(-W4) + add_definitions(-D_CRT_SECURE_NO_WARNINGS) +else() + add_cxx_compiler_flag(-Wall) +endif() +add_cxx_compiler_flag(-Wextra) +add_cxx_compiler_flag(-Wshadow) +add_cxx_compiler_flag(-Werror RELEASE) +add_cxx_compiler_flag(-pedantic) +add_cxx_compiler_flag(-pedantic-errors) +add_cxx_compiler_flag(-Wshorten-64-to-32) +add_cxx_compiler_flag(-Wfloat-equal) +add_cxx_compiler_flag(-Wzero-as-null-pointer-constant) +add_cxx_compiler_flag(-fstrict-aliasing) +if (HAVE_CXX_FLAG_FSTRICT_ALIASING) + add_cxx_compiler_flag(-Wstrict-aliasing) +endif() +add_cxx_compiler_flag(-Wthread-safety) +if (HAVE_WTHREAD_SAFETY) + add_definitions(-DHAVE_WTHREAD_SAFETY) + cxx_feature_check(THREAD_SAFETY_ATTRIBUTES) +endif() + +# Link time optimisation +if (BENCHMARK_ENABLE_LTO) + add_cxx_compiler_flag(-flto) + if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") + find_program(GCC_AR gcc-ar) + if (GCC_AR) + set(CMAKE_AR ${GCC_AR}) + endif() + find_program(GCC_RANLIB gcc-ranlib) + if (GCC_RANLIB) + set(CMAKE_RANLIB ${GCC_RANLIB}) + endif() + endif() +endif() + +# Coverage build type +set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING + "Flags used by the C++ compiler during coverage builds." + FORCE) +set(CMAKE_EXE_LINKER_FLAGS_COVERAGE + "${CMAKE_EXE_LINKER_FLAGS_DEBUG}" CACHE STRING + "Flags used for linking binaries during coverage builds." + FORCE) +set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE + "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}" CACHE STRING + "Flags used by the shared libraries linker during coverage builds." + FORCE) +mark_as_advanced( + CMAKE_CXX_FLAGS_COVERAGE + CMAKE_EXE_LINKER_FLAGS_COVERAGE + CMAKE_SHARED_LINKER_FLAGS_COVERAGE) +set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING + "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Coverage." + FORCE) +add_cxx_compiler_flag(--coverage COVERAGE) + +# C++ feature checks +cxx_feature_check(STD_REGEX) +cxx_feature_check(GNU_POSIX_REGEX) +cxx_feature_check(POSIX_REGEX) +cxx_feature_check(STEADY_CLOCK) + +# Ensure we have pthreads +find_package(Threads REQUIRED) + +# Set up directories +include_directories(${PROJECT_SOURCE_DIR}/include) + +# Build the targets +add_subdirectory(src) + diff --git a/thirdparty/google-benchmark/CONTRIBUTING.md b/thirdparty/google-benchmark/CONTRIBUTING.md new file mode 100644 index 00000000..43de4c9d --- /dev/null +++ b/thirdparty/google-benchmark/CONTRIBUTING.md @@ -0,0 +1,58 @@ +# How to contribute # + +We'd love to accept your patches and contributions to this project. There are +a just a few small guidelines you need to follow. + + +## Contributor License Agreement ## + +Contributions to any Google project must be accompanied by a Contributor +License Agreement. This is not a copyright **assignment**, it simply gives +Google permission to use and redistribute your contributions as part of the +project. + + * If you are an individual writing original source code and you're sure you + own the intellectual property, then you'll need to sign an [individual + CLA][]. + + * If you work for a company that wants to allow you to contribute your work, + then you'll need to sign a [corporate CLA][]. + +You generally only need to submit a CLA once, so if you've already submitted +one (even if it was for a different project), you probably don't need to do it +again. + +[individual CLA]: https://developers.google.com/open-source/cla/individual +[corporate CLA]: https://developers.google.com/open-source/cla/corporate + +Once your CLA is submitted (or if you already submitted one for +another Google project), make a commit adding yourself to the +[AUTHORS][] and [CONTRIBUTORS][] files. This commit can be part +of your first [pull request][]. + +[AUTHORS]: AUTHORS +[CONTRIBUTORS]: CONTRIBUTORS + + +## Submitting a patch ## + + 1. It's generally best to start by opening a new issue describing the bug or + feature you're intending to fix. Even if you think it's relatively minor, + it's helpful to know what people are working on. Mention in the initial + issue that you are planning to work on that bug or feature so that it can + be assigned to you. + + 1. Follow the normal process of [forking][] the project, and setup a new + branch to work in. It's important that each group of changes be done in + separate branches in order to ensure that a pull request only includes the + commits related to that bug or feature. + + 1. Do your best to have [well-formed commit messages][] for each change. + This provides consistency throughout the project, and ensures that commit + messages are able to be formatted properly by various git tools. + + 1. Finally, push the commits to your fork and submit a [pull request][]. + +[forking]: https://help.github.com/articles/fork-a-repo +[well-formed commit messages]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html +[pull request]: https://help.github.com/articles/creating-a-pull-request diff --git a/thirdparty/google-benchmark/CONTRIBUTORS b/thirdparty/google-benchmark/CONTRIBUTORS new file mode 100644 index 00000000..ed55bcf2 --- /dev/null +++ b/thirdparty/google-benchmark/CONTRIBUTORS @@ -0,0 +1,46 @@ +# People who have agreed to one of the CLAs and can contribute patches. +# The AUTHORS file lists the copyright holders; this file +# lists people. For example, Google employees are listed here +# but not in AUTHORS, because Google holds the copyright. +# +# Names should be added to this file only after verifying that +# the individual or the individual's organization has agreed to +# the appropriate Contributor License Agreement, found here: +# +# https://developers.google.com/open-source/cla/individual +# https://developers.google.com/open-source/cla/corporate +# +# The agreement for individuals can be filled out on the web. +# +# When adding J Random Contributor's name to this file, +# either J's name or J's organization's name should be +# added to the AUTHORS file, depending on whether the +# individual or corporate CLA was used. +# +# Names should be added to this file as: +# Name +# +# Please keep the list sorted. + +Arne Beer +Chris Kennelly +Christopher Seymour +David Coeurjolly +Dominic Hamon +Eugene Zhuk +Evgeny Safronov +Felix Homann +JianXiong Zhou +Kaito Udagawa +Lei Xu +Matt Clarkson +Oleksandr Sochka +Pascal Leroy +Paul Redmond +Pierre Phaneuf +Radoslav Yovchev +Shuo Chen +Yusuke Suzuki +Tobias Ulvgård +Zbigniew Skowron +Dominik Czarnota diff --git a/thirdparty/google-benchmark/LICENSE b/thirdparty/google-benchmark/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/thirdparty/google-benchmark/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/thirdparty/google-benchmark/README.md b/thirdparty/google-benchmark/README.md new file mode 100644 index 00000000..1fa7186e --- /dev/null +++ b/thirdparty/google-benchmark/README.md @@ -0,0 +1,295 @@ +benchmark +========= +[![Build Status](https://travis-ci.org/google/benchmark.svg?branch=master)](https://travis-ci.org/google/benchmark) +[![Build status](https://ci.appveyor.com/api/projects/status/u0qsyp7t1tk7cpxs/branch/master?svg=true)](https://ci.appveyor.com/project/google/benchmark/branch/master) +[![Coverage Status](https://coveralls.io/repos/google/benchmark/badge.svg)](https://coveralls.io/r/google/benchmark) + +A library to support the benchmarking of functions, similar to unit-tests. + +Discussion group: https://groups.google.com/d/forum/benchmark-discuss + +IRC channel: https://freenode.net #googlebenchmark + +Example usage +------------- +Define a function that executes the code to be measured a +specified number of times: + +```c++ +static void BM_StringCreation(benchmark::State& state) { + while (state.KeepRunning()) + std::string empty_string; +} +// Register the function as a benchmark +BENCHMARK(BM_StringCreation); + +// Define another benchmark +static void BM_StringCopy(benchmark::State& state) { + std::string x = "hello"; + while (state.KeepRunning()) + std::string copy(x); +} +BENCHMARK(BM_StringCopy); + +BENCHMARK_MAIN(); +``` + +Sometimes a family of microbenchmarks can be implemented with +just one routine that takes an extra argument to specify which +one of the family of benchmarks to run. For example, the following +code defines a family of microbenchmarks for measuring the speed +of `memcpy()` calls of different lengths: + +```c++ +static void BM_memcpy(benchmark::State& state) { + char* src = new char[state.range_x()]; char* dst = new char[state.range_x()]; + memset(src, 'x', state.range_x()); + while (state.KeepRunning()) + memcpy(dst, src, state.range_x()); + state.SetBytesProcessed(int64_t(state.iterations()) * + int64_t(state.range_x())); + delete[] src; + delete[] dst; +} +BENCHMARK(BM_memcpy)->Arg(8)->Arg(64)->Arg(512)->Arg(1<<10)->Arg(8<<10); +``` + +The preceding code is quite repetitive, and can be replaced with the +following short-hand. The following invocation will pick a few +appropriate arguments in the specified range and will generate a +microbenchmark for each such argument. + +```c++ +BENCHMARK(BM_memcpy)->Range(8, 8<<10); +``` + +You might have a microbenchmark that depends on two inputs. For +example, the following code defines a family of microbenchmarks for +measuring the speed of set insertion. + +```c++ +static void BM_SetInsert(benchmark::State& state) { + while (state.KeepRunning()) { + state.PauseTiming(); + std::set data = ConstructRandomSet(state.range_x()); + state.ResumeTiming(); + for (int j = 0; j < state.range_y(); ++j) + data.insert(RandomNumber()); + } +} +BENCHMARK(BM_SetInsert) + ->ArgPair(1<<10, 1) + ->ArgPair(1<<10, 8) + ->ArgPair(1<<10, 64) + ->ArgPair(1<<10, 512) + ->ArgPair(8<<10, 1) + ->ArgPair(8<<10, 8) + ->ArgPair(8<<10, 64) + ->ArgPair(8<<10, 512); +``` + +The preceding code is quite repetitive, and can be replaced with +the following short-hand. The following macro will pick a few +appropriate arguments in the product of the two specified ranges +and will generate a microbenchmark for each such pair. + +```c++ +BENCHMARK(BM_SetInsert)->RangePair(1<<10, 8<<10, 1, 512); +``` + +For more complex patterns of inputs, passing a custom function +to Apply allows programmatic specification of an +arbitrary set of arguments to run the microbenchmark on. +The following example enumerates a dense range on one parameter, +and a sparse range on the second. + +```c++ +static void CustomArguments(benchmark::internal::Benchmark* b) { + for (int i = 0; i <= 10; ++i) + for (int j = 32; j <= 1024*1024; j *= 8) + b->ArgPair(i, j); +} +BENCHMARK(BM_SetInsert)->Apply(CustomArguments); +``` + +Templated microbenchmarks work the same way: +Produce then consume 'size' messages 'iters' times +Measures throughput in the absence of multiprogramming. + +```c++ +template int BM_Sequential(benchmark::State& state) { + Q q; + typename Q::value_type v; + while (state.KeepRunning()) { + for (int i = state.range_x(); i--; ) + q.push(v); + for (int e = state.range_x(); e--; ) + q.Wait(&v); + } + // actually messages, not bytes: + state.SetBytesProcessed( + static_cast(state.iterations())*state.range_x()); +} +BENCHMARK_TEMPLATE(BM_Sequential, WaitQueue)->Range(1<<0, 1<<10); +``` + +Three macros are provided for adding benchmark templates. + +```c++ +#if __cplusplus >= 201103L // C++11 and greater. +#define BENCHMARK_TEMPLATE(func, ...) // Takes any number of parameters. +#else // C++ < C++11 +#define BENCHMARK_TEMPLATE(func, arg1) +#endif +#define BENCHMARK_TEMPLATE1(func, arg1) +#define BENCHMARK_TEMPLATE2(func, arg1, arg2) +``` + +In a multithreaded test (benchmark invoked by multiple threads simultaneously), +it is guaranteed that none of the threads will start until all have called +KeepRunning, and all will have finished before KeepRunning returns false. As +such, any global setup or teardown you want to do can be +wrapped in a check against the thread index: + +```c++ +static void BM_MultiThreaded(benchmark::State& state) { + if (state.thread_index == 0) { + // Setup code here. + } + while (state.KeepRunning()) { + // Run the test as normal. + } + if (state.thread_index == 0) { + // Teardown code here. + } +} +BENCHMARK(BM_MultiThreaded)->Threads(2); +``` + +If the benchmarked code itself uses threads and you want to compare it to +single-threaded code, you may want to use real-time ("wallclock") measurements +for latency comparisons: + +```c++ +BENCHMARK(BM_test)->Range(8, 8<<10)->UseRealTime(); +``` + +Without `UseRealTime`, CPU time is used by default. + +To prevent a value or expression from being optimized away by the compiler +the `benchmark::DoNotOptimize(...)` function can be used. + +```c++ +static void BM_test(benchmark::State& state) { + while (state.KeepRunning()) { + int x = 0; + for (int i=0; i < 64; ++i) { + benchmark::DoNotOptimize(x += i); + } + } +} +``` + +Benchmark Fixtures +------------------ +Fixture tests are created by +first defining a type that derives from ::benchmark::Fixture and then +creating/registering the tests using the following macros: + +* `BENCHMARK_F(ClassName, Method)` +* `BENCHMARK_DEFINE_F(ClassName, Method)` +* `BENCHMARK_REGISTER_F(ClassName, Method)` + +For Example: + +```c++ +class MyFixture : public benchmark::Fixture {}; + +BENCHMARK_F(MyFixture, FooTest)(benchmark::State& st) { + while (st.KeepRunning()) { + ... + } +} + +BENCHMARK_DEFINE_F(MyFixture, BarTest)(benchmark::State& st) { + while (st.KeepRunning()) { + ... + } +} +/* BarTest is NOT registered */ +BENCHMARK_REGISTER_F(MyFixture, BarTest)->Threads(2); +/* BarTest is now registered */ +``` + +Output Formats +-------------- +The library supports multiple output formats. Use the +`--benchmark_format=` flag to set the format type. `tabular` is +the default format. + +The Tabular format is intended to be a human readable format. By default +the format generates color output. Context is output on stderr and the +tabular data on stdout. Example tabular output looks like: +``` +Benchmark Time(ns) CPU(ns) Iterations +---------------------------------------------------------------------- +BM_SetInsert/1024/1 28928 29349 23853 133.097kB/s 33.2742k items/s +BM_SetInsert/1024/8 32065 32913 21375 949.487kB/s 237.372k items/s +BM_SetInsert/1024/10 33157 33648 21431 1.13369MB/s 290.225k items/s +``` + +The JSON format outputs human readable json split into two top level attributes. +The `context` attribute contains information about the run in general, including +information about the CPU and the date. +The `benchmarks` attribute contains a list of ever benchmark run. Example json +output looks like: +``` +{ + "context": { + "date": "2015/03/17-18:40:25", + "num_cpus": 40, + "mhz_per_cpu": 2801, + "cpu_scaling_enabled": false, + "build_type": "debug" + }, + "benchmarks": [ + { + "name": "BM_SetInsert/1024/1", + "iterations": 94877, + "real_time": 29275, + "cpu_time": 29836, + "bytes_per_second": 134066, + "items_per_second": 33516 + }, + { + "name": "BM_SetInsert/1024/8", + "iterations": 21609, + "real_time": 32317, + "cpu_time": 32429, + "bytes_per_second": 986770, + "items_per_second": 246693 + }, + { + "name": "BM_SetInsert/1024/10", + "iterations": 21393, + "real_time": 32724, + "cpu_time": 33355, + "bytes_per_second": 1199226, + "items_per_second": 299807 + } + ] +} +``` + +The CSV format outputs comma-separated values. The `context` is output on stderr +and the CSV itself on stdout. Example CSV output looks like: +``` +name,iterations,real_time,cpu_time,bytes_per_second,items_per_second,label +"BM_SetInsert/1024/1",65465,17890.7,8407.45,475768,118942, +"BM_SetInsert/1024/8",116606,18810.1,9766.64,3.27646e+06,819115, +"BM_SetInsert/1024/10",106365,17238.4,8421.53,4.74973e+06,1.18743e+06, +``` + +Linking against the library +--------------------------- +When using gcc, it is necessary to link against pthread to avoid runtime exceptions. This is due to how gcc implements std::thread. See [issue #67](https://github.com/google/benchmark/issues/67) for more details. diff --git a/thirdparty/google-benchmark/appveyor.yml b/thirdparty/google-benchmark/appveyor.yml new file mode 100644 index 00000000..5368a4ac --- /dev/null +++ b/thirdparty/google-benchmark/appveyor.yml @@ -0,0 +1,55 @@ +version: '{build}' + +configuration: + - Static Debug + - Static Release +# - Shared Debug +# - Shared Release + +platform: + - x86 + - x64 + +environment: + matrix: + - compiler: gcc-4.9.2-posix +# - compiler: gcc-4.8.4-posix +# - compiler: msvc-12-seh + +install: + # derive some extra information + - for /f "tokens=1-2" %%a in ("%configuration%") do (@set "linkage=%%a") + - for /f "tokens=1-2" %%a in ("%configuration%") do (@set "variant=%%b") + - if "%linkage%"=="Shared" (set shared=YES) else (set shared=NO) + - for /f "tokens=1-3 delims=-" %%a in ("%compiler%") do (@set "compiler_name=%%a") + - for /f "tokens=1-3 delims=-" %%a in ("%compiler%") do (@set "compiler_version=%%b") + - for /f "tokens=1-3 delims=-" %%a in ("%compiler%") do (@set "compiler_threading=%%c") + - if "%platform%"=="x64" (set arch=x86_64) + - if "%platform%"=="x86" (set arch=i686) + # download the specific version of MinGW + - if "%compiler_name%"=="gcc" (for /f %%a in ('python mingw.py --quiet --version "%compiler_version%" --arch "%arch%" --threading "%compiler_threading%" --location "C:\mingw-builds"') do @set "compiler_path=%%a") + +before_build: + # Set up mingw commands + - if "%compiler_name%"=="gcc" (set "generator=MinGW Makefiles") + - if "%compiler_name%"=="gcc" (set "build=mingw32-make -j4") + - if "%compiler_name%"=="gcc" (set "test=mingw32-make CTEST_OUTPUT_ON_FAILURE=1 test") + # msvc specific commands + # TODO :) + # add the compiler path if needed + - if not "%compiler_path%"=="" (set "PATH=%PATH%;%compiler_path%") + # git bash conflicts with MinGW makefiles + - if "%generator%"=="MinGW Makefiles" (set "PATH=%PATH:C:\Program Files (x86)\Git\bin=%") + +build_script: + - cmake -G "%generator%" "-DCMAKE_BUILD_TYPE=%variant%" "-DBUILD_SHARED_LIBS=%shared%" + - cmd /c "%build%" + +test_script: + - cmd /c "%test%" + +matrix: + fast_finish: true + +cache: + - C:\mingw-builds diff --git a/thirdparty/google-benchmark/cmake/AddCXXCompilerFlag.cmake b/thirdparty/google-benchmark/cmake/AddCXXCompilerFlag.cmake new file mode 100644 index 00000000..870f11ae --- /dev/null +++ b/thirdparty/google-benchmark/cmake/AddCXXCompilerFlag.cmake @@ -0,0 +1,37 @@ +# - Adds a compiler flag if it is supported by the compiler +# +# This function checks that the supplied compiler flag is supported and then +# adds it to the corresponding compiler flags +# +# add_cxx_compiler_flag( []) +# +# - Example +# +# include(AddCXXCompilerFlag) +# add_cxx_compiler_flag(-Wall) +# add_cxx_compiler_flag(-no-strict-aliasing RELEASE) +# Requires CMake 2.6+ + +if(__add_cxx_compiler_flag) + return() +endif() +set(__add_cxx_compiler_flag INCLUDED) + +include(CheckCXXCompilerFlag) + +function(add_cxx_compiler_flag FLAG) + string(TOUPPER "HAVE_CXX_FLAG_${FLAG}" SANITIZED_FLAG) + string(REPLACE "+" "X" SANITIZED_FLAG ${SANITIZED_FLAG}) + string(REGEX REPLACE "[^A-Za-z_0-9]" "_" SANITIZED_FLAG ${SANITIZED_FLAG}) + string(REGEX REPLACE "_+" "_" SANITIZED_FLAG ${SANITIZED_FLAG}) + set(CMAKE_REQUIRED_FLAGS "${FLAG}") + check_cxx_compiler_flag("" ${SANITIZED_FLAG}) + if(${SANITIZED_FLAG}) + set(VARIANT ${ARGV1}) + if(ARGV1) + string(TOUPPER "_${VARIANT}" VARIANT) + endif() + set(CMAKE_CXX_FLAGS${VARIANT} "${CMAKE_CXX_FLAGS${VARIANT}} ${FLAG}" PARENT_SCOPE) + endif() +endfunction() + diff --git a/thirdparty/google-benchmark/cmake/CXXFeatureCheck.cmake b/thirdparty/google-benchmark/cmake/CXXFeatureCheck.cmake new file mode 100644 index 00000000..23ee8ac6 --- /dev/null +++ b/thirdparty/google-benchmark/cmake/CXXFeatureCheck.cmake @@ -0,0 +1,39 @@ +# - Compile and run code to check for C++ features +# +# This functions compiles a source file under the `cmake` folder +# and adds the corresponding `HAVE_[FILENAME]` flag to the CMake +# environment +# +# cxx_feature_check( []) +# +# - Example +# +# include(CXXFeatureCheck) +# cxx_feature_check(STD_REGEX) +# Requires CMake 2.6+ + +if(__cxx_feature_check) + return() +endif() +set(__cxx_feature_check INCLUDED) + +function(cxx_feature_check FILE) + string(TOLOWER ${FILE} FILE) + string(TOUPPER ${FILE} VAR) + string(TOUPPER "HAVE_${VAR}" FEATURE) + message("-- Performing Test ${FEATURE}") + try_run(RUN_${FEATURE} COMPILE_${FEATURE} + ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/${FILE}.cpp) + if(RUN_${FEATURE} EQUAL 0) + message("-- Performing Test ${FEATURE} -- success") + set(HAVE_${VAR} 1 PARENT_SCOPE) + add_definitions(-DHAVE_${VAR}) + else() + if(NOT COMPILE_${FEATURE}) + message("-- Performing Test ${FEATURE} -- failed to compile") + else() + message("-- Performing Test ${FEATURE} -- compiled but failed to run") + endif() + endif() +endfunction() + diff --git a/thirdparty/google-benchmark/cmake/GetGitVersion.cmake b/thirdparty/google-benchmark/cmake/GetGitVersion.cmake new file mode 100644 index 00000000..8dd94800 --- /dev/null +++ b/thirdparty/google-benchmark/cmake/GetGitVersion.cmake @@ -0,0 +1,51 @@ +# - Returns a version string from Git tags +# +# This function inspects the annotated git tags for the project and returns a string +# into a CMake variable +# +# get_git_version() +# +# - Example +# +# include(GetGitVersion) +# get_git_version(GIT_VERSION) +# +# Requires CMake 2.8.11+ +find_package(Git) + +if(__get_git_version) + return() +endif() +set(__get_git_version INCLUDED) + +function(get_git_version var) + if(GIT_EXECUTABLE) + execute_process(COMMAND ${GIT_EXECUTABLE} describe --match "v[0-9]*.[0-9]*.[0-9]*" --abbrev=8 + RESULT_VARIABLE status + OUTPUT_VARIABLE GIT_VERSION + ERROR_QUIET) + if(${status}) + set(GIT_VERSION "v0.0.0") + else() + string(STRIP ${GIT_VERSION} GIT_VERSION) + string(REGEX REPLACE "-[0-9]+-g" "-" GIT_VERSION ${GIT_VERSION}) + endif() + + # Work out if the repository is dirty + execute_process(COMMAND ${GIT_EXECUTABLE} update-index -q --refresh + OUTPUT_QUIET + ERROR_QUIET) + execute_process(COMMAND ${GIT_EXECUTABLE} diff-index --name-only HEAD -- + OUTPUT_VARIABLE GIT_DIFF_INDEX + ERROR_QUIET) + string(COMPARE NOTEQUAL "${GIT_DIFF_INDEX}" "" GIT_DIRTY) + if (${GIT_DIRTY}) + set(GIT_VERSION "${GIT_VERSION}-dirty") + endif() + else() + set(GIT_VERSION "v0.0.0") + endif() + + message("-- git Version: ${GIT_VERSION}") + set(${var} ${GIT_VERSION} PARENT_SCOPE) +endfunction() diff --git a/thirdparty/google-benchmark/cmake/gnu_posix_regex.cpp b/thirdparty/google-benchmark/cmake/gnu_posix_regex.cpp new file mode 100644 index 00000000..b5b91cda --- /dev/null +++ b/thirdparty/google-benchmark/cmake/gnu_posix_regex.cpp @@ -0,0 +1,12 @@ +#include +#include +int main() { + std::string str = "test0159"; + regex_t re; + int ec = regcomp(&re, "^[a-z]+[0-9]+$", REG_EXTENDED | REG_NOSUB); + if (ec != 0) { + return ec; + } + return regexec(&re, str.c_str(), 0, nullptr, 0) ? -1 : 0; +} + diff --git a/thirdparty/google-benchmark/cmake/posix_regex.cpp b/thirdparty/google-benchmark/cmake/posix_regex.cpp new file mode 100644 index 00000000..a31af804 --- /dev/null +++ b/thirdparty/google-benchmark/cmake/posix_regex.cpp @@ -0,0 +1,12 @@ +#include +#include +int main() { + std::string str = "test0159"; + regex_t re; + int ec = regcomp(&re, "^[a-z]+[0-9]+$", REG_EXTENDED | REG_NOSUB); + if (ec != 0) { + return ec; + } + return regexec(&re, str.c_str(), 0, nullptr, 0) ? -1 : 0; +} + diff --git a/thirdparty/google-benchmark/cmake/std_regex.cpp b/thirdparty/google-benchmark/cmake/std_regex.cpp new file mode 100644 index 00000000..696f2a26 --- /dev/null +++ b/thirdparty/google-benchmark/cmake/std_regex.cpp @@ -0,0 +1,10 @@ +#include +#include +int main() { + const std::string str = "test0159"; + std::regex re; + re = std::regex("^[a-z]+[0-9]+$", + std::regex_constants::extended | std::regex_constants::nosubs); + return std::regex_search(str, re) ? 0 : -1; +} + diff --git a/thirdparty/google-benchmark/cmake/steady_clock.cpp b/thirdparty/google-benchmark/cmake/steady_clock.cpp new file mode 100644 index 00000000..66d50d17 --- /dev/null +++ b/thirdparty/google-benchmark/cmake/steady_clock.cpp @@ -0,0 +1,7 @@ +#include + +int main() { + typedef std::chrono::steady_clock Clock; + Clock::time_point tp = Clock::now(); + ((void)tp); +} diff --git a/thirdparty/google-benchmark/cmake/thread_safety_attributes.cpp b/thirdparty/google-benchmark/cmake/thread_safety_attributes.cpp new file mode 100644 index 00000000..46161bab --- /dev/null +++ b/thirdparty/google-benchmark/cmake/thread_safety_attributes.cpp @@ -0,0 +1,4 @@ +#define HAVE_THREAD_SAFETY_ATTRIBUTES +#include "../src/mutex.h" + +int main() {} diff --git a/thirdparty/google-benchmark/include/benchmark/benchmark.h b/thirdparty/google-benchmark/include/benchmark/benchmark.h new file mode 100644 index 00000000..18aa9e63 --- /dev/null +++ b/thirdparty/google-benchmark/include/benchmark/benchmark.h @@ -0,0 +1,21 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef BENCHMARK_BENCHMARK_H_ +#define BENCHMARK_BENCHMARK_H_ + +#include "macros.h" +#include "benchmark_api.h" +#include "reporter.h" + +#endif // BENCHMARK_BENCHMARK_H_ diff --git a/thirdparty/google-benchmark/include/benchmark/benchmark_api.h b/thirdparty/google-benchmark/include/benchmark/benchmark_api.h new file mode 100644 index 00000000..55235878 --- /dev/null +++ b/thirdparty/google-benchmark/include/benchmark/benchmark_api.h @@ -0,0 +1,602 @@ +// Support for registering benchmarks for functions. + +/* Example usage: +// Define a function that executes the code to be measured a +// specified number of times: +static void BM_StringCreation(benchmark::State& state) { + while (state.KeepRunning()) + std::string empty_string; +} + +// Register the function as a benchmark +BENCHMARK(BM_StringCreation); + +// Define another benchmark +static void BM_StringCopy(benchmark::State& state) { + std::string x = "hello"; + while (state.KeepRunning()) + std::string copy(x); +} +BENCHMARK(BM_StringCopy); + +// Augment the main() program to invoke benchmarks if specified +// via the --benchmarks command line flag. E.g., +// my_unittest --benchmark_filter=all +// my_unittest --benchmark_filter=BM_StringCreation +// my_unittest --benchmark_filter=String +// my_unittest --benchmark_filter='Copy|Creation' +int main(int argc, char** argv) { + benchmark::Initialize(&argc, argv); + benchmark::RunSpecifiedBenchmarks(); + return 0; +} + +// Sometimes a family of microbenchmarks can be implemented with +// just one routine that takes an extra argument to specify which +// one of the family of benchmarks to run. For example, the following +// code defines a family of microbenchmarks for measuring the speed +// of memcpy() calls of different lengths: + +static void BM_memcpy(benchmark::State& state) { + char* src = new char[state.range_x()]; char* dst = new char[state.range_x()]; + memset(src, 'x', state.range_x()); + while (state.KeepRunning()) + memcpy(dst, src, state.range_x()); + state.SetBytesProcessed(int64_t(state.iterations()) * + int64_t(state.range_x())); + delete[] src; delete[] dst; +} +BENCHMARK(BM_memcpy)->Arg(8)->Arg(64)->Arg(512)->Arg(1<<10)->Arg(8<<10); + +// The preceding code is quite repetitive, and can be replaced with the +// following short-hand. The following invocation will pick a few +// appropriate arguments in the specified range and will generate a +// microbenchmark for each such argument. +BENCHMARK(BM_memcpy)->Range(8, 8<<10); + +// You might have a microbenchmark that depends on two inputs. For +// example, the following code defines a family of microbenchmarks for +// measuring the speed of set insertion. +static void BM_SetInsert(benchmark::State& state) { + while (state.KeepRunning()) { + state.PauseTiming(); + set data = ConstructRandomSet(state.range_x()); + state.ResumeTiming(); + for (int j = 0; j < state.range_y(); ++j) + data.insert(RandomNumber()); + } +} +BENCHMARK(BM_SetInsert) + ->ArgPair(1<<10, 1) + ->ArgPair(1<<10, 8) + ->ArgPair(1<<10, 64) + ->ArgPair(1<<10, 512) + ->ArgPair(8<<10, 1) + ->ArgPair(8<<10, 8) + ->ArgPair(8<<10, 64) + ->ArgPair(8<<10, 512); + +// The preceding code is quite repetitive, and can be replaced with +// the following short-hand. The following macro will pick a few +// appropriate arguments in the product of the two specified ranges +// and will generate a microbenchmark for each such pair. +BENCHMARK(BM_SetInsert)->RangePair(1<<10, 8<<10, 1, 512); + +// For more complex patterns of inputs, passing a custom function +// to Apply allows programmatic specification of an +// arbitrary set of arguments to run the microbenchmark on. +// The following example enumerates a dense range on +// one parameter, and a sparse range on the second. +static void CustomArguments(benchmark::internal::Benchmark* b) { + for (int i = 0; i <= 10; ++i) + for (int j = 32; j <= 1024*1024; j *= 8) + b->ArgPair(i, j); +} +BENCHMARK(BM_SetInsert)->Apply(CustomArguments); + +// Templated microbenchmarks work the same way: +// Produce then consume 'size' messages 'iters' times +// Measures throughput in the absence of multiprogramming. +template int BM_Sequential(benchmark::State& state) { + Q q; + typename Q::value_type v; + while (state.KeepRunning()) { + for (int i = state.range_x(); i--; ) + q.push(v); + for (int e = state.range_x(); e--; ) + q.Wait(&v); + } + // actually messages, not bytes: + state.SetBytesProcessed( + static_cast(state.iterations())*state.range_x()); +} +BENCHMARK_TEMPLATE(BM_Sequential, WaitQueue)->Range(1<<0, 1<<10); + +Use `Benchmark::MinTime(double t)` to set the minimum time used to run the +benchmark. This option overrides the `benchmark_min_time` flag. + +void BM_test(benchmark::State& state) { + ... body ... +} +BENCHMARK(BM_test)->MinTime(2.0); // Run for at least 2 seconds. + +In a multithreaded test, it is guaranteed that none of the threads will start +until all have called KeepRunning, and all will have finished before KeepRunning +returns false. As such, any global setup or teardown you want to do can be +wrapped in a check against the thread index: + +static void BM_MultiThreaded(benchmark::State& state) { + if (state.thread_index == 0) { + // Setup code here. + } + while (state.KeepRunning()) { + // Run the test as normal. + } + if (state.thread_index == 0) { + // Teardown code here. + } +} +BENCHMARK(BM_MultiThreaded)->Threads(4); +*/ + +#ifndef BENCHMARK_BENCHMARK_API_H_ +#define BENCHMARK_BENCHMARK_API_H_ + +#include +#include +#include + +#include "macros.h" + +namespace benchmark { +class BenchmarkReporter; + +void Initialize(int* argc, char** argv); + +// Otherwise, run all benchmarks specified by the --benchmark_filter flag, +// and exit after running the benchmarks. +void RunSpecifiedBenchmarks(); +void RunSpecifiedBenchmarks(BenchmarkReporter* reporter); + +// If this routine is called, peak memory allocation past this point in the +// benchmark is reported at the end of the benchmark report line. (It is +// computed by running the benchmark once with a single iteration and a memory +// tracer.) +// TODO(dominic) +// void MemoryUsage(); + +namespace internal { +class Benchmark; +class BenchmarkImp; +class BenchmarkFamilies; + +template struct Voider { + typedef void type; +}; + +template +struct EnableIfString {}; + +template +struct EnableIfString::type> { + typedef int type; +}; + +void UseCharPointer(char const volatile*); + +// Take ownership of the pointer and register the benchmark. Return the +// registered benchmark. +Benchmark* RegisterBenchmarkInternal(Benchmark*); + +} // end namespace internal + + +// The DoNotOptimize(...) function can be used to prevent a value or +// expression from being optimized away by the compiler. This function is +// intented to add little to no overhead. +// See: http://stackoverflow.com/questions/28287064 +#if defined(__clang__) && defined(__GNUC__) +// TODO(ericwf): Clang has a bug where it tries to always use a register +// even if value must be stored in memory. This causes codegen to fail. +// To work around this we remove the "r" modifier so the operand is always +// loaded into memory. +template +inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) { + asm volatile("" : "+m" (const_cast(value))); +} +#elif defined(__GNUC__) +template +inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) { + asm volatile("" : "+rm" (const_cast(value))); +} +#else +template +inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) { + internal::UseCharPointer(&reinterpret_cast(value)); +} +#endif + + +// State is passed to a running Benchmark and contains state for the +// benchmark to use. +class State { +public: + State(size_t max_iters, bool has_x, int x, bool has_y, int y, int thread_i); + + // Returns true iff the benchmark should continue through another iteration. + // NOTE: A benchmark may not return from the test until KeepRunning() has + // returned false. + bool KeepRunning() { + if (BENCHMARK_BUILTIN_EXPECT(!started_, false)) { + ResumeTiming(); + started_ = true; + } + bool const res = total_iterations_++ < max_iterations; + if (BENCHMARK_BUILTIN_EXPECT(!res, false)) { + assert(started_); + PauseTiming(); + // Total iterations now is one greater than max iterations. Fix this. + total_iterations_ = max_iterations; + } + return res; + } + + // REQUIRES: timer is running + // Stop the benchmark timer. If not called, the timer will be + // automatically stopped after KeepRunning() returns false for the first time. + // + // For threaded benchmarks the PauseTiming() function acts + // like a barrier. I.e., the ith call by a particular thread to this + // function will block until all threads have made their ith call. + // The timer will stop when the last thread has called this function. + // + // NOTE: PauseTiming()/ResumeTiming() are relatively + // heavyweight, and so their use should generally be avoided + // within each benchmark iteration, if possible. + void PauseTiming(); + + // REQUIRES: timer is not running + // Start the benchmark timer. The timer is NOT running on entrance to the + // benchmark function. It begins running after the first call to KeepRunning() + // + // For threaded benchmarks the ResumeTiming() function acts + // like a barrier. I.e., the ith call by a particular thread to this + // function will block until all threads have made their ith call. + // The timer will start when the last thread has called this function. + // + // NOTE: PauseTiming()/ResumeTiming() are relatively + // heavyweight, and so their use should generally be avoided + // within each benchmark iteration, if possible. + void ResumeTiming(); + + // Set the number of bytes processed by the current benchmark + // execution. This routine is typically called once at the end of a + // throughput oriented benchmark. If this routine is called with a + // value > 0, the report is printed in MB/sec instead of nanoseconds + // per iteration. + // + // REQUIRES: a benchmark has exited its KeepRunning loop. + BENCHMARK_ALWAYS_INLINE + void SetBytesProcessed(size_t bytes) { + bytes_processed_ = bytes; + } + + BENCHMARK_ALWAYS_INLINE + size_t bytes_processed() const { + return bytes_processed_; + } + + // If this routine is called with items > 0, then an items/s + // label is printed on the benchmark report line for the currently + // executing benchmark. It is typically called at the end of a processing + // benchmark where a processing items/second output is desired. + // + // REQUIRES: a benchmark has exited its KeepRunning loop. + BENCHMARK_ALWAYS_INLINE + void SetItemsProcessed(size_t items) { + items_processed_ = items; + } + + BENCHMARK_ALWAYS_INLINE + size_t items_processed() const { + return items_processed_; + } + + // If this routine is called, the specified label is printed at the + // end of the benchmark report line for the currently executing + // benchmark. Example: + // static void BM_Compress(int iters) { + // ... + // double compress = input_size / output_size; + // benchmark::SetLabel(StringPrintf("compress:%.1f%%", 100.0*compression)); + // } + // Produces output that looks like: + // BM_Compress 50 50 14115038 compress:27.3% + // + // REQUIRES: a benchmark has exited its KeepRunning loop. + void SetLabel(const char* label); + + // Allow the use of std::string without actually including . + // This function does not participate in overload resolution unless StringType + // has the nested typename `basic_string`. This typename should be provided + // as an injected class name in the case of std::string. + template + void SetLabel(StringType const & str, + typename internal::EnableIfString::type = 1) { + this->SetLabel(str.c_str()); + } + + // Range arguments for this run. CHECKs if the argument has been set. + BENCHMARK_ALWAYS_INLINE + int range_x() const { + assert(has_range_x_); + ((void)has_range_x_); // Prevent unused warning. + return range_x_; + } + + BENCHMARK_ALWAYS_INLINE + int range_y() const { + assert(has_range_y_); + ((void)has_range_y_); // Prevent unused warning. + return range_y_; + } + + BENCHMARK_ALWAYS_INLINE + size_t iterations() const { return total_iterations_; } + +private: + bool started_; + size_t total_iterations_; + + bool has_range_x_; + int range_x_; + + bool has_range_y_; + int range_y_; + + size_t bytes_processed_; + size_t items_processed_; + +public: + const int thread_index; + const size_t max_iterations; + +private: + BENCHMARK_DISALLOW_COPY_AND_ASSIGN(State); +}; + +namespace internal { + +typedef void(Function)(State&); + +// ------------------------------------------------------ +// Benchmark registration object. The BENCHMARK() macro expands +// into an internal::Benchmark* object. Various methods can +// be called on this object to change the properties of the benchmark. +// Each method returns "this" so that multiple method calls can +// chained into one expression. +class Benchmark { +public: + virtual ~Benchmark(); + + // Note: the following methods all return "this" so that multiple + // method calls can be chained together in one expression. + + // Run this benchmark once with "x" as the extra argument passed + // to the function. + // REQUIRES: The function passed to the constructor must accept an arg1. + Benchmark* Arg(int x); + + // Run this benchmark once for a number of values picked from the + // range [start..limit]. (start and limit are always picked.) + // REQUIRES: The function passed to the constructor must accept an arg1. + Benchmark* Range(int start, int limit); + + // Run this benchmark once for every value in the range [start..limit] + // REQUIRES: The function passed to the constructor must accept an arg1. + Benchmark* DenseRange(int start, int limit); + + // Run this benchmark once with "x,y" as the extra arguments passed + // to the function. + // REQUIRES: The function passed to the constructor must accept arg1,arg2. + Benchmark* ArgPair(int x, int y); + + // Pick a set of values A from the range [lo1..hi1] and a set + // of values B from the range [lo2..hi2]. Run the benchmark for + // every pair of values in the cartesian product of A and B + // (i.e., for all combinations of the values in A and B). + // REQUIRES: The function passed to the constructor must accept arg1,arg2. + Benchmark* RangePair(int lo1, int hi1, int lo2, int hi2); + + // Pass this benchmark object to *func, which can customize + // the benchmark by calling various methods like Arg, ArgPair, + // Threads, etc. + Benchmark* Apply(void (*func)(Benchmark* benchmark)); + + // Set the minimum amount of time to use when running this benchmark. This + // option overrides the `benchmark_min_time` flag. + Benchmark* MinTime(double t); + + // If a particular benchmark is I/O bound, runs multiple threads internally or + // if for some reason CPU timings are not representative, call this method. If + // called, the elapsed time will be used to control how many iterations are + // run, and in the printing of items/second or MB/seconds values. If not + // called, the cpu time used by the benchmark will be used. + Benchmark* UseRealTime(); + + // Support for running multiple copies of the same benchmark concurrently + // in multiple threads. This may be useful when measuring the scaling + // of some piece of code. + + // Run one instance of this benchmark concurrently in t threads. + Benchmark* Threads(int t); + + // Pick a set of values T from [min_threads,max_threads]. + // min_threads and max_threads are always included in T. Run this + // benchmark once for each value in T. The benchmark run for a + // particular value t consists of t threads running the benchmark + // function concurrently. For example, consider: + // BENCHMARK(Foo)->ThreadRange(1,16); + // This will run the following benchmarks: + // Foo in 1 thread + // Foo in 2 threads + // Foo in 4 threads + // Foo in 8 threads + // Foo in 16 threads + Benchmark* ThreadRange(int min_threads, int max_threads); + + // Equivalent to ThreadRange(NumCPUs(), NumCPUs()) + Benchmark* ThreadPerCpu(); + + virtual void Run(State& state) = 0; + + // Used inside the benchmark implementation + struct Instance; + +protected: + explicit Benchmark(const char* name); + Benchmark(Benchmark const&); + void SetName(const char* name); + +private: + friend class BenchmarkFamilies; + BenchmarkImp* imp_; + + Benchmark& operator=(Benchmark const&); +}; + +// The class used to hold all Benchmarks created from static function. +// (ie those created using the BENCHMARK(...) macros. +class FunctionBenchmark : public Benchmark { +public: + FunctionBenchmark(const char* name, Function* func) + : Benchmark(name), func_(func) + {} + + virtual void Run(State& st); +private: + Function* func_; +}; + +} // end namespace internal + +// The base class for all fixture tests. +class Fixture: public internal::Benchmark { +public: + Fixture() : internal::Benchmark("") {} + + virtual void Run(State& st) { + this->SetUp(); + this->BenchmarkCase(st); + this->TearDown(); + } + + virtual void SetUp() {} + virtual void TearDown() {} + +protected: + virtual void BenchmarkCase(State&) = 0; +}; + +} // end namespace benchmark + + +// ------------------------------------------------------ +// Macro to register benchmarks + +// Check that __COUNTER__ is defined and that __COUNTER__ increases by 1 +// every time it is expanded. X + 1 == X + 0 is used in case X is defined to be +// empty. If X is empty the expression becomes (+1 == +0). +#if defined(__COUNTER__) && (__COUNTER__ + 1 == __COUNTER__ + 0) +#define BENCHMARK_PRIVATE_UNIQUE_ID __COUNTER__ +#else +#define BENCHMARK_PRIVATE_UNIQUE_ID __LINE__ +#endif + +// Helpers for generating unique variable names +#define BENCHMARK_PRIVATE_NAME(n) \ + BENCHMARK_PRIVATE_CONCAT(_benchmark_, BENCHMARK_PRIVATE_UNIQUE_ID, n) +#define BENCHMARK_PRIVATE_CONCAT(a, b, c) BENCHMARK_PRIVATE_CONCAT2(a, b, c) +#define BENCHMARK_PRIVATE_CONCAT2(a, b, c) a##b##c + +#define BENCHMARK_PRIVATE_DECLARE(n) \ + static ::benchmark::internal::Benchmark* \ + BENCHMARK_PRIVATE_NAME(n) BENCHMARK_UNUSED + +#define BENCHMARK(n) \ + BENCHMARK_PRIVATE_DECLARE(n) = \ + (::benchmark::internal::RegisterBenchmarkInternal( \ + new ::benchmark::internal::FunctionBenchmark(#n, n))) + +// Old-style macros +#define BENCHMARK_WITH_ARG(n, a) BENCHMARK(n)->Arg((a)) +#define BENCHMARK_WITH_ARG2(n, a1, a2) BENCHMARK(n)->ArgPair((a1), (a2)) +#define BENCHMARK_RANGE(n, lo, hi) BENCHMARK(n)->Range((lo), (hi)) +#define BENCHMARK_RANGE2(n, l1, h1, l2, h2) \ + BENCHMARK(n)->RangePair((l1), (h1), (l2), (h2)) + +// This will register a benchmark for a templatized function. For example: +// +// template +// void BM_Foo(int iters); +// +// BENCHMARK_TEMPLATE(BM_Foo, 1); +// +// will register BM_Foo<1> as a benchmark. +#define BENCHMARK_TEMPLATE1(n, a) \ + BENCHMARK_PRIVATE_DECLARE(n) = \ + (::benchmark::internal::RegisterBenchmarkInternal( \ + new ::benchmark::internal::FunctionBenchmark(#n "<" #a ">", n))) + +#define BENCHMARK_TEMPLATE2(n, a, b) \ + BENCHMARK_PRIVATE_DECLARE(n) = \ + (::benchmark::internal::RegisterBenchmarkInternal( \ + new ::benchmark::internal::FunctionBenchmark( \ + #n "<" #a "," #b ">", n))) + +#if __cplusplus >= 201103L +#define BENCHMARK_TEMPLATE(n, ...) \ + BENCHMARK_PRIVATE_DECLARE(n) = \ + (::benchmark::internal::RegisterBenchmarkInternal( \ + new ::benchmark::internal::FunctionBenchmark( \ + #n "<" #__VA_ARGS__ ">", n<__VA_ARGS__>))) +#else +#define BENCHMARK_TEMPLATE(n, a) BENCHMARK_TEMPLATE1(n, a) +#endif + + +#define BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \ +class BaseClass##_##Method##_Benchmark : public BaseClass { \ +public: \ + BaseClass##_##Method##_Benchmark() : BaseClass() { \ + this->SetName(#BaseClass "/" #Method);} \ +protected: \ + virtual void BenchmarkCase(::benchmark::State&); \ +}; + +#define BENCHMARK_DEFINE_F(BaseClass, Method) \ + BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \ + void BaseClass##_##Method##_Benchmark::BenchmarkCase + +#define BENCHMARK_REGISTER_F(BaseClass, Method) \ + BENCHMARK_PRIVATE_REGISTER_F(BaseClass##_##Method##_Benchmark) + +#define BENCHMARK_PRIVATE_REGISTER_F(TestName) \ + BENCHMARK_PRIVATE_DECLARE(TestName) = \ + (::benchmark::internal::RegisterBenchmarkInternal(new TestName())) + +// This macro will define and register a benchmark within a fixture class. +#define BENCHMARK_F(BaseClass, Method) \ + BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \ + BENCHMARK_REGISTER_F(BaseClass, Method); \ + void BaseClass##_##Method##_Benchmark::BenchmarkCase + + +// Helper macro to create a main routine in a test that runs the benchmarks +#define BENCHMARK_MAIN() \ + int main(int argc, char** argv) { \ + ::benchmark::Initialize(&argc, argv); \ + ::benchmark::RunSpecifiedBenchmarks(); \ + } + +#endif // BENCHMARK_BENCHMARK_API_H_ diff --git a/thirdparty/google-benchmark/include/benchmark/macros.h b/thirdparty/google-benchmark/include/benchmark/macros.h new file mode 100644 index 00000000..3e9540ed --- /dev/null +++ b/thirdparty/google-benchmark/include/benchmark/macros.h @@ -0,0 +1,48 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef BENCHMARK_MACROS_H_ +#define BENCHMARK_MACROS_H_ + +#if __cplusplus < 201103L +# define BENCHMARK_DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&); \ + TypeName& operator=(const TypeName&) +#else +# define BENCHMARK_DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&) = delete; \ + TypeName& operator=(const TypeName&) = delete +#endif + +#if defined(__GNUC__) +# define BENCHMARK_UNUSED __attribute__((unused)) +# define BENCHMARK_ALWAYS_INLINE __attribute__((always_inline)) +# define BENCHMARK_NOEXCEPT noexcept +#elif defined(_MSC_VER) && !defined(__clang__) +# define BENCHMARK_UNUSED +# define BENCHMARK_ALWAYS_INLINE __forceinline +# define BENCHMARK_NOEXCEPT +# define __func__ __FUNCTION__ +#else +# define BENCHMARK_UNUSED +# define BENCHMARK_ALWAYS_INLINE +# define BENCHMARK_NOEXCEPT +#endif + +#if defined(__GNUC__) +# define BENCHMARK_BUILTIN_EXPECT(x, y) __builtin_expect(x, y) +#else +# define BENCHMARK_BUILTIN_EXPECT(x, y) x +#endif + +#endif // BENCHMARK_MACROS_H_ diff --git a/thirdparty/google-benchmark/include/benchmark/reporter.h b/thirdparty/google-benchmark/include/benchmark/reporter.h new file mode 100644 index 00000000..d23ab657 --- /dev/null +++ b/thirdparty/google-benchmark/include/benchmark/reporter.h @@ -0,0 +1,122 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef BENCHMARK_REPORTER_H_ +#define BENCHMARK_REPORTER_H_ + +#include +#include +#include + +#include "benchmark_api.h" // For forward declaration of BenchmarkReporter + +namespace benchmark { + +// Interface for custom benchmark result printers. +// By default, benchmark reports are printed to stdout. However an application +// can control the destination of the reports by calling +// RunSpecifiedBenchmarks and passing it a custom reporter object. +// The reporter object must implement the following interface. +class BenchmarkReporter { + public: + struct Context { + int num_cpus; + double mhz_per_cpu; + bool cpu_scaling_enabled; + + // The number of chars in the longest benchmark name. + size_t name_field_width; + }; + + struct Run { + Run() : + iterations(1), + real_accumulated_time(0), + cpu_accumulated_time(0), + bytes_per_second(0), + items_per_second(0), + max_heapbytes_used(0) {} + + std::string benchmark_name; + std::string report_label; // Empty if not set by benchmark. + int64_t iterations; + double real_accumulated_time; + double cpu_accumulated_time; + + // Zero if not set by benchmark. + double bytes_per_second; + double items_per_second; + + // This is set to 0.0 if memory tracing is not enabled. + double max_heapbytes_used; + }; + + // Called once for every suite of benchmarks run. + // The parameter "context" contains information that the + // reporter may wish to use when generating its report, for example the + // platform under which the benchmarks are running. The benchmark run is + // never started if this function returns false, allowing the reporter + // to skip runs based on the context information. + virtual bool ReportContext(const Context& context) = 0; + + // Called once for each group of benchmark runs, gives information about + // cpu-time and heap memory usage during the benchmark run. + // Note that all the grouped benchmark runs should refer to the same + // benchmark, thus have the same name. + virtual void ReportRuns(const std::vector& report) = 0; + + // Called once and only once after ever group of benchmarks is run and + // reported. + virtual void Finalize(); + + virtual ~BenchmarkReporter(); +protected: + static void ComputeStats(std::vector const& reports, Run* mean, Run* stddev); +}; + +// Simple reporter that outputs benchmark data to the console. This is the +// default reporter used by RunSpecifiedBenchmarks(). +class ConsoleReporter : public BenchmarkReporter { + public: + virtual bool ReportContext(const Context& context); + virtual void ReportRuns(const std::vector& reports); +protected: + virtual void PrintRunData(const Run& report); + + size_t name_field_width_; +}; + +class JSONReporter : public BenchmarkReporter { +public: + JSONReporter() : first_report_(true) {} + virtual bool ReportContext(const Context& context); + virtual void ReportRuns(const std::vector& reports); + virtual void Finalize(); + +private: + void PrintRunData(const Run& report); + + bool first_report_; +}; + +class CSVReporter : public BenchmarkReporter { +public: + virtual bool ReportContext(const Context& context); + virtual void ReportRuns(const std::vector& reports); + +private: + void PrintRunData(const Run& report); +}; + +} // end namespace benchmark +#endif // BENCHMARK_REPORTER_H_ diff --git a/thirdparty/google-benchmark/mingw.py b/thirdparty/google-benchmark/mingw.py new file mode 100644 index 00000000..706ad559 --- /dev/null +++ b/thirdparty/google-benchmark/mingw.py @@ -0,0 +1,320 @@ +#! /usr/bin/env python +# encoding: utf-8 + +import argparse +import errno +import logging +import os +import platform +import re +import sys +import subprocess +import tempfile + +try: + import winreg +except ImportError: + import _winreg as winreg +try: + import urllib.request as request +except ImportError: + import urllib as request +try: + import urllib.parse as parse +except ImportError: + import urlparse as parse + +class EmptyLogger(object): + ''' + Provides an implementation that performs no logging + ''' + def debug(self, *k, **kw): + pass + def info(self, *k, **kw): + pass + def warn(self, *k, **kw): + pass + def error(self, *k, **kw): + pass + def critical(self, *k, **kw): + pass + def setLevel(self, *k, **kw): + pass + +urls = ( + 'http://downloads.sourceforge.net/project/mingw-w64/Toolchains%20' + 'targetting%20Win32/Personal%20Builds/mingw-builds/installer/' + 'repository.txt', + 'http://downloads.sourceforge.net/project/mingwbuilds/host-windows/' + 'repository.txt' +) +''' +A list of mingw-build repositories +''' + +def repository(urls = urls, log = EmptyLogger()): + ''' + Downloads and parse mingw-build repository files and parses them + ''' + log.info('getting mingw-builds repository') + versions = {} + re_sourceforge = re.compile(r'http://sourceforge.net/projects/([^/]+)/files') + re_sub = r'http://downloads.sourceforge.net/project/\1' + for url in urls: + log.debug(' - requesting: %s', url) + socket = request.urlopen(url) + repo = socket.read() + if not isinstance(repo, str): + repo = repo.decode(); + socket.close() + for entry in repo.split('\n')[:-1]: + value = entry.split('|') + version = tuple([int(n) for n in value[0].strip().split('.')]) + version = versions.setdefault(version, {}) + arch = value[1].strip() + if arch == 'x32': + arch = 'i686' + elif arch == 'x64': + arch = 'x86_64' + arch = version.setdefault(arch, {}) + threading = arch.setdefault(value[2].strip(), {}) + exceptions = threading.setdefault(value[3].strip(), {}) + revision = exceptions.setdefault(int(value[4].strip()[3:]), + re_sourceforge.sub(re_sub, value[5].strip())) + return versions + +def find_in_path(file, path=None): + ''' + Attempts to find an executable in the path + ''' + if platform.system() == 'Windows': + file += '.exe' + if path is None: + path = os.environ.get('PATH', '') + if type(path) is type(''): + path = path.split(os.pathsep) + return list(filter(os.path.exists, + map(lambda dir, file=file: os.path.join(dir, file), path))) + +def find_7zip(log = EmptyLogger()): + ''' + Attempts to find 7zip for unpacking the mingw-build archives + ''' + log.info('finding 7zip') + path = find_in_path('7z') + if not path: + key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r'SOFTWARE\7-Zip') + path, _ = winreg.QueryValueEx(key, 'Path') + path = [os.path.join(path, '7z.exe')] + log.debug('found \'%s\'', path[0]) + return path[0] + +find_7zip() + +def unpack(archive, location, log = EmptyLogger()): + ''' + Unpacks a mingw-builds archive + ''' + sevenzip = find_7zip(log) + log.info('unpacking %s', os.path.basename(archive)) + cmd = [sevenzip, 'x', archive, '-o' + location, '-y'] + log.debug(' - %r', cmd) + with open(os.devnull, 'w') as devnull: + subprocess.check_call(cmd, stdout = devnull) + +def download(url, location, log = EmptyLogger()): + ''' + Downloads and unpacks a mingw-builds archive + ''' + log.info('downloading MinGW') + log.debug(' - url: %s', url) + log.debug(' - location: %s', location) + + re_content = re.compile(r'attachment;[ \t]*filename=(")?([^"]*)(")?[\r\n]*') + + stream = request.urlopen(url) + try: + content = stream.getheader('Content-Disposition') or '' + except AttributeError: + content = stream.headers.getheader('Content-Disposition') or '' + matches = re_content.match(content) + if matches: + filename = matches.group(2) + else: + parsed = parse.urlparse(stream.geturl()) + filename = os.path.basename(parsed.path) + + try: + os.makedirs(location) + except OSError as e: + if e.errno == errno.EEXIST and os.path.isdir(location): + pass + else: + raise + + archive = os.path.join(location, filename) + with open(archive, 'wb') as out: + while True: + buf = stream.read(1024) + if not buf: + break + out.write(buf) + unpack(archive, location, log = log) + os.remove(archive) + + possible = os.path.join(location, 'mingw64') + if not os.path.exists(possible): + possible = os.path.join(location, 'mingw32') + if not os.path.exists(possible): + raise ValueError('Failed to find unpacked MinGW: ' + possible) + return possible + +def root(location = None, arch = None, version = None, threading = None, + exceptions = None, revision = None, log = EmptyLogger()): + ''' + Returns the root folder of a specific version of the mingw-builds variant + of gcc. Will download the compiler if needed + ''' + + # Get the repository if we don't have all the information + if not (arch and version and threading and exceptions and revision): + versions = repository(log = log) + + # Determine some defaults + version = version or max(versions.keys()) + if not arch: + arch = platform.machine().lower() + if arch == 'x86': + arch = 'i686' + elif arch == 'amd64': + arch = 'x86_64' + if not threading: + keys = versions[version][arch].keys() + if 'posix' in keys: + threading = 'posix' + elif 'win32' in keys: + threading = 'win32' + else: + threading = keys[0] + if not exceptions: + keys = versions[version][arch][threading].keys() + if 'seh' in keys: + exceptions = 'seh' + elif 'sjlj' in keys: + exceptions = 'sjlj' + else: + exceptions = keys[0] + if revision == None: + revision = max(versions[version][arch][threading][exceptions].keys()) + if not location: + location = os.path.join(tempfile.gettempdir(), 'mingw-builds') + + # Get the download url + url = versions[version][arch][threading][exceptions][revision] + + # Tell the user whatzzup + log.info('finding MinGW %s', '.'.join(str(v) for v in version)) + log.debug(' - arch: %s', arch) + log.debug(' - threading: %s', threading) + log.debug(' - exceptions: %s', exceptions) + log.debug(' - revision: %s', revision) + log.debug(' - url: %s', url) + + # Store each specific revision differently + slug = '{version}-{arch}-{threading}-{exceptions}-rev{revision}' + slug = slug.format( + version = '.'.join(str(v) for v in version), + arch = arch, + threading = threading, + exceptions = exceptions, + revision = revision + ) + if arch == 'x86_64': + root_dir = os.path.join(location, slug, 'mingw64') + elif arch == 'i686': + root_dir = os.path.join(location, slug, 'mingw32') + else: + raise ValueError('Unknown MinGW arch: ' + arch) + + # Download if needed + if not os.path.exists(root_dir): + downloaded = download(url, os.path.join(location, slug), log = log) + if downloaded != root_dir: + raise ValueError('The location of mingw did not match\n%s\n%s' + % (downloaded, root_dir)) + + return root_dir + +def str2ver(string): + ''' + Converts a version string into a tuple + ''' + try: + version = tuple(int(v) for v in string.split('.')) + if len(version) is not 3: + raise ValueError() + except ValueError: + raise argparse.ArgumentTypeError( + 'please provide a three digit version string') + return version + +def main(): + ''' + Invoked when the script is run directly by the python interpreter + ''' + parser = argparse.ArgumentParser( + description = 'Downloads a specific version of MinGW', + formatter_class = argparse.ArgumentDefaultsHelpFormatter + ) + parser.add_argument('--location', + help = 'the location to download the compiler to', + default = os.path.join(tempfile.gettempdir(), 'mingw-builds')) + parser.add_argument('--arch', required = True, choices = ['i686', 'x86_64'], + help = 'the target MinGW architecture string') + parser.add_argument('--version', type = str2ver, + help = 'the version of GCC to download') + parser.add_argument('--threading', choices = ['posix', 'win32'], + help = 'the threading type of the compiler') + parser.add_argument('--exceptions', choices = ['sjlj', 'seh', 'dwarf'], + help = 'the method to throw exceptions') + parser.add_argument('--revision', type=int, + help = 'the revision of the MinGW release') + group = parser.add_mutually_exclusive_group() + group.add_argument('-v', '--verbose', action='store_true', + help='increase the script output verbosity') + group.add_argument('-q', '--quiet', action='store_true', + help='only print errors and warning') + args = parser.parse_args() + + # Create the logger + logger = logging.getLogger('mingw') + handler = logging.StreamHandler() + formatter = logging.Formatter('%(message)s') + handler.setFormatter(formatter) + logger.addHandler(handler) + logger.setLevel(logging.INFO) + if args.quiet: + logger.setLevel(logging.WARN) + if args.verbose: + logger.setLevel(logging.DEBUG) + + # Get MinGW + root_dir = root(location = args.location, arch = args.arch, + version = args.version, threading = args.threading, + exceptions = args.exceptions, revision = args.revision, + log = logger) + + sys.stdout.write('%s\n' % os.path.join(root_dir, 'bin')) + +if __name__ == '__main__': + try: + main() + except IOError as e: + sys.stderr.write('IO error: %s\n' % e) + sys.exit(1) + except OSError as e: + sys.stderr.write('OS error: %s\n' % e) + sys.exit(1) + except KeyboardInterrupt as e: + sys.stderr.write('Killed\n') + sys.exit(1) diff --git a/thirdparty/google-benchmark/src/CMakeLists.txt b/thirdparty/google-benchmark/src/CMakeLists.txt new file mode 100644 index 00000000..811d0755 --- /dev/null +++ b/thirdparty/google-benchmark/src/CMakeLists.txt @@ -0,0 +1,51 @@ +# Allow the source files to find headers in src/ +include_directories(${PROJECT_SOURCE_DIR}/src) + +# Define the source files +set(SOURCE_FILES "benchmark.cc" "colorprint.cc" "commandlineflags.cc" + "console_reporter.cc" "csv_reporter.cc" "json_reporter.cc" + "log.cc" "reporter.cc" "sleep.cc" "string_util.cc" + "sysinfo.cc" "walltime.cc") +# Determine the correct regular expression engine to use +if(HAVE_STD_REGEX) + set(RE_FILES "re_std.cc") +elseif(HAVE_GNU_POSIX_REGEX) + set(RE_FILES "re_posix.cc") +elseif(HAVE_POSIX_REGEX) + set(RE_FILES "re_posix.cc") +else() + message(FATAL_ERROR "Failed to determine the source files for the regular expression backend") +endif() + +add_library(benchmark ${SOURCE_FILES} ${RE_FILES}) + + +set_target_properties(benchmark PROPERTIES + OUTPUT_NAME "benchmark" + VERSION ${GENERIC_LIB_VERSION} + SOVERSION ${GENERIC_LIB_SOVERSION} +) + +# Link threads. +target_link_libraries(benchmark ${CMAKE_THREAD_LIBS_INIT}) + +# We need extra libraries on Windows +if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") + target_link_libraries(benchmark Shlwapi) +endif() + +# Expose public API +target_include_directories(benchmark PUBLIC ${PROJECT_SOURCE_DIR}/include) + +# Install target (will install the library to specified CMAKE_INSTALL_PREFIX variable) +install( + TARGETS benchmark + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin + COMPONENT library) + +install( + DIRECTORY "${PROJECT_SOURCE_DIR}/include/benchmark" + DESTINATION include + FILES_MATCHING PATTERN "*.*h") diff --git a/thirdparty/google-benchmark/src/arraysize.h b/thirdparty/google-benchmark/src/arraysize.h new file mode 100644 index 00000000..638a52a0 --- /dev/null +++ b/thirdparty/google-benchmark/src/arraysize.h @@ -0,0 +1,34 @@ +#ifndef BENCHMARK_ARRAYSIZE_H_ +#define BENCHMARK_ARRAYSIZE_H_ + +#include "internal_macros.h" + +namespace benchmark { +namespace internal { +// The arraysize(arr) macro returns the # of elements in an array arr. +// The expression is a compile-time constant, and therefore can be +// used in defining new arrays, for example. If you use arraysize on +// a pointer by mistake, you will get a compile-time error. +// + + +// This template function declaration is used in defining arraysize. +// Note that the function doesn't need an implementation, as we only +// use its type. +template +char (&ArraySizeHelper(T (&array)[N]))[N]; + +// That gcc wants both of these prototypes seems mysterious. VC, for +// its part, can't decide which to use (another mystery). Matching of +// template overloads: the final frontier. +#ifndef COMPILER_MSVC +template +char (&ArraySizeHelper(const T (&array)[N]))[N]; +#endif + +#define arraysize(array) (sizeof(::benchmark::internal::ArraySizeHelper(array))) + +} // end namespace internal +} // end namespace benchmark + +#endif // BENCHMARK_ARRAYSIZE_H_ diff --git a/thirdparty/google-benchmark/src/benchmark.cc b/thirdparty/google-benchmark/src/benchmark.cc new file mode 100644 index 00000000..269b7978 --- /dev/null +++ b/thirdparty/google-benchmark/src/benchmark.cc @@ -0,0 +1,919 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "benchmark/benchmark.h" +#include "internal_macros.h" + +#ifndef BENCHMARK_OS_WINDOWS +#include +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "check.h" +#include "commandlineflags.h" +#include "log.h" +#include "mutex.h" +#include "re.h" +#include "stat.h" +#include "string_util.h" +#include "sysinfo.h" +#include "walltime.h" + +DEFINE_bool(benchmark_list_tests, false, + "Print a list of benchmarks. This option overrides all other " + "options."); + +DEFINE_string(benchmark_filter, ".", + "A regular expression that specifies the set of benchmarks " + "to execute. If this flag is empty, no benchmarks are run. " + "If this flag is the string \"all\", all benchmarks linked " + "into the process are run."); + +DEFINE_double(benchmark_min_time, 0.5, + "Minimum number of seconds we should run benchmark before " + "results are considered significant. For cpu-time based " + "tests, this is the lower bound on the total cpu time " + "used by all threads that make up the test. For real-time " + "based tests, this is the lower bound on the elapsed time " + "of the benchmark execution, regardless of number of " + "threads."); + +DEFINE_int32(benchmark_repetitions, 1, + "The number of runs of each benchmark. If greater than 1, the " + "mean and standard deviation of the runs will be reported."); + +DEFINE_string(benchmark_format, "tabular", + "The format to use for console output. Valid values are " + "'tabular', 'json', or 'csv'."); + +DEFINE_bool(color_print, true, "Enables colorized logging."); + +DEFINE_int32(v, 0, "The level of verbose logging to output"); + + +namespace benchmark { + +namespace internal { + +void UseCharPointer(char const volatile*) {} + +// NOTE: This is a dummy "mutex" type used to denote the actual mutex +// returned by GetBenchmarkLock(). This is only used to placate the thread +// safety warnings by giving the return of GetBenchmarkLock() a name. +struct CAPABILITY("mutex") BenchmarkLockType {}; +BenchmarkLockType BenchmarkLockVar; + +} // end namespace internal + +inline Mutex& RETURN_CAPABILITY(::benchmark::internal::BenchmarkLockVar) +GetBenchmarkLock() +{ + static Mutex lock; + return lock; +} + +namespace { + +bool IsZero(double n) { + return std::abs(n) < std::numeric_limits::epsilon(); +} + +// For non-dense Range, intermediate values are powers of kRangeMultiplier. +static const int kRangeMultiplier = 8; +static const size_t kMaxIterations = 1000000000; + +bool running_benchmark = false; + +// Global variable so that a benchmark can cause a little extra printing +std::string* GetReportLabel() { + static std::string label GUARDED_BY(GetBenchmarkLock()); + return &label; +} + +// TODO(ericwf): support MallocCounter. +//static benchmark::MallocCounter *benchmark_mc; + +struct ThreadStats { + ThreadStats() : bytes_processed(0), items_processed(0) {} + int64_t bytes_processed; + int64_t items_processed; +}; + +// Timer management class +class TimerManager { + public: + TimerManager(int num_threads, Notification* done) + : num_threads_(num_threads), + done_(done), + running_(false), + real_time_used_(0), + cpu_time_used_(0), + num_finalized_(0), + phase_number_(0), + entered_(0) { + } + + // Called by each thread + void StartTimer() EXCLUDES(lock_) { + bool last_thread = false; + { + MutexLock ml(lock_); + last_thread = Barrier(ml); + if (last_thread) { + CHECK(!running_) << "Called StartTimer when timer is already running"; + running_ = true; + start_real_time_ = walltime::Now(); + start_cpu_time_ = MyCPUUsage() + ChildrenCPUUsage(); + } + } + if (last_thread) { + phase_condition_.notify_all(); + } + } + + // Called by each thread + void StopTimer() EXCLUDES(lock_) { + bool last_thread = false; + { + MutexLock ml(lock_); + last_thread = Barrier(ml); + if (last_thread) { + CHECK(running_) << "Called StopTimer when timer is already stopped"; + InternalStop(); + } + } + if (last_thread) { + phase_condition_.notify_all(); + } + } + + // Called by each thread + void Finalize() EXCLUDES(lock_) { + MutexLock l(lock_); + num_finalized_++; + if (num_finalized_ == num_threads_) { + CHECK(!running_) << + "The timer should be stopped before the timer is finalized"; + done_->Notify(); + } + } + + // REQUIRES: timer is not running + double real_time_used() EXCLUDES(lock_) { + MutexLock l(lock_); + CHECK(!running_); + return real_time_used_; + } + + // REQUIRES: timer is not running + double cpu_time_used() EXCLUDES(lock_) { + MutexLock l(lock_); + CHECK(!running_); + return cpu_time_used_; + } + + private: + Mutex lock_; + Condition phase_condition_; + int num_threads_; + Notification* done_; + + bool running_; // Is the timer running + double start_real_time_; // If running_ + double start_cpu_time_; // If running_ + + // Accumulated time so far (does not contain current slice if running_) + double real_time_used_; + double cpu_time_used_; + + // How many threads have called Finalize() + int num_finalized_; + + // State for barrier management + int phase_number_; + int entered_; // Number of threads that have entered this barrier + + void InternalStop() REQUIRES(lock_) { + CHECK(running_); + running_ = false; + real_time_used_ += walltime::Now() - start_real_time_; + cpu_time_used_ += ((MyCPUUsage() + ChildrenCPUUsage()) + - start_cpu_time_); + } + + // Enter the barrier and wait until all other threads have also + // entered the barrier. Returns iff this is the last thread to + // enter the barrier. + bool Barrier(MutexLock& ml) REQUIRES(lock_) { + CHECK_LT(entered_, num_threads_); + entered_++; + if (entered_ < num_threads_) { + // Wait for all threads to enter + int phase_number_cp = phase_number_; + auto cb = [this, phase_number_cp]() { + return this->phase_number_ > phase_number_cp; + }; + phase_condition_.wait(ml.native_handle(), cb); + return false; // I was not the last one + } else { + // Last thread has reached the barrier + phase_number_++; + entered_ = 0; + return true; + } + } +}; + +// TimerManager for current run. +static std::unique_ptr timer_manager = nullptr; + +} // end namespace + +namespace internal { + +// Information kept per benchmark we may want to run +struct Benchmark::Instance { + std::string name; + Benchmark* benchmark; + bool has_arg1; + int arg1; + bool has_arg2; + int arg2; + bool use_real_time; + double min_time; + int threads; // Number of concurrent threads to use + bool multithreaded; // Is benchmark multi-threaded? +}; + +// Class for managing registered benchmarks. Note that each registered +// benchmark identifies a family of related benchmarks to run. +class BenchmarkFamilies { + public: + static BenchmarkFamilies* GetInstance(); + + // Registers a benchmark family and returns the index assigned to it. + size_t AddBenchmark(std::unique_ptr family); + + // Extract the list of benchmark instances that match the specified + // regular expression. + bool FindBenchmarks(const std::string& re, + std::vector* benchmarks); + private: + BenchmarkFamilies() {} + + std::vector> families_; + Mutex mutex_; +}; + + +class BenchmarkImp { +public: + explicit BenchmarkImp(const char* name); + ~BenchmarkImp(); + + void Arg(int x); + void Range(int start, int limit); + void DenseRange(int start, int limit); + void ArgPair(int start, int limit); + void RangePair(int lo1, int hi1, int lo2, int hi2); + void MinTime(double n); + void UseRealTime(); + void Threads(int t); + void ThreadRange(int min_threads, int max_threads); + void ThreadPerCpu(); + void SetName(const char* name); + + static void AddRange(std::vector* dst, int lo, int hi, int mult); + +private: + friend class BenchmarkFamilies; + + std::string name_; + int arg_count_; + std::vector< std::pair > args_; // Args for all benchmark runs + double min_time_; + bool use_real_time_; + std::vector thread_counts_; + + BenchmarkImp& operator=(BenchmarkImp const&); +}; + +BenchmarkFamilies* BenchmarkFamilies::GetInstance() { + static BenchmarkFamilies instance; + return &instance; +} + + +size_t BenchmarkFamilies::AddBenchmark(std::unique_ptr family) { + MutexLock l(mutex_); + size_t index = families_.size(); + families_.push_back(std::move(family)); + return index; +} + +bool BenchmarkFamilies::FindBenchmarks( + const std::string& spec, + std::vector* benchmarks) { + // Make regular expression out of command-line flag + std::string error_msg; + Regex re; + if (!re.Init(spec, &error_msg)) { + std::cerr << "Could not compile benchmark re: " << error_msg << std::endl; + return false; + } + + // Special list of thread counts to use when none are specified + std::vector one_thread; + one_thread.push_back(1); + + MutexLock l(mutex_); + for (std::unique_ptr& bench_family : families_) { + // Family was deleted or benchmark doesn't match + if (!bench_family) continue; + BenchmarkImp* family = bench_family->imp_; + + if (family->arg_count_ == -1) { + family->arg_count_ = 0; + family->args_.emplace_back(-1, -1); + } + for (auto const& args : family->args_) { + const std::vector* thread_counts = + (family->thread_counts_.empty() + ? &one_thread + : &family->thread_counts_); + for (int num_threads : *thread_counts) { + + Benchmark::Instance instance; + instance.name = family->name_; + instance.benchmark = bench_family.get(); + instance.has_arg1 = family->arg_count_ >= 1; + instance.arg1 = args.first; + instance.has_arg2 = family->arg_count_ == 2; + instance.arg2 = args.second; + instance.min_time = family->min_time_; + instance.use_real_time = family->use_real_time_; + instance.threads = num_threads; + instance.multithreaded = !(family->thread_counts_.empty()); + + // Add arguments to instance name + if (family->arg_count_ >= 1) { + AppendHumanReadable(instance.arg1, &instance.name); + } + if (family->arg_count_ >= 2) { + AppendHumanReadable(instance.arg2, &instance.name); + } + if (!IsZero(family->min_time_)) { + instance.name += StringPrintF("/min_time:%0.3f", family->min_time_); + } + if (family->use_real_time_) { + instance.name += "/real_time"; + } + + // Add the number of threads used to the name + if (!family->thread_counts_.empty()) { + instance.name += StringPrintF("/threads:%d", instance.threads); + } + + if (re.Match(instance.name)) { + benchmarks->push_back(instance); + } + } + } + } + return true; +} + +BenchmarkImp::BenchmarkImp(const char* name) + : name_(name), arg_count_(-1), + min_time_(0.0), use_real_time_(false) { +} + +BenchmarkImp::~BenchmarkImp() { +} + +void BenchmarkImp::Arg(int x) { + CHECK(arg_count_ == -1 || arg_count_ == 1); + arg_count_ = 1; + args_.emplace_back(x, -1); +} + +void BenchmarkImp::Range(int start, int limit) { + CHECK(arg_count_ == -1 || arg_count_ == 1); + arg_count_ = 1; + std::vector arglist; + AddRange(&arglist, start, limit, kRangeMultiplier); + + for (int i : arglist) { + args_.emplace_back(i, -1); + } +} + +void BenchmarkImp::DenseRange(int start, int limit) { + CHECK(arg_count_ == -1 || arg_count_ == 1); + arg_count_ = 1; + CHECK_GE(start, 0); + CHECK_LE(start, limit); + for (int arg = start; arg <= limit; arg++) { + args_.emplace_back(arg, -1); + } +} + +void BenchmarkImp::ArgPair(int x, int y) { + CHECK(arg_count_ == -1 || arg_count_ == 2); + arg_count_ = 2; + args_.emplace_back(x, y); +} + +void BenchmarkImp::RangePair(int lo1, int hi1, int lo2, int hi2) { + CHECK(arg_count_ == -1 || arg_count_ == 2); + arg_count_ = 2; + std::vector arglist1, arglist2; + AddRange(&arglist1, lo1, hi1, kRangeMultiplier); + AddRange(&arglist2, lo2, hi2, kRangeMultiplier); + + for (int i : arglist1) { + for (int j : arglist2) { + args_.emplace_back(i, j); + } + } +} + +void BenchmarkImp::MinTime(double t) { + CHECK(t > 0.0); + min_time_ = t; +} + +void BenchmarkImp::UseRealTime() { + use_real_time_ = true; +} + +void BenchmarkImp::Threads(int t) { + CHECK_GT(t, 0); + thread_counts_.push_back(t); +} + +void BenchmarkImp::ThreadRange(int min_threads, int max_threads) { + CHECK_GT(min_threads, 0); + CHECK_GE(max_threads, min_threads); + + AddRange(&thread_counts_, min_threads, max_threads, 2); +} + +void BenchmarkImp::ThreadPerCpu() { + static int num_cpus = NumCPUs(); + thread_counts_.push_back(num_cpus); +} + +void BenchmarkImp::SetName(const char* name) { + name_ = name; +} + +void BenchmarkImp::AddRange(std::vector* dst, int lo, int hi, int mult) { + CHECK_GE(lo, 0); + CHECK_GE(hi, lo); + + // Add "lo" + dst->push_back(lo); + + static const int kint32max = std::numeric_limits::max(); + + // Now space out the benchmarks in multiples of "mult" + for (int32_t i = 1; i < kint32max/mult; i *= mult) { + if (i >= hi) break; + if (i > lo) { + dst->push_back(i); + } + } + // Add "hi" (if different from "lo") + if (hi != lo) { + dst->push_back(hi); + } +} + +Benchmark::Benchmark(const char* name) + : imp_(new BenchmarkImp(name)) +{ +} + +Benchmark::~Benchmark() { + delete imp_; +} + +Benchmark::Benchmark(Benchmark const& other) + : imp_(new BenchmarkImp(*other.imp_)) +{ +} + +Benchmark* Benchmark::Arg(int x) { + imp_->Arg(x); + return this; +} + +Benchmark* Benchmark::Range(int start, int limit) { + imp_->Range(start, limit); + return this; +} + +Benchmark* Benchmark::DenseRange(int start, int limit) { + imp_->DenseRange(start, limit); + return this; +} + +Benchmark* Benchmark::ArgPair(int x, int y) { + imp_->ArgPair(x, y); + return this; +} + +Benchmark* Benchmark::RangePair(int lo1, int hi1, int lo2, int hi2) { + imp_->RangePair(lo1, hi1, lo2, hi2); + return this; +} + +Benchmark* Benchmark::Apply(void (*custom_arguments)(Benchmark* benchmark)) { + custom_arguments(this); + return this; +} + +Benchmark* Benchmark::MinTime(double t) { + imp_->MinTime(t); + return this; +} + +Benchmark* Benchmark::UseRealTime() { + imp_->UseRealTime(); + return this; +} + +Benchmark* Benchmark::Threads(int t) { + imp_->Threads(t); + return this; +} + +Benchmark* Benchmark::ThreadRange(int min_threads, int max_threads) { + imp_->ThreadRange(min_threads, max_threads); + return this; +} + +Benchmark* Benchmark::ThreadPerCpu() { + imp_->ThreadPerCpu(); + return this; +} + +void Benchmark::SetName(const char* name) { + imp_->SetName(name); +} + +void FunctionBenchmark::Run(State& st) { + func_(st); +} + +} // end namespace internal + +namespace { + + +// Execute one thread of benchmark b for the specified number of iterations. +// Adds the stats collected for the thread into *total. +void RunInThread(const benchmark::internal::Benchmark::Instance* b, + size_t iters, int thread_id, + ThreadStats* total) EXCLUDES(GetBenchmarkLock()) { + State st(iters, b->has_arg1, b->arg1, b->has_arg2, b->arg2, thread_id); + b->benchmark->Run(st); + CHECK(st.iterations() == st.max_iterations) << + "Benchmark returned before State::KeepRunning() returned false!"; + { + MutexLock l(GetBenchmarkLock()); + total->bytes_processed += st.bytes_processed(); + total->items_processed += st.items_processed(); + } + + timer_manager->Finalize(); +} + +void RunBenchmark(const benchmark::internal::Benchmark::Instance& b, + BenchmarkReporter* br) EXCLUDES(GetBenchmarkLock()) { + size_t iters = 1; + + std::vector reports; + + std::vector pool; + if (b.multithreaded) + pool.resize(b.threads); + + for (int i = 0; i < FLAGS_benchmark_repetitions; i++) { + std::string mem; + for (;;) { + // Try benchmark + VLOG(2) << "Running " << b.name << " for " << iters << "\n"; + + { + MutexLock l(GetBenchmarkLock()); + GetReportLabel()->clear(); + } + + Notification done; + timer_manager = std::unique_ptr(new TimerManager(b.threads, &done)); + + ThreadStats total; + running_benchmark = true; + if (b.multithreaded) { + // If this is out first iteration of the while(true) loop then the + // threads haven't been started and can't be joined. Otherwise we need + // to join the thread before replacing them. + for (std::thread& thread : pool) { + if (thread.joinable()) + thread.join(); + } + for (std::size_t ti = 0; ti < pool.size(); ++ti) { + pool[ti] = std::thread(&RunInThread, &b, iters, ti, &total); + } + } else { + // Run directly in this thread + RunInThread(&b, iters, 0, &total); + } + done.WaitForNotification(); + running_benchmark = false; + + const double cpu_accumulated_time = timer_manager->cpu_time_used(); + const double real_accumulated_time = timer_manager->real_time_used(); + timer_manager.reset(); + + VLOG(2) << "Ran in " << cpu_accumulated_time << "/" + << real_accumulated_time << "\n"; + + // Base decisions off of real time if requested by this benchmark. + double seconds = cpu_accumulated_time; + if (b.use_real_time) { + seconds = real_accumulated_time; + } + + std::string label; + { + MutexLock l(GetBenchmarkLock()); + label = *GetReportLabel(); + } + + const double min_time = !IsZero(b.min_time) ? b.min_time + : FLAGS_benchmark_min_time; + + // If this was the first run, was elapsed time or cpu time large enough? + // If this is not the first run, go with the current value of iter. + if ((i > 0) || + (iters >= kMaxIterations) || + (seconds >= min_time) || + (real_accumulated_time >= 5*min_time)) { + double bytes_per_second = 0; + if (total.bytes_processed > 0 && seconds > 0.0) { + bytes_per_second = (total.bytes_processed / seconds); + } + double items_per_second = 0; + if (total.items_processed > 0 && seconds > 0.0) { + items_per_second = (total.items_processed / seconds); + } + + // Create report about this benchmark run. + BenchmarkReporter::Run report; + report.benchmark_name = b.name; + report.report_label = label; + // Report the total iterations across all threads. + report.iterations = static_cast(iters) * b.threads; + report.real_accumulated_time = real_accumulated_time; + report.cpu_accumulated_time = cpu_accumulated_time; + report.bytes_per_second = bytes_per_second; + report.items_per_second = items_per_second; + reports.push_back(report); + break; + } + + // See how much iterations should be increased by + // Note: Avoid division by zero with max(seconds, 1ns). + double multiplier = min_time * 1.4 / std::max(seconds, 1e-9); + // If our last run was at least 10% of FLAGS_benchmark_min_time then we + // use the multiplier directly. Otherwise we use at most 10 times + // expansion. + // NOTE: When the last run was at least 10% of the min time the max + // expansion should be 14x. + bool is_significant = (seconds / min_time) > 0.1; + multiplier = is_significant ? multiplier : std::min(10.0, multiplier); + if (multiplier <= 1.0) multiplier = 2.0; + double next_iters = std::max(multiplier * iters, iters + 1.0); + if (next_iters > kMaxIterations) { + next_iters = kMaxIterations; + } + VLOG(3) << "Next iters: " << next_iters << ", " << multiplier << "\n"; + iters = static_cast(next_iters + 0.5); + } + } + br->ReportRuns(reports); + if (b.multithreaded) { + for (std::thread& thread : pool) + thread.join(); + } +} + +} // namespace + +State::State(size_t max_iters, bool has_x, int x, bool has_y, int y, + int thread_i) + : started_(false), total_iterations_(0), + has_range_x_(has_x), range_x_(x), + has_range_y_(has_y), range_y_(y), + bytes_processed_(0), items_processed_(0), + thread_index(thread_i), + max_iterations(max_iters) +{ + CHECK(max_iterations != 0) << "At least one iteration must be run"; +} + +void State::PauseTiming() { + // Add in time accumulated so far + CHECK(running_benchmark); + timer_manager->StopTimer(); +} + +void State::ResumeTiming() { + CHECK(running_benchmark); + timer_manager->StartTimer(); +} + +void State::SetLabel(const char* label) { + CHECK(running_benchmark); + MutexLock l(GetBenchmarkLock()); + *GetReportLabel() = label; +} + +namespace internal { +namespace { + +void PrintBenchmarkList() { + std::vector benchmarks; + auto families = BenchmarkFamilies::GetInstance(); + if (!families->FindBenchmarks(".", &benchmarks)) return; + + for (const internal::Benchmark::Instance& benchmark : benchmarks) { + std::cout << benchmark.name << "\n"; + } +} + +void RunMatchingBenchmarks(const std::string& spec, + BenchmarkReporter* reporter) { + CHECK(reporter != nullptr); + if (spec.empty()) return; + + std::vector benchmarks; + auto families = BenchmarkFamilies::GetInstance(); + if (!families->FindBenchmarks(spec, &benchmarks)) return; + + // Determine the width of the name field using a minimum width of 10. + size_t name_field_width = 10; + for (const Benchmark::Instance& benchmark : benchmarks) { + name_field_width = + std::max(name_field_width, benchmark.name.size()); + } + if (FLAGS_benchmark_repetitions > 1) + name_field_width += std::strlen("_stddev"); + + // Print header here + BenchmarkReporter::Context context; + context.num_cpus = NumCPUs(); + context.mhz_per_cpu = CyclesPerSecond() / 1000000.0f; + + context.cpu_scaling_enabled = CpuScalingEnabled(); + context.name_field_width = name_field_width; + + if (reporter->ReportContext(context)) { + for (const auto& benchmark : benchmarks) { + RunBenchmark(benchmark, reporter); + } + } +} + +std::unique_ptr GetDefaultReporter() { + typedef std::unique_ptr PtrType; + if (FLAGS_benchmark_format == "tabular") { + return PtrType(new ConsoleReporter); + } else if (FLAGS_benchmark_format == "json") { + return PtrType(new JSONReporter); + } else if (FLAGS_benchmark_format == "csv") { + return PtrType(new CSVReporter); + } else { + std::cerr << "Unexpected format: '" << FLAGS_benchmark_format << "'\n"; + std::exit(1); + } +} + +} // end namespace +} // end namespace internal + +void RunSpecifiedBenchmarks() { + RunSpecifiedBenchmarks(nullptr); +} + +void RunSpecifiedBenchmarks(BenchmarkReporter* reporter) { + if (FLAGS_benchmark_list_tests) { + internal::PrintBenchmarkList(); + return; + } + std::string spec = FLAGS_benchmark_filter; + if (spec.empty() || spec == "all") + spec = "."; // Regexp that matches all benchmarks + + std::unique_ptr default_reporter; + if (!reporter) { + default_reporter = internal::GetDefaultReporter(); + reporter = default_reporter.get(); + } + internal::RunMatchingBenchmarks(spec, reporter); + reporter->Finalize(); +} + +namespace internal { + +void PrintUsageAndExit() { + fprintf(stdout, + "benchmark" + " [--benchmark_list_tests={true|false}]\n" + " [--benchmark_filter=]\n" + " [--benchmark_min_time=]\n" + " [--benchmark_repetitions=]\n" + " [--benchmark_format=]\n" + " [--color_print={true|false}]\n" + " [--v=]\n"); + exit(0); +} + +void ParseCommandLineFlags(int* argc, char** argv) { + using namespace benchmark; + for (int i = 1; i < *argc; ++i) { + if ( + ParseBoolFlag(argv[i], "benchmark_list_tests", + &FLAGS_benchmark_list_tests) || + ParseStringFlag(argv[i], "benchmark_filter", + &FLAGS_benchmark_filter) || + ParseDoubleFlag(argv[i], "benchmark_min_time", + &FLAGS_benchmark_min_time) || + ParseInt32Flag(argv[i], "benchmark_repetitions", + &FLAGS_benchmark_repetitions) || + ParseStringFlag(argv[i], "benchmark_format", + &FLAGS_benchmark_format) || + ParseBoolFlag(argv[i], "color_print", + &FLAGS_color_print) || + ParseInt32Flag(argv[i], "v", &FLAGS_v)) { + for (int j = i; j != *argc; ++j) argv[j] = argv[j + 1]; + + --(*argc); + --i; + } else if (IsFlag(argv[i], "help")) { + PrintUsageAndExit(); + } + } + if (FLAGS_benchmark_format != "tabular" && + FLAGS_benchmark_format != "json" && + FLAGS_benchmark_format != "csv") { + PrintUsageAndExit(); + } +} + +Benchmark* RegisterBenchmarkInternal(Benchmark* bench) { + std::unique_ptr bench_ptr(bench); + BenchmarkFamilies* families = BenchmarkFamilies::GetInstance(); + families->AddBenchmark(std::move(bench_ptr)); + return bench; +} + +} // end namespace internal + +void Initialize(int* argc, char** argv) { + internal::ParseCommandLineFlags(argc, argv); + internal::SetLogLevel(FLAGS_v); + // TODO remove this. It prints some output the first time it is called. + // We don't want to have this ouput printed during benchmarking. + MyCPUUsage(); + // The first call to walltime::Now initialized it. Call it once to + // prevent the initialization from happening in a benchmark. + walltime::Now(); +} + +} // end namespace benchmark diff --git a/thirdparty/google-benchmark/src/check.h b/thirdparty/google-benchmark/src/check.h new file mode 100644 index 00000000..d2c1fda9 --- /dev/null +++ b/thirdparty/google-benchmark/src/check.h @@ -0,0 +1,60 @@ +#ifndef CHECK_H_ +#define CHECK_H_ + +#include +#include + +#include "internal_macros.h" +#include "log.h" + +namespace benchmark { +namespace internal { + +// CheckHandler is the class constructed by failing CHECK macros. CheckHandler +// will log information about the failures and abort when it is destructed. +class CheckHandler { +public: + CheckHandler(const char* check, const char* file, const char* func, int line) + : log_(GetErrorLogInstance()) + { + log_ << file << ":" << line << ": " << func << ": Check `" + << check << "' failed. "; + } + + std::ostream& GetLog() { + return log_; + } + + BENCHMARK_NORETURN ~CheckHandler() { + log_ << std::endl; + std::abort(); + } + + CheckHandler & operator=(const CheckHandler&) = delete; + CheckHandler(const CheckHandler&) = delete; + CheckHandler() = delete; +private: + std::ostream& log_; +}; + +} // end namespace internal +} // end namespace benchmark + +// The CHECK macro returns a std::ostream object that can have extra information +// written to it. +#ifndef NDEBUG +# define CHECK(b) (b ? ::benchmark::internal::GetNullLogInstance() \ + : ::benchmark::internal::CheckHandler( \ + #b, __FILE__, __func__, __LINE__).GetLog()) +#else +# define CHECK(b) ::benchmark::internal::GetNullLogInstance() +#endif + +#define CHECK_EQ(a, b) CHECK((a) == (b)) +#define CHECK_NE(a, b) CHECK((a) != (b)) +#define CHECK_GE(a, b) CHECK((a) >= (b)) +#define CHECK_LE(a, b) CHECK((a) <= (b)) +#define CHECK_GT(a, b) CHECK((a) > (b)) +#define CHECK_LT(a, b) CHECK((a) < (b)) + +#endif // CHECK_H_ diff --git a/thirdparty/google-benchmark/src/colorprint.cc b/thirdparty/google-benchmark/src/colorprint.cc new file mode 100644 index 00000000..81f917b2 --- /dev/null +++ b/thirdparty/google-benchmark/src/colorprint.cc @@ -0,0 +1,116 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "colorprint.h" + +#include +#include + +#include "commandlineflags.h" +#include "internal_macros.h" + +#ifdef BENCHMARK_OS_WINDOWS +#include +#endif + +DECLARE_bool(color_print); + +namespace benchmark { +namespace { +#ifdef BENCHMARK_OS_WINDOWS +typedef WORD PlatformColorCode; +#else +typedef const char* PlatformColorCode; +#endif + +PlatformColorCode GetPlatformColorCode(LogColor color) { +#ifdef BENCHMARK_OS_WINDOWS + switch (color) { + case COLOR_RED: + return FOREGROUND_RED; + case COLOR_GREEN: + return FOREGROUND_GREEN; + case COLOR_YELLOW: + return FOREGROUND_RED | FOREGROUND_GREEN; + case COLOR_BLUE: + return FOREGROUND_BLUE; + case COLOR_MAGENTA: + return FOREGROUND_BLUE | FOREGROUND_RED; + case COLOR_CYAN: + return FOREGROUND_BLUE | FOREGROUND_GREEN; + case COLOR_WHITE: // fall through to default + default: + return 0; + } +#else + switch (color) { + case COLOR_RED: + return "1"; + case COLOR_GREEN: + return "2"; + case COLOR_YELLOW: + return "3"; + case COLOR_BLUE: + return "4"; + case COLOR_MAGENTA: + return "5"; + case COLOR_CYAN: + return "6"; + case COLOR_WHITE: + return "7"; + default: + return nullptr; + }; +#endif +} +} // end namespace + +void ColorPrintf(LogColor color, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + + if (!FLAGS_color_print) { + vprintf(fmt, args); + va_end(args); + return; + } + +#ifdef BENCHMARK_OS_WINDOWS + const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE); + + // Gets the current text color. + CONSOLE_SCREEN_BUFFER_INFO buffer_info; + GetConsoleScreenBufferInfo(stdout_handle, &buffer_info); + const WORD old_color_attrs = buffer_info.wAttributes; + + // We need to flush the stream buffers into the console before each + // SetConsoleTextAttribute call lest it affect the text that is already + // printed but has not yet reached the console. + fflush(stdout); + SetConsoleTextAttribute(stdout_handle, + GetPlatformColorCode(color) | FOREGROUND_INTENSITY); + vprintf(fmt, args); + + fflush(stdout); + // Restores the text color. + SetConsoleTextAttribute(stdout_handle, old_color_attrs); +#else + const char* color_code = GetPlatformColorCode(color); + if (color_code) fprintf(stdout, "\033[0;3%sm", color_code); + vprintf(fmt, args); + printf("\033[m"); // Resets the terminal to default. +#endif + va_end(args); +} +} // end namespace benchmark diff --git a/thirdparty/google-benchmark/src/colorprint.h b/thirdparty/google-benchmark/src/colorprint.h new file mode 100644 index 00000000..54d1f664 --- /dev/null +++ b/thirdparty/google-benchmark/src/colorprint.h @@ -0,0 +1,19 @@ +#ifndef BENCHMARK_COLORPRINT_H_ +#define BENCHMARK_COLORPRINT_H_ + +namespace benchmark { +enum LogColor { + COLOR_DEFAULT, + COLOR_RED, + COLOR_GREEN, + COLOR_YELLOW, + COLOR_BLUE, + COLOR_MAGENTA, + COLOR_CYAN, + COLOR_WHITE +}; + +void ColorPrintf(LogColor color, const char* fmt, ...); +} // end namespace benchmark + +#endif // BENCHMARK_COLORPRINT_H_ diff --git a/thirdparty/google-benchmark/src/commandlineflags.cc b/thirdparty/google-benchmark/src/commandlineflags.cc new file mode 100644 index 00000000..3e9a37a7 --- /dev/null +++ b/thirdparty/google-benchmark/src/commandlineflags.cc @@ -0,0 +1,220 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "commandlineflags.h" + +#include +#include +#include +#include + +namespace benchmark { +// Parses 'str' for a 32-bit signed integer. If successful, writes +// the result to *value and returns true; otherwise leaves *value +// unchanged and returns false. +bool ParseInt32(const std::string& src_text, const char* str, int32_t* value) { + // Parses the environment variable as a decimal integer. + char* end = nullptr; + const long long_value = strtol(str, &end, 10); // NOLINT + + // Has strtol() consumed all characters in the string? + if (*end != '\0') { + // No - an invalid character was encountered. + std::cerr << src_text << " is expected to be a 32-bit integer, " + << "but actually has value \"" << str << "\".\n"; + return false; + } + + // Is the parsed value in the range of an Int32? + const int32_t result = static_cast(long_value); + if (long_value == std::numeric_limits::max() || + long_value == std::numeric_limits::min() || + // The parsed value overflows as a long. (strtol() returns + // LONG_MAX or LONG_MIN when the input overflows.) + result != long_value + // The parsed value overflows as an Int32. + ) { + std::cerr << src_text << " is expected to be a 32-bit integer, " + << "but actually has value \"" << str << "\", " + << "which overflows.\n"; + return false; + } + + *value = result; + return true; +} + +// Parses 'str' for a double. If successful, writes the result to *value and +// returns true; otherwise leaves *value unchanged and returns false. +bool ParseDouble(const std::string& src_text, const char* str, double* value) { + // Parses the environment variable as a decimal integer. + char* end = nullptr; + const double double_value = strtod(str, &end); // NOLINT + + // Has strtol() consumed all characters in the string? + if (*end != '\0') { + // No - an invalid character was encountered. + std::cerr << src_text << " is expected to be a double, " + << "but actually has value \"" << str << "\".\n"; + return false; + } + + *value = double_value; + return true; +} + +inline const char* GetEnv(const char* name) { +#if defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9) + // Environment variables which we programmatically clear will be set to the + // empty string rather than unset (nullptr). Handle that case. + const char* const env = getenv(name); + return (env != nullptr && env[0] != '\0') ? env : nullptr; +#else + return getenv(name); +#endif +} + +// Returns the name of the environment variable corresponding to the +// given flag. For example, FlagToEnvVar("foo") will return +// "BENCHMARK_FOO" in the open-source version. +static std::string FlagToEnvVar(const char* flag) { + const std::string flag_str(flag); + + std::string env_var; + for (size_t i = 0; i != flag_str.length(); ++i) + env_var += static_cast(::toupper(flag_str.c_str()[i])); + + return "BENCHMARK_" + env_var; +} + +// Reads and returns the Boolean environment variable corresponding to +// the given flag; if it's not set, returns default_value. +// +// The value is considered true iff it's not "0". +bool BoolFromEnv(const char* flag, bool default_value) { + const std::string env_var = FlagToEnvVar(flag); + const char* const string_value = GetEnv(env_var.c_str()); + return string_value == nullptr ? default_value : strcmp(string_value, "0") != 0; +} + +// Reads and returns a 32-bit integer stored in the environment +// variable corresponding to the given flag; if it isn't set or +// doesn't represent a valid 32-bit integer, returns default_value. +int32_t Int32FromEnv(const char* flag, int32_t default_value) { + const std::string env_var = FlagToEnvVar(flag); + const char* const string_value = GetEnv(env_var.c_str()); + if (string_value == nullptr) { + // The environment variable is not set. + return default_value; + } + + int32_t result = default_value; + if (!ParseInt32(std::string("Environment variable ") + env_var, string_value, + &result)) { + std::cout << "The default value " << default_value << " is used.\n"; + return default_value; + } + + return result; +} + +// Reads and returns the string environment variable corresponding to +// the given flag; if it's not set, returns default_value. +const char* StringFromEnv(const char* flag, const char* default_value) { + const std::string env_var = FlagToEnvVar(flag); + const char* const value = GetEnv(env_var.c_str()); + return value == nullptr ? default_value : value; +} + +// Parses a string as a command line flag. The string should have +// the format "--flag=value". When def_optional is true, the "=value" +// part can be omitted. +// +// Returns the value of the flag, or nullptr if the parsing failed. +const char* ParseFlagValue(const char* str, const char* flag, + bool def_optional) { + // str and flag must not be nullptr. + if (str == nullptr || flag == nullptr) return nullptr; + + // The flag must start with "--". + const std::string flag_str = std::string("--") + std::string(flag); + const size_t flag_len = flag_str.length(); + if (strncmp(str, flag_str.c_str(), flag_len) != 0) return nullptr; + + // Skips the flag name. + const char* flag_end = str + flag_len; + + // When def_optional is true, it's OK to not have a "=value" part. + if (def_optional && (flag_end[0] == '\0')) return flag_end; + + // If def_optional is true and there are more characters after the + // flag name, or if def_optional is false, there must be a '=' after + // the flag name. + if (flag_end[0] != '=') return nullptr; + + // Returns the string after "=". + return flag_end + 1; +} + +bool ParseBoolFlag(const char* str, const char* flag, bool* value) { + // Gets the value of the flag as a string. + const char* const value_str = ParseFlagValue(str, flag, true); + + // Aborts if the parsing failed. + if (value_str == nullptr) return false; + + // Converts the string value to a bool. + *value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F'); + return true; +} + +bool ParseInt32Flag(const char* str, const char* flag, int32_t* value) { + // Gets the value of the flag as a string. + const char* const value_str = ParseFlagValue(str, flag, false); + + // Aborts if the parsing failed. + if (value_str == nullptr) return false; + + // Sets *value to the value of the flag. + return ParseInt32(std::string("The value of flag --") + flag, value_str, + value); +} + +bool ParseDoubleFlag(const char* str, const char* flag, double* value) { + // Gets the value of the flag as a string. + const char* const value_str = ParseFlagValue(str, flag, false); + + // Aborts if the parsing failed. + if (value_str == nullptr) return false; + + // Sets *value to the value of the flag. + return ParseDouble(std::string("The value of flag --") + flag, value_str, + value); +} + +bool ParseStringFlag(const char* str, const char* flag, std::string* value) { + // Gets the value of the flag as a string. + const char* const value_str = ParseFlagValue(str, flag, false); + + // Aborts if the parsing failed. + if (value_str == nullptr) return false; + + *value = value_str; + return true; +} + +bool IsFlag(const char* str, const char* flag) { + return (ParseFlagValue(str, flag, true) != nullptr); +} +} // end namespace benchmark diff --git a/thirdparty/google-benchmark/src/commandlineflags.h b/thirdparty/google-benchmark/src/commandlineflags.h new file mode 100644 index 00000000..34b9c6f3 --- /dev/null +++ b/thirdparty/google-benchmark/src/commandlineflags.h @@ -0,0 +1,76 @@ +#ifndef BENCHMARK_COMMANDLINEFLAGS_H_ +#define BENCHMARK_COMMANDLINEFLAGS_H_ + +#include +#include + +// Macro for referencing flags. +#define FLAG(name) FLAGS_##name + +// Macros for declaring flags. +#define DECLARE_bool(name) extern bool FLAG(name) +#define DECLARE_int32(name) extern int32_t FLAG(name) +#define DECLARE_int64(name) extern int64_t FLAG(name) +#define DECLARE_double(name) extern double FLAG(name) +#define DECLARE_string(name) extern std::string FLAG(name) + +// Macros for defining flags. +#define DEFINE_bool(name, default_val, doc) bool FLAG(name) = (default_val) +#define DEFINE_int32(name, default_val, doc) int32_t FLAG(name) = (default_val) +#define DEFINE_int64(name, default_val, doc) int64_t FLAG(name) = (default_val) +#define DEFINE_double(name, default_val, doc) double FLAG(name) = (default_val) +#define DEFINE_string(name, default_val, doc) \ + std::string FLAG(name) = (default_val) + +namespace benchmark { +// Parses 'str' for a 32-bit signed integer. If successful, writes the result +// to *value and returns true; otherwise leaves *value unchanged and returns +// false. +bool ParseInt32(const std::string& src_text, const char* str, int32_t* value); + +// Parses a bool/Int32/string from the environment variable +// corresponding to the given Google Test flag. +bool BoolFromEnv(const char* flag, bool default_val); +int32_t Int32FromEnv(const char* flag, int32_t default_val); +double DoubleFromEnv(const char* flag, double default_val); +const char* StringFromEnv(const char* flag, const char* default_val); + +// Parses a string for a bool flag, in the form of either +// "--flag=value" or "--flag". +// +// In the former case, the value is taken as true as long as it does +// not start with '0', 'f', or 'F'. +// +// In the latter case, the value is taken as true. +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +bool ParseBoolFlag(const char* str, const char* flag, bool* value); + +// Parses a string for an Int32 flag, in the form of +// "--flag=value". +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +bool ParseInt32Flag(const char* str, const char* flag, int32_t* value); + +// Parses a string for a Double flag, in the form of +// "--flag=value". +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +bool ParseDoubleFlag(const char* str, const char* flag, double* value); + +// Parses a string for a string flag, in the form of +// "--flag=value". +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +bool ParseStringFlag(const char* str, const char* flag, std::string* value); + +// Returns true if the string matches the flag. +bool IsFlag(const char* str, const char* flag); + +} // end namespace benchmark + +#endif // BENCHMARK_COMMANDLINEFLAGS_H_ diff --git a/thirdparty/google-benchmark/src/console_reporter.cc b/thirdparty/google-benchmark/src/console_reporter.cc new file mode 100644 index 00000000..bee3c857 --- /dev/null +++ b/thirdparty/google-benchmark/src/console_reporter.cc @@ -0,0 +1,116 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "benchmark/reporter.h" + +#include +#include +#include +#include +#include + +#include "check.h" +#include "colorprint.h" +#include "string_util.h" +#include "walltime.h" + +namespace benchmark { + +bool ConsoleReporter::ReportContext(const Context& context) { + name_field_width_ = context.name_field_width; + + std::cerr << "Run on (" << context.num_cpus << " X " << context.mhz_per_cpu + << " MHz CPU " << ((context.num_cpus > 1) ? "s" : "") << ")\n"; + + std::cerr << LocalDateTimeString() << "\n"; + + if (context.cpu_scaling_enabled) { + std::cerr << "***WARNING*** CPU scaling is enabled, the benchmark " + "real time measurements may be noisy and will incure extra " + "overhead.\n"; + } + +#ifndef NDEBUG + std::cerr << "***WARNING*** Library was built as DEBUG. Timings may be " + "affected.\n"; +#endif + + int output_width = fprintf(stdout, "%-*s %10s %10s %10s\n", + static_cast(name_field_width_), "Benchmark", + "Time(ns)", "CPU(ns)", "Iterations"); + std::cout << std::string(output_width - 1, '-') << "\n"; + + return true; +} + +void ConsoleReporter::ReportRuns(const std::vector& reports) { + if (reports.empty()) { + return; + } + + for (Run const& run : reports) { + CHECK_EQ(reports[0].benchmark_name, run.benchmark_name); + PrintRunData(run); + } + + if (reports.size() < 2) { + // We don't report aggregated data if there was a single run. + return; + } + + Run mean_data; + Run stddev_data; + BenchmarkReporter::ComputeStats(reports, &mean_data, &stddev_data); + + // Output using PrintRun. + PrintRunData(mean_data); + PrintRunData(stddev_data); +} + +void ConsoleReporter::PrintRunData(const Run& result) { + // Format bytes per second + std::string rate; + if (result.bytes_per_second > 0) { + rate = StrCat(" ", HumanReadableNumber(result.bytes_per_second), "B/s"); + } + + // Format items per second + std::string items; + if (result.items_per_second > 0) { + items = StrCat(" ", HumanReadableNumber(result.items_per_second), + " items/s"); + } + + double const multiplier = 1e9; // nano second multiplier + ColorPrintf(COLOR_GREEN, "%-*s ", + name_field_width_, result.benchmark_name.c_str()); + if (result.iterations == 0) { + ColorPrintf(COLOR_YELLOW, "%10.0f %10.0f ", + result.real_accumulated_time * multiplier, + result.cpu_accumulated_time * multiplier); + } else { + ColorPrintf(COLOR_YELLOW, "%10.0f %10.0f ", + (result.real_accumulated_time * multiplier) / + (static_cast(result.iterations)), + (result.cpu_accumulated_time * multiplier) / + (static_cast(result.iterations))); + } + ColorPrintf(COLOR_CYAN, "%10lld", result.iterations); + ColorPrintf(COLOR_DEFAULT, "%*s %*s %s\n", + 13, rate.c_str(), + 18, items.c_str(), + result.report_label.c_str()); +} + +} // end namespace benchmark diff --git a/thirdparty/google-benchmark/src/csv_reporter.cc b/thirdparty/google-benchmark/src/csv_reporter.cc new file mode 100644 index 00000000..a8369433 --- /dev/null +++ b/thirdparty/google-benchmark/src/csv_reporter.cc @@ -0,0 +1,105 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "benchmark/reporter.h" + +#include +#include +#include +#include + +#include "string_util.h" +#include "walltime.h" + +// File format reference: http://edoceo.com/utilitas/csv-file-format. + +namespace benchmark { + +bool CSVReporter::ReportContext(const Context& context) { + std::cerr << "Run on (" << context.num_cpus << " X " << context.mhz_per_cpu + << " MHz CPU " << ((context.num_cpus > 1) ? "s" : "") << ")\n"; + + std::cerr << LocalDateTimeString() << "\n"; + + if (context.cpu_scaling_enabled) { + std::cerr << "***WARNING*** CPU scaling is enabled, the benchmark " + "real time measurements may be noisy and will incure extra " + "overhead.\n"; + } + +#ifndef NDEBUG + std::cerr << "***WARNING*** Library was built as DEBUG. Timings may be " + "affected.\n"; +#endif + std::cout << "name,iterations,real_time,cpu_time,bytes_per_second," + "items_per_second,label\n"; + return true; +} + +void CSVReporter::ReportRuns(std::vector const& reports) { + if (reports.empty()) { + return; + } + + std::vector reports_cp = reports; + if (reports.size() >= 2) { + Run mean_data; + Run stddev_data; + BenchmarkReporter::ComputeStats(reports, &mean_data, &stddev_data); + reports_cp.push_back(mean_data); + reports_cp.push_back(stddev_data); + } + for (auto it = reports_cp.begin(); it != reports_cp.end(); ++it) { + PrintRunData(*it); + } +} + +void CSVReporter::PrintRunData(Run const& run) { + double const multiplier = 1e9; // nano second multiplier + double cpu_time = run.cpu_accumulated_time * multiplier; + double real_time = run.real_accumulated_time * multiplier; + if (run.iterations != 0) { + real_time = real_time / static_cast(run.iterations); + cpu_time = cpu_time / static_cast(run.iterations); + } + + // Field with embedded double-quote characters must be doubled and the field + // delimited with double-quotes. + std::string name = run.benchmark_name; + ReplaceAll(&name, "\"", "\"\""); + std::cout << "\"" << name << "\","; + + std::cout << run.iterations << ","; + std::cout << real_time << ","; + std::cout << cpu_time << ","; + + if (run.bytes_per_second > 0.0) { + std::cout << run.bytes_per_second; + } + std::cout << ","; + if (run.items_per_second > 0.0) { + std::cout << run.items_per_second; + } + std::cout << ","; + if (!run.report_label.empty()) { + // Field with embedded double-quote characters must be doubled and the field + // delimited with double-quotes. + std::string label = run.report_label; + ReplaceAll(&label, "\"", "\"\""); + std::cout << "\"" << label << "\""; + } + std::cout << '\n'; +} + +} // end namespace benchmark diff --git a/thirdparty/google-benchmark/src/cycleclock.h b/thirdparty/google-benchmark/src/cycleclock.h new file mode 100644 index 00000000..42541daf --- /dev/null +++ b/thirdparty/google-benchmark/src/cycleclock.h @@ -0,0 +1,137 @@ +// ---------------------------------------------------------------------- +// CycleClock +// A CycleClock tells you the current time in Cycles. The "time" +// is actually time since power-on. This is like time() but doesn't +// involve a system call and is much more precise. +// +// NOTE: Not all cpu/platform/kernel combinations guarantee that this +// clock increments at a constant rate or is synchronized across all logical +// cpus in a system. +// +// If you need the above guarantees, please consider using a different +// API. There are efforts to provide an interface which provides a millisecond +// granularity and implemented as a memory read. A memory read is generally +// cheaper than the CycleClock for many architectures. +// +// Also, in some out of order CPU implementations, the CycleClock is not +// serializing. So if you're trying to count at cycles granularity, your +// data might be inaccurate due to out of order instruction execution. +// ---------------------------------------------------------------------- + +#ifndef BENCHMARK_CYCLECLOCK_H_ +#define BENCHMARK_CYCLECLOCK_H_ + +#include + +#include "benchmark/macros.h" +#include "internal_macros.h" + +#if defined(BENCHMARK_OS_MACOSX) +#include +#endif +// For MSVC, we want to use '_asm rdtsc' when possible (since it works +// with even ancient MSVC compilers), and when not possible the +// __rdtsc intrinsic, declared in . Unfortunately, in some +// environments, and have conflicting +// declarations of some other intrinsics, breaking compilation. +// Therefore, we simply declare __rdtsc ourselves. See also +// http://connect.microsoft.com/VisualStudio/feedback/details/262047 +#if defined(COMPILER_MSVC) && !defined(_M_IX86) +extern "C" uint64_t __rdtsc(); +#pragma intrinsic(__rdtsc) +#endif + +#ifndef BENCHMARK_OS_WINDOWS +#include +#endif + +namespace benchmark { +// NOTE: only i386 and x86_64 have been well tested. +// PPC, sparc, alpha, and ia64 are based on +// http://peter.kuscsik.com/wordpress/?p=14 +// with modifications by m3b. See also +// https://setisvn.ssl.berkeley.edu/svn/lib/fftw-3.0.1/kernel/cycle.h +namespace cycleclock { +// This should return the number of cycles since power-on. Thread-safe. +inline BENCHMARK_ALWAYS_INLINE int64_t Now() { +#if defined(BENCHMARK_OS_MACOSX) + // this goes at the top because we need ALL Macs, regardless of + // architecture, to return the number of "mach time units" that + // have passed since startup. See sysinfo.cc where + // InitializeSystemInfo() sets the supposed cpu clock frequency of + // macs to the number of mach time units per second, not actual + // CPU clock frequency (which can change in the face of CPU + // frequency scaling). Also note that when the Mac sleeps, this + // counter pauses; it does not continue counting, nor does it + // reset to zero. + return mach_absolute_time(); +#elif defined(__i386__) + int64_t ret; + __asm__ volatile("rdtsc" : "=A"(ret)); + return ret; +#elif defined(__x86_64__) || defined(__amd64__) + uint64_t low, high; + __asm__ volatile("rdtsc" : "=a"(low), "=d"(high)); + return (high << 32) | low; +#elif defined(__powerpc__) || defined(__ppc__) + // This returns a time-base, which is not always precisely a cycle-count. + int64_t tbl, tbu0, tbu1; + asm("mftbu %0" : "=r"(tbu0)); + asm("mftb %0" : "=r"(tbl)); + asm("mftbu %0" : "=r"(tbu1)); + tbl &= -static_cast(tbu0 == tbu1); + // high 32 bits in tbu1; low 32 bits in tbl (tbu0 is garbage) + return (tbu1 << 32) | tbl; +#elif defined(__sparc__) + int64_t tick; + asm(".byte 0x83, 0x41, 0x00, 0x00"); + asm("mov %%g1, %0" : "=r"(tick)); + return tick; +#elif defined(__ia64__) + int64_t itc; + asm("mov %0 = ar.itc" : "=r"(itc)); + return itc; +#elif defined(COMPILER_MSVC) && defined(_M_IX86) + // Older MSVC compilers (like 7.x) don't seem to support the + // __rdtsc intrinsic properly, so I prefer to use _asm instead + // when I know it will work. Otherwise, I'll use __rdtsc and hope + // the code is being compiled with a non-ancient compiler. + _asm rdtsc +#elif defined(COMPILER_MSVC) + return __rdtsc(); +#elif defined(__ARM_ARCH) +#if (__ARM_ARCH >= 6) // V6 is the earliest arch that has a standard cyclecount + uint32_t pmccntr; + uint32_t pmuseren; + uint32_t pmcntenset; + // Read the user mode perf monitor counter access permissions. + asm("mrc p15, 0, %0, c9, c14, 0" : "=r"(pmuseren)); + if (pmuseren & 1) { // Allows reading perfmon counters for user mode code. + asm("mrc p15, 0, %0, c9, c12, 1" : "=r"(pmcntenset)); + if (pmcntenset & 0x80000000ul) { // Is it counting? + asm("mrc p15, 0, %0, c9, c13, 0" : "=r"(pmccntr)); + // The counter is set up to count every 64th cycle + return static_cast(pmccntr) * 64; // Should optimize to << 6 + } + } +#endif + struct timeval tv; + gettimeofday(&tv, nullptr); + return static_cast(tv.tv_sec) * 1000000 + tv.tv_usec; +#elif defined(__mips__) + // mips apparently only allows rdtsc for superusers, so we fall + // back to gettimeofday. It's possible clock_gettime would be better. + struct timeval tv; + gettimeofday(&tv, nullptr); + return static_cast(tv.tv_sec) * 1000000 + tv.tv_usec; +#else +// The soft failover to a generic implementation is automatic only for ARM. +// For other platforms the developer is expected to make an attempt to create +// a fast implementation and use generic version if nothing better is available. +#error You need to define CycleTimer for your OS and CPU +#endif +} +} // end namespace cycleclock +} // end namespace benchmark + +#endif // BENCHMARK_CYCLECLOCK_H_ diff --git a/thirdparty/google-benchmark/src/internal_macros.h b/thirdparty/google-benchmark/src/internal_macros.h new file mode 100644 index 00000000..1080ac94 --- /dev/null +++ b/thirdparty/google-benchmark/src/internal_macros.h @@ -0,0 +1,40 @@ +#ifndef BENCHMARK_INTERNAL_MACROS_H_ +#define BENCHMARK_INTERNAL_MACROS_H_ + +#include "benchmark/macros.h" + +#ifndef __has_feature +# define __has_feature(x) 0 +#endif + +#if __has_feature(cxx_attributes) +# define BENCHMARK_NORETURN [[noreturn]] +#elif defined(__GNUC__) +# define BENCHMARK_NORETURN __attribute__((noreturn)) +#else +# define BENCHMARK_NORETURN +#endif + +#if defined(__CYGWIN__) +# define BENCHMARK_OS_CYGWIN 1 +#elif defined(_WIN32) +# define BENCHMARK_OS_WINDOWS 1 +#elif defined(__APPLE__) +// TODO(ericwf) This doesn't actually check that it is a Mac OSX system. Just +// that it is an apple system. +# define BENCHMARK_OS_MACOSX 1 +#elif defined(__FreeBSD__) +# define BENCHMARK_OS_FREEBSD 1 +#elif defined(__linux__) +# define BENCHMARK_OS_LINUX 1 +#endif + +#if defined(__clang__) +# define COMPILER_CLANG +#elif defined(_MSC_VER) +# define COMPILER_MSVC +#elif defined(__GNUC__) +# define COMPILER_GCC +#endif + +#endif // BENCHMARK_INTERNAL_MACROS_H_ diff --git a/thirdparty/google-benchmark/src/json_reporter.cc b/thirdparty/google-benchmark/src/json_reporter.cc new file mode 100644 index 00000000..def50ac4 --- /dev/null +++ b/thirdparty/google-benchmark/src/json_reporter.cc @@ -0,0 +1,159 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "benchmark/reporter.h" + +#include +#include +#include +#include + +#include "string_util.h" +#include "walltime.h" + +namespace benchmark { + +namespace { + +std::string FormatKV(std::string const& key, std::string const& value) { + return StringPrintF("\"%s\": \"%s\"", key.c_str(), value.c_str()); +} + +std::string FormatKV(std::string const& key, const char* value) { + return StringPrintF("\"%s\": \"%s\"", key.c_str(), value); +} + +std::string FormatKV(std::string const& key, bool value) { + return StringPrintF("\"%s\": %s", key.c_str(), value ? "true" : "false"); +} + +std::string FormatKV(std::string const& key, int64_t value) { + std::stringstream ss; + ss << '"' << key << "\": " << value; + return ss.str(); +} + +int64_t RoundDouble(double v) { + return static_cast(v + 0.5); +} + +} // end namespace + +bool JSONReporter::ReportContext(const Context& context) { + std::ostream& out = std::cout; + + out << "{\n"; + std::string inner_indent(2, ' '); + + // Open context block and print context information. + out << inner_indent << "\"context\": {\n"; + std::string indent(4, ' '); + + std::string walltime_value = LocalDateTimeString(); + out << indent << FormatKV("date", walltime_value) << ",\n"; + + out << indent + << FormatKV("num_cpus", static_cast(context.num_cpus)) + << ",\n"; + out << indent + << FormatKV("mhz_per_cpu", RoundDouble(context.mhz_per_cpu)) + << ",\n"; + out << indent + << FormatKV("cpu_scaling_enabled", context.cpu_scaling_enabled) + << ",\n"; + +#if defined(NDEBUG) + const char build_type[] = "release"; +#else + const char build_type[] = "debug"; +#endif + out << indent << FormatKV("library_build_type", build_type) << "\n"; + // Close context block and open the list of benchmarks. + out << inner_indent << "},\n"; + out << inner_indent << "\"benchmarks\": [\n"; + return true; +} + +void JSONReporter::ReportRuns(std::vector const& reports) { + if (reports.empty()) { + return; + } + std::string indent(4, ' '); + std::ostream& out = std::cout; + if (!first_report_) { + out << ",\n"; + } + first_report_ = false; + std::vector reports_cp = reports; + if (reports.size() >= 2) { + Run mean_data; + Run stddev_data; + BenchmarkReporter::ComputeStats(reports, &mean_data, &stddev_data); + reports_cp.push_back(mean_data); + reports_cp.push_back(stddev_data); + } + for (auto it = reports_cp.begin(); it != reports_cp.end(); ++it) { + out << indent << "{\n"; + PrintRunData(*it); + out << indent << '}'; + auto it_cp = it; + if (++it_cp != reports_cp.end()) { + out << ",\n"; + } + } +} + +void JSONReporter::Finalize() { + // Close the list of benchmarks and the top level object. + std::cout << "\n ]\n}\n"; +} + +void JSONReporter::PrintRunData(Run const& run) { + double const multiplier = 1e9; // nano second multiplier + double cpu_time = run.cpu_accumulated_time * multiplier; + double real_time = run.real_accumulated_time * multiplier; + if (run.iterations != 0) { + real_time = real_time / static_cast(run.iterations); + cpu_time = cpu_time / static_cast(run.iterations); + } + + std::string indent(6, ' '); + std::ostream& out = std::cout; + out << indent + << FormatKV("name", run.benchmark_name) + << ",\n"; + out << indent + << FormatKV("iterations", run.iterations) + << ",\n"; + out << indent + << FormatKV("real_time", RoundDouble(real_time)) + << ",\n"; + out << indent + << FormatKV("cpu_time", RoundDouble(cpu_time)); + if (run.bytes_per_second > 0.0) { + out << ",\n" << indent + << FormatKV("bytes_per_second", RoundDouble(run.bytes_per_second)); + } + if (run.items_per_second > 0.0) { + out << ",\n" << indent + << FormatKV("items_per_second", RoundDouble(run.items_per_second)); + } + if (!run.report_label.empty()) { + out << ",\n" << indent + << FormatKV("label", run.report_label); + } + out << '\n'; +} + +} // end namespace benchmark diff --git a/thirdparty/google-benchmark/src/log.cc b/thirdparty/google-benchmark/src/log.cc new file mode 100644 index 00000000..b660309d --- /dev/null +++ b/thirdparty/google-benchmark/src/log.cc @@ -0,0 +1,40 @@ +#include "log.h" + +#include + +namespace benchmark { +namespace internal { + +int& LoggingLevelImp() { + static int level = 0; + return level; +} + +void SetLogLevel(int value) { + LoggingLevelImp() = value; +} + +int GetLogLevel() { + return LoggingLevelImp(); +} + +class NullLogBuffer : public std::streambuf +{ +public: + int overflow(int c) { + return c; + } +}; + +std::ostream& GetNullLogInstance() { + static NullLogBuffer log_buff; + static std::ostream null_log(&log_buff); + return null_log; +} + +std::ostream& GetErrorLogInstance() { + return std::clog; +} + +} // end namespace internal +} // end namespace benchmark \ No newline at end of file diff --git a/thirdparty/google-benchmark/src/log.h b/thirdparty/google-benchmark/src/log.h new file mode 100644 index 00000000..3777810e --- /dev/null +++ b/thirdparty/google-benchmark/src/log.h @@ -0,0 +1,28 @@ +#ifndef BENCHMARK_LOG_H_ +#define BENCHMARK_LOG_H_ + +#include + +namespace benchmark { +namespace internal { + +int GetLogLevel(); +void SetLogLevel(int level); + +std::ostream& GetNullLogInstance(); +std::ostream& GetErrorLogInstance(); + +inline std::ostream& GetLogInstanceForLevel(int level) { + if (level <= GetLogLevel()) { + return GetErrorLogInstance(); + } + return GetNullLogInstance(); +} + +} // end namespace internal +} // end namespace benchmark + +#define VLOG(x) (::benchmark::internal::GetLogInstanceForLevel(x) \ + << "-- LOG(" << x << "): ") + +#endif \ No newline at end of file diff --git a/thirdparty/google-benchmark/src/mutex.h b/thirdparty/google-benchmark/src/mutex.h new file mode 100644 index 00000000..f37ec35b --- /dev/null +++ b/thirdparty/google-benchmark/src/mutex.h @@ -0,0 +1,142 @@ +#ifndef BENCHMARK_MUTEX_H_ +#define BENCHMARK_MUTEX_H_ + +#include +#include + +// Enable thread safety attributes only with clang. +// The attributes can be safely erased when compiling with other compilers. +#if defined(HAVE_THREAD_SAFETY_ATTRIBUTES) +#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) +#else +#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op +#endif + +#define CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(capability(x)) + +#define SCOPED_CAPABILITY \ + THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) + +#define GUARDED_BY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) + +#define PT_GUARDED_BY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) + +#define ACQUIRED_BEFORE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) + +#define ACQUIRED_AFTER(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) + +#define REQUIRES(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__)) + +#define REQUIRES_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__)) + +#define ACQUIRE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__)) + +#define ACQUIRE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__)) + +#define RELEASE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__)) + +#define RELEASE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__)) + +#define TRY_ACQUIRE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__)) + +#define TRY_ACQUIRE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__)) + +#define EXCLUDES(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) + +#define ASSERT_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x)) + +#define ASSERT_SHARED_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x)) + +#define RETURN_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) + +#define NO_THREAD_SAFETY_ANALYSIS \ + THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) + + +namespace benchmark { + +typedef std::condition_variable Condition; + +// NOTE: Wrappers for std::mutex and std::unique_lock are provided so that +// we can annotate them with thread safety attributes and use the +// -Wthread-safety warning with clang. The standard library types cannot be +// used directly because they do not provided the required annotations. +class CAPABILITY("mutex") Mutex +{ +public: + Mutex() {} + + void lock() ACQUIRE() { mut_.lock(); } + void unlock() RELEASE() { mut_.unlock(); } + std::mutex& native_handle() { + return mut_; + } +private: + std::mutex mut_; +}; + + +class SCOPED_CAPABILITY MutexLock +{ + typedef std::unique_lock MutexLockImp; +public: + MutexLock(Mutex& m) ACQUIRE(m) : ml_(m.native_handle()) + { } + ~MutexLock() RELEASE() {} + MutexLockImp& native_handle() { return ml_; } +private: + MutexLockImp ml_; +}; + + +class Notification +{ +public: + Notification() : notified_yet_(false) { } + + void WaitForNotification() const EXCLUDES(mutex_) { + MutexLock m_lock(mutex_); + auto notified_fn = [this]() REQUIRES(mutex_) { + return this->HasBeenNotified(); + }; + cv_.wait(m_lock.native_handle(), notified_fn); + } + + void Notify() EXCLUDES(mutex_) { + { + MutexLock lock(mutex_); + notified_yet_ = 1; + } + cv_.notify_all(); + } + +private: + bool HasBeenNotified() const REQUIRES(mutex_) { + return notified_yet_; + } + + mutable Mutex mutex_; + mutable std::condition_variable cv_; + bool notified_yet_ GUARDED_BY(mutex_); +}; + +} // end namespace benchmark + +#endif // BENCHMARK_MUTEX_H_ diff --git a/thirdparty/google-benchmark/src/re.h b/thirdparty/google-benchmark/src/re.h new file mode 100644 index 00000000..af57a39c --- /dev/null +++ b/thirdparty/google-benchmark/src/re.h @@ -0,0 +1,60 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef BENCHMARK_RE_H_ +#define BENCHMARK_RE_H_ + +#if defined(HAVE_STD_REGEX) +#include +#elif defined(HAVE_GNU_POSIX_REGEX) +#include +#elif defined(HAVE_POSIX_REGEX) +#include +#else +#error No regular expression backend was found! +#endif +#include + +namespace benchmark { + +// A wrapper around the POSIX regular expression API that provides automatic +// cleanup +class Regex { + public: + Regex(); + ~Regex(); + + // Compile a regular expression matcher from spec. Returns true on success. + // + // On failure (and if error is not nullptr), error is populated with a human + // readable error message if an error occurs. + bool Init(const std::string& spec, std::string* error); + + // Returns whether str matches the compiled regular expression. + bool Match(const std::string& str); + private: + bool init_; + // Underlying regular expression object +#if defined(HAVE_STD_REGEX) + std::regex re_; +#elif defined(HAVE_POSIX_REGEX) || defined(HAVE_GNU_POSIX_REGEX) + regex_t re_; +#else +# error No regular expression backend implementation available +#endif +}; + +} // end namespace benchmark + +#endif // BENCHMARK_RE_H_ diff --git a/thirdparty/google-benchmark/src/re_posix.cc b/thirdparty/google-benchmark/src/re_posix.cc new file mode 100644 index 00000000..95b086ff --- /dev/null +++ b/thirdparty/google-benchmark/src/re_posix.cc @@ -0,0 +1,59 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "check.h" +#include "re.h" + +namespace benchmark { + +Regex::Regex() : init_(false) { } + +bool Regex::Init(const std::string& spec, std::string* error) { + int ec = regcomp(&re_, spec.c_str(), REG_EXTENDED | REG_NOSUB); + if (ec != 0) { + if (error) { + size_t needed = regerror(ec, &re_, nullptr, 0); + char* errbuf = new char[needed]; + regerror(ec, &re_, errbuf, needed); + + // regerror returns the number of bytes necessary to null terminate + // the string, so we move that when assigning to error. + CHECK_NE(needed, 0); + error->assign(errbuf, needed - 1); + + delete[] errbuf; + } + + return false; + } + + init_ = true; + return true; +} + +Regex::~Regex() { + if (init_) { + regfree(&re_); + } +} + +bool Regex::Match(const std::string& str) { + if (!init_) { + return false; + } + + return regexec(&re_, str.c_str(), 0, nullptr, 0) == 0; +} + +} // end namespace benchmark diff --git a/thirdparty/google-benchmark/src/re_std.cc b/thirdparty/google-benchmark/src/re_std.cc new file mode 100644 index 00000000..cfd7a218 --- /dev/null +++ b/thirdparty/google-benchmark/src/re_std.cc @@ -0,0 +1,44 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "re.h" + +namespace benchmark { + +Regex::Regex() : init_(false) { } + +bool Regex::Init(const std::string& spec, std::string* error) { + try { + re_ = std::regex(spec, std::regex_constants::extended); + + init_ = true; + } catch (const std::regex_error& e) { + if (error) { + *error = e.what(); + } + } + return init_; +} + +Regex::~Regex() { } + +bool Regex::Match(const std::string& str) { + if (!init_) { + return false; + } + + return std::regex_search(str, re_); +} + +} // end namespace benchmark diff --git a/thirdparty/google-benchmark/src/reporter.cc b/thirdparty/google-benchmark/src/reporter.cc new file mode 100644 index 00000000..4b47e3d5 --- /dev/null +++ b/thirdparty/google-benchmark/src/reporter.cc @@ -0,0 +1,86 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "benchmark/reporter.h" + +#include +#include + +#include "check.h" +#include "stat.h" + +namespace benchmark { + +void BenchmarkReporter::ComputeStats( + const std::vector& reports, + Run* mean_data, Run* stddev_data) { + CHECK(reports.size() >= 2) << "Cannot compute stats for less than 2 reports"; + // Accumulators. + Stat1_d real_accumulated_time_stat; + Stat1_d cpu_accumulated_time_stat; + Stat1_d bytes_per_second_stat; + Stat1_d items_per_second_stat; + // All repetitions should be run with the same number of iterations so we + // can take this information from the first benchmark. + int64_t const run_iterations = reports.front().iterations; + + // Populate the accumulators. + for (Run const& run : reports) { + CHECK_EQ(reports[0].benchmark_name, run.benchmark_name); + CHECK_EQ(run_iterations, run.iterations); + real_accumulated_time_stat += + Stat1_d(run.real_accumulated_time/run.iterations, run.iterations); + cpu_accumulated_time_stat += + Stat1_d(run.cpu_accumulated_time/run.iterations, run.iterations); + items_per_second_stat += Stat1_d(run.items_per_second, run.iterations); + bytes_per_second_stat += Stat1_d(run.bytes_per_second, run.iterations); + } + + // Get the data from the accumulator to BenchmarkReporter::Run's. + mean_data->benchmark_name = reports[0].benchmark_name + "_mean"; + mean_data->iterations = run_iterations; + mean_data->real_accumulated_time = real_accumulated_time_stat.Mean() * + run_iterations; + mean_data->cpu_accumulated_time = cpu_accumulated_time_stat.Mean() * + run_iterations; + mean_data->bytes_per_second = bytes_per_second_stat.Mean(); + mean_data->items_per_second = items_per_second_stat.Mean(); + + // Only add label to mean/stddev if it is same for all runs + mean_data->report_label = reports[0].report_label; + for (std::size_t i = 1; i < reports.size(); i++) { + if (reports[i].report_label != reports[0].report_label) { + mean_data->report_label = ""; + break; + } + } + + stddev_data->benchmark_name = reports[0].benchmark_name + "_stddev"; + stddev_data->report_label = mean_data->report_label; + stddev_data->iterations = 0; + stddev_data->real_accumulated_time = + real_accumulated_time_stat.StdDev(); + stddev_data->cpu_accumulated_time = + cpu_accumulated_time_stat.StdDev(); + stddev_data->bytes_per_second = bytes_per_second_stat.StdDev(); + stddev_data->items_per_second = items_per_second_stat.StdDev(); +} + +void BenchmarkReporter::Finalize() { +} + +BenchmarkReporter::~BenchmarkReporter() { +} + +} // end namespace benchmark diff --git a/thirdparty/google-benchmark/src/sleep.cc b/thirdparty/google-benchmark/src/sleep.cc new file mode 100644 index 00000000..918abc48 --- /dev/null +++ b/thirdparty/google-benchmark/src/sleep.cc @@ -0,0 +1,50 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "sleep.h" + +#include +#include + +#include "internal_macros.h" + +#ifdef BENCHMARK_OS_WINDOWS +#include +#endif + +namespace benchmark { +#ifdef BENCHMARK_OS_WINDOWS +// Window's Sleep takes milliseconds argument. +void SleepForMilliseconds(int milliseconds) { Sleep(milliseconds); } +void SleepForSeconds(double seconds) { + SleepForMilliseconds(static_cast(kNumMillisPerSecond * seconds)); +} +#else // BENCHMARK_OS_WINDOWS +void SleepForMicroseconds(int microseconds) { + struct timespec sleep_time; + sleep_time.tv_sec = microseconds / kNumMicrosPerSecond; + sleep_time.tv_nsec = (microseconds % kNumMicrosPerSecond) * kNumNanosPerMicro; + while (nanosleep(&sleep_time, &sleep_time) != 0 && errno == EINTR) + ; // Ignore signals and wait for the full interval to elapse. +} + +void SleepForMilliseconds(int milliseconds) { + SleepForMicroseconds(static_cast(milliseconds) * kNumMicrosPerMilli); +} + +void SleepForSeconds(double seconds) { + SleepForMicroseconds(static_cast(seconds * kNumMicrosPerSecond)); +} +#endif // BENCHMARK_OS_WINDOWS +} // end namespace benchmark diff --git a/thirdparty/google-benchmark/src/sleep.h b/thirdparty/google-benchmark/src/sleep.h new file mode 100644 index 00000000..f1e515ca --- /dev/null +++ b/thirdparty/google-benchmark/src/sleep.h @@ -0,0 +1,17 @@ +#ifndef BENCHMARK_SLEEP_H_ +#define BENCHMARK_SLEEP_H_ + +#include + +namespace benchmark { +const int64_t kNumMillisPerSecond = 1000LL; +const int64_t kNumMicrosPerMilli = 1000LL; +const int64_t kNumMicrosPerSecond = kNumMillisPerSecond * 1000LL; +const int64_t kNumNanosPerMicro = 1000LL; +const int64_t kNumNanosPerSecond = kNumNanosPerMicro * kNumMicrosPerSecond; + +void SleepForMilliseconds(int milliseconds); +void SleepForSeconds(double seconds); +} // end namespace benchmark + +#endif // BENCHMARK_SLEEP_H_ diff --git a/thirdparty/google-benchmark/src/stat.h b/thirdparty/google-benchmark/src/stat.h new file mode 100644 index 00000000..c4ecfe8e --- /dev/null +++ b/thirdparty/google-benchmark/src/stat.h @@ -0,0 +1,307 @@ +#ifndef BENCHMARK_STAT_H_ +#define BENCHMARK_STAT_H_ + +#include +#include +#include +#include + + +namespace benchmark { + +template +class Stat1; + +template +class Stat1MinMax; + +typedef Stat1 Stat1_f; +typedef Stat1 Stat1_d; +typedef Stat1MinMax Stat1MinMax_f; +typedef Stat1MinMax Stat1MinMax_d; + +template +class Vector2; +template +class Vector3; +template +class Vector4; + +template +class Stat1 { + public: + typedef Stat1 Self; + + Stat1() { Clear(); } + // Create a sample of value dat and weight 1 + explicit Stat1(const VType &dat) { + sum_ = dat; + sum_squares_ = Sqr(dat); + numsamples_ = 1; + } + // Create statistics for all the samples between begin (included) + // and end(excluded) + explicit Stat1(const VType *begin, const VType *end) { + Clear(); + for (const VType *item = begin; item < end; ++item) { + (*this) += Stat1(*item); + } + } + // Create a sample of value dat and weight w + Stat1(const VType &dat, const NumType &w) { + sum_ = w * dat; + sum_squares_ = w * Sqr(dat); + numsamples_ = w; + } + // Copy operator + Stat1(const Self &stat) { + sum_ = stat.sum_; + sum_squares_ = stat.sum_squares_; + numsamples_ = stat.numsamples_; + } + + void Clear() { + numsamples_ = NumType(); + sum_squares_ = sum_ = VType(); + } + + Self &operator=(const Self &stat) { + sum_ = stat.sum_; + sum_squares_ = stat.sum_squares_; + numsamples_ = stat.numsamples_; + return (*this); + } + // Merge statistics from two sample sets. + Self &operator+=(const Self &stat) { + sum_ += stat.sum_; + sum_squares_ += stat.sum_squares_; + numsamples_ += stat.numsamples_; + return (*this); + } + // The operation opposite to += + Self &operator-=(const Self &stat) { + sum_ -= stat.sum_; + sum_squares_ -= stat.sum_squares_; + numsamples_ -= stat.numsamples_; + return (*this); + } + // Multiply the weight of the set of samples by a factor k + Self &operator*=(const VType &k) { + sum_ *= k; + sum_squares_ *= k; + numsamples_ *= k; + return (*this); + } + + // Merge statistics from two sample sets. + Self operator+(const Self &stat) const { return Self(*this) += stat; } + + // The operation opposite to + + Self operator-(const Self &stat) const { return Self(*this) -= stat; } + + // Multiply the weight of the set of samples by a factor k + Self operator*(const VType &k) const { return Self(*this) *= k; } + + // Return the total weight of this sample set + NumType numSamples() const { return numsamples_; } + + // Return the sum of this sample set + VType Sum() const { return sum_; } + + // Return the mean of this sample set + VType Mean() const { + if (numsamples_ == 0) return VType(); + return sum_ * (1.0 / numsamples_); + } + + // Return the mean of this sample set and compute the standard deviation at + // the same time. + VType Mean(VType *stddev) const { + if (numsamples_ == 0) return VType(); + VType mean = sum_ * (1.0 / numsamples_); + if (stddev) { + VType avg_squares = sum_squares_ * (1.0 / numsamples_); + *stddev = Sqrt(avg_squares - Sqr(mean)); + } + return mean; + } + + // Return the standard deviation of the sample set + VType StdDev() const { + if (numsamples_ == 0) return VType(); + VType mean = Mean(); + VType avg_squares = sum_squares_ * (1.0 / numsamples_); + return Sqrt(avg_squares - Sqr(mean)); + } + + private: + static_assert(std::is_integral::value && + !std::is_same::value, + "NumType must be an integral type that is not bool."); + // Let i be the index of the samples provided (using +=) + // and weight[i],value[i] be the data of sample #i + // then the variables have the following meaning: + NumType numsamples_; // sum of weight[i]; + VType sum_; // sum of weight[i]*value[i]; + VType sum_squares_; // sum of weight[i]*value[i]^2; + + // Template function used to square a number. + // For a vector we square all components + template + static inline SType Sqr(const SType &dat) { + return dat * dat; + } + + template + static inline Vector2 Sqr(const Vector2 &dat) { + return dat.MulComponents(dat); + } + + template + static inline Vector3 Sqr(const Vector3 &dat) { + return dat.MulComponents(dat); + } + + template + static inline Vector4 Sqr(const Vector4 &dat) { + return dat.MulComponents(dat); + } + + // Template function used to take the square root of a number. + // For a vector we square all components + template + static inline SType Sqrt(const SType &dat) { + // Avoid NaN due to imprecision in the calculations + if (dat < 0) return 0; + return sqrt(dat); + } + + template + static inline Vector2 Sqrt(const Vector2 &dat) { + // Avoid NaN due to imprecision in the calculations + return Max(dat, Vector2()).Sqrt(); + } + + template + static inline Vector3 Sqrt(const Vector3 &dat) { + // Avoid NaN due to imprecision in the calculations + return Max(dat, Vector3()).Sqrt(); + } + + template + static inline Vector4 Sqrt(const Vector4 &dat) { + // Avoid NaN due to imprecision in the calculations + return Max(dat, Vector4()).Sqrt(); + } +}; + +// Useful printing function +template +std::ostream &operator<<(std::ostream &out, const Stat1 &s) { + out << "{ avg = " << s.Mean() << " std = " << s.StdDev() + << " nsamples = " << s.NumSamples() << "}"; + return out; +} + +// Stat1MinMax: same as Stat1, but it also +// keeps the Min and Max values; the "-" +// operator is disabled because it cannot be implemented +// efficiently +template +class Stat1MinMax : public Stat1 { + public: + typedef Stat1MinMax Self; + + Stat1MinMax() { Clear(); } + // Create a sample of value dat and weight 1 + explicit Stat1MinMax(const VType &dat) : Stat1(dat) { + max_ = dat; + min_ = dat; + } + // Create statistics for all the samples between begin (included) + // and end(excluded) + explicit Stat1MinMax(const VType *begin, const VType *end) { + Clear(); + for (const VType *item = begin; item < end; ++item) { + (*this) += Stat1MinMax(*item); + } + } + // Create a sample of value dat and weight w + Stat1MinMax(const VType &dat, const NumType &w) + : Stat1(dat, w) { + max_ = dat; + min_ = dat; + } + // Copy operator + Stat1MinMax(const Self &stat) : Stat1(stat) { + max_ = stat.max_; + min_ = stat.min_; + } + + void Clear() { + Stat1::Clear(); + if (std::numeric_limits::has_infinity) { + min_ = std::numeric_limits::infinity(); + max_ = -std::numeric_limits::infinity(); + } else { + min_ = std::numeric_limits::max(); + max_ = std::numeric_limits::min(); + } + } + + Self &operator=(const Self &stat) { + this->Stat1::operator=(stat); + max_ = stat.max_; + min_ = stat.min_; + return (*this); + } + // Merge statistics from two sample sets. + Self &operator+=(const Self &stat) { + this->Stat1::operator+=(stat); + if (stat.max_ > max_) max_ = stat.max_; + if (stat.min_ < min_) min_ = stat.min_; + return (*this); + } + // Multiply the weight of the set of samples by a factor k + Self &operator*=(const VType &stat) { + this->Stat1::operator*=(stat); + return (*this); + } + // Merge statistics from two sample sets. + Self operator+(const Self &stat) const { return Self(*this) += stat; } + // Multiply the weight of the set of samples by a factor k + Self operator*(const VType &k) const { return Self(*this) *= k; } + + // Return the maximal value in this sample set + VType Max() const { return max_; } + // Return the minimal value in this sample set + VType Min() const { return min_; } + + private: + // The - operation makes no sense with Min/Max + // unless we keep the full list of values (but we don't) + // make it private, and let it undefined so nobody can call it + Self &operator-=(const Self &stat); // senseless. let it undefined. + + // The operation opposite to - + Self operator-(const Self &stat) const; // senseless. let it undefined. + + // Let i be the index of the samples provided (using +=) + // and weight[i],value[i] be the data of sample #i + // then the variables have the following meaning: + VType max_; // max of value[i] + VType min_; // min of value[i] +}; + +// Useful printing function +template +std::ostream &operator<<(std::ostream &out, + const Stat1MinMax &s) { + out << "{ avg = " << s.Mean() << " std = " << s.StdDev() + << " nsamples = " << s.NumSamples() << " min = " << s.Min() + << " max = " << s.Max() << "}"; + return out; +} +} // end namespace benchmark + +#endif // BENCHMARK_STAT_H_ diff --git a/thirdparty/google-benchmark/src/string_util.cc b/thirdparty/google-benchmark/src/string_util.cc new file mode 100644 index 00000000..30d13050 --- /dev/null +++ b/thirdparty/google-benchmark/src/string_util.cc @@ -0,0 +1,169 @@ +#include "string_util.h" + +#include +#include +#include +#include +#include +#include + +#include "arraysize.h" + +namespace benchmark { +namespace { + +// kilo, Mega, Giga, Tera, Peta, Exa, Zetta, Yotta. +const char kBigSIUnits[] = "kMGTPEZY"; +// Kibi, Mebi, Gibi, Tebi, Pebi, Exbi, Zebi, Yobi. +const char kBigIECUnits[] = "KMGTPEZY"; +// milli, micro, nano, pico, femto, atto, zepto, yocto. +const char kSmallSIUnits[] = "munpfazy"; + +// We require that all three arrays have the same size. +static_assert(arraysize(kBigSIUnits) == arraysize(kBigIECUnits), + "SI and IEC unit arrays must be the same size"); +static_assert(arraysize(kSmallSIUnits) == arraysize(kBigSIUnits), + "Small SI and Big SI unit arrays must be the same size"); + +static const int64_t kUnitsSize = arraysize(kBigSIUnits); + +} // end anonymous namespace + +void ToExponentAndMantissa(double val, double thresh, int precision, + double one_k, std::string* mantissa, + int64_t* exponent) { + std::stringstream mantissa_stream; + + if (val < 0) { + mantissa_stream << "-"; + val = -val; + } + + // Adjust threshold so that it never excludes things which can't be rendered + // in 'precision' digits. + const double adjusted_threshold = + std::max(thresh, 1.0 / std::pow(10.0, precision)); + const double big_threshold = adjusted_threshold * one_k; + const double small_threshold = adjusted_threshold; + + if (val > big_threshold) { + // Positive powers + double scaled = val; + for (size_t i = 0; i < arraysize(kBigSIUnits); ++i) { + scaled /= one_k; + if (scaled <= big_threshold) { + mantissa_stream << scaled; + *exponent = i + 1; + *mantissa = mantissa_stream.str(); + return; + } + } + mantissa_stream << val; + *exponent = 0; + } else if (val < small_threshold) { + // Negative powers + double scaled = val; + for (size_t i = 0; i < arraysize(kSmallSIUnits); ++i) { + scaled *= one_k; + if (scaled >= small_threshold) { + mantissa_stream << scaled; + *exponent = -static_cast(i + 1); + *mantissa = mantissa_stream.str(); + return; + } + } + mantissa_stream << val; + *exponent = 0; + } else { + mantissa_stream << val; + *exponent = 0; + } + *mantissa = mantissa_stream.str(); +} + +std::string ExponentToPrefix(int64_t exponent, bool iec) { + if (exponent == 0) return ""; + + const int64_t index = (exponent > 0 ? exponent - 1 : -exponent - 1); + if (index >= kUnitsSize) return ""; + + const char* array = + (exponent > 0 ? (iec ? kBigIECUnits : kBigSIUnits) : kSmallSIUnits); + if (iec) + return array[index] + std::string("i"); + else + return std::string(1, array[index]); +} + +std::string ToBinaryStringFullySpecified(double value, double threshold, + int precision) { + std::string mantissa; + int64_t exponent; + ToExponentAndMantissa(value, threshold, precision, 1024.0, &mantissa, + &exponent); + return mantissa + ExponentToPrefix(exponent, false); +} + +void AppendHumanReadable(int n, std::string* str) { + std::stringstream ss; + // Round down to the nearest SI prefix. + ss << "/" << ToBinaryStringFullySpecified(n, 1.0, 0); + *str += ss.str(); +} + +std::string HumanReadableNumber(double n) { + // 1.1 means that figures up to 1.1k should be shown with the next unit down; + // this softens edge effects. + // 1 means that we should show one decimal place of precision. + return ToBinaryStringFullySpecified(n, 1.1, 1); +} + +std::string StringPrintFImp(const char *msg, va_list args) +{ + // we might need a second shot at this, so pre-emptivly make a copy + va_list args_cp; + va_copy(args_cp, args); + + // TODO(ericwf): use std::array for first attempt to avoid one memory + // allocation guess what the size might be + std::array local_buff; + std::size_t size = local_buff.size(); + // 2015-10-08: vsnprintf is used instead of snd::vsnprintf due to a limitation in the android-ndk + auto ret = vsnprintf(local_buff.data(), size, msg, args_cp); + + va_end(args_cp); + + // handle empty expansion + if (ret == 0) + return std::string{}; + if (static_cast(ret) < size) + return std::string(local_buff.data()); + + // we did not provide a long enough buffer on our first attempt. + // add 1 to size to account for null-byte in size cast to prevent overflow + size = static_cast(ret) + 1; + auto buff_ptr = std::unique_ptr(new char[size]); + // 2015-10-08: vsnprintf is used instead of snd::vsnprintf due to a limitation in the android-ndk + ret = vsnprintf(buff_ptr.get(), size, msg, args); + return std::string(buff_ptr.get()); +} + +std::string StringPrintF(const char* format, ...) +{ + va_list args; + va_start(args, format); + std::string tmp = StringPrintFImp(format, args); + va_end(args); + return tmp; +} + +void ReplaceAll(std::string* str, const std::string& from, + const std::string& to) { + std::size_t start = 0; + while((start = str->find(from, start)) != std::string::npos) { + str->replace(start, from.length(), to); + start += to.length(); + } +} + +} // end namespace benchmark diff --git a/thirdparty/google-benchmark/src/string_util.h b/thirdparty/google-benchmark/src/string_util.h new file mode 100644 index 00000000..b89fef5f --- /dev/null +++ b/thirdparty/google-benchmark/src/string_util.h @@ -0,0 +1,44 @@ +#ifndef BENCHMARK_STRING_UTIL_H_ +#define BENCHMARK_STRING_UTIL_H_ + +#include +#include +#include +#include "internal_macros.h" + +namespace benchmark { + +void AppendHumanReadable(int n, std::string* str); + +std::string HumanReadableNumber(double n); + +std::string StringPrintF(const char* format, ...); + +inline std::ostream& +StringCatImp(std::ostream& out) BENCHMARK_NOEXCEPT +{ + return out; +} + +template +inline std::ostream& +StringCatImp(std::ostream& out, First&& f, Rest&&... rest) +{ + out << std::forward(f); + return StringCatImp(out, std::forward(rest)...); +} + +template +inline std::string StrCat(Args&&... args) +{ + std::ostringstream ss; + StringCatImp(ss, std::forward(args)...); + return ss.str(); +} + +void ReplaceAll(std::string* str, const std::string& from, + const std::string& to); + +} // end namespace benchmark + +#endif // BENCHMARK_STRING_UTIL_H_ diff --git a/thirdparty/google-benchmark/src/sysinfo.cc b/thirdparty/google-benchmark/src/sysinfo.cc new file mode 100644 index 00000000..d1f31202 --- /dev/null +++ b/thirdparty/google-benchmark/src/sysinfo.cc @@ -0,0 +1,416 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "sysinfo.h" +#include "internal_macros.h" + +#ifdef BENCHMARK_OS_WINDOWS +#include +#include +#include +#else +#include +#include +#include // this header must be included before 'sys/sysctl.h' to avoid compilation error on FreeBSD +#include +#include +#if defined BENCHMARK_OS_FREEBSD || defined BENCHMARK_OS_MACOSX +#include +#endif +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "arraysize.h" +#include "check.h" +#include "cycleclock.h" +#include "internal_macros.h" +#include "log.h" +#include "sleep.h" +#include "string_util.h" + +namespace benchmark { +namespace { +std::once_flag cpuinfo_init; +double cpuinfo_cycles_per_second = 1.0; +int cpuinfo_num_cpus = 1; // Conservative guess +std::mutex cputimens_mutex; + +#if !defined BENCHMARK_OS_MACOSX +const int64_t estimate_time_ms = 1000; + +// Helper function estimates cycles/sec by observing cycles elapsed during +// sleep(). Using small sleep time decreases accuracy significantly. +int64_t EstimateCyclesPerSecond() { + const int64_t start_ticks = cycleclock::Now(); + SleepForMilliseconds(estimate_time_ms); + return cycleclock::Now() - start_ticks; +} +#endif + +#if defined BENCHMARK_OS_LINUX || defined BENCHMARK_OS_CYGWIN +// Helper function for reading an int from a file. Returns true if successful +// and the memory location pointed to by value is set to the value read. +bool ReadIntFromFile(const char* file, long* value) { + bool ret = false; + int fd = open(file, O_RDONLY); + if (fd != -1) { + char line[1024]; + char* err; + memset(line, '\0', sizeof(line)); + CHECK(read(fd, line, sizeof(line) - 1)); + const long temp_value = strtol(line, &err, 10); + if (line[0] != '\0' && (*err == '\n' || *err == '\0')) { + *value = temp_value; + ret = true; + } + close(fd); + } + return ret; +} +#endif + +void InitializeSystemInfo() { +#if defined BENCHMARK_OS_LINUX || defined BENCHMARK_OS_CYGWIN + char line[1024]; + char* err; + long freq; + + bool saw_mhz = false; + + // If the kernel is exporting the tsc frequency use that. There are issues + // where cpuinfo_max_freq cannot be relied on because the BIOS may be + // exporintg an invalid p-state (on x86) or p-states may be used to put the + // processor in a new mode (turbo mode). Essentially, those frequencies + // cannot always be relied upon. The same reasons apply to /proc/cpuinfo as + // well. + if (!saw_mhz && + ReadIntFromFile("/sys/devices/system/cpu/cpu0/tsc_freq_khz", &freq)) { + // The value is in kHz (as the file name suggests). For example, on a + // 2GHz warpstation, the file contains the value "2000000". + cpuinfo_cycles_per_second = freq * 1000.0; + saw_mhz = true; + } + + // If CPU scaling is in effect, we want to use the *maximum* frequency, + // not whatever CPU speed some random processor happens to be using now. + if (!saw_mhz && + ReadIntFromFile("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", + &freq)) { + // The value is in kHz. For example, on a 2GHz warpstation, the file + // contains the value "2000000". + cpuinfo_cycles_per_second = freq * 1000.0; + saw_mhz = true; + } + + // Read /proc/cpuinfo for other values, and if there is no cpuinfo_max_freq. + const char* pname = "/proc/cpuinfo"; + int fd = open(pname, O_RDONLY); + if (fd == -1) { + perror(pname); + if (!saw_mhz) { + cpuinfo_cycles_per_second = static_cast(EstimateCyclesPerSecond()); + } + return; + } + + double bogo_clock = 1.0; + bool saw_bogo = false; + long max_cpu_id = 0; + int num_cpus = 0; + line[0] = line[1] = '\0'; + size_t chars_read = 0; + do { // we'll exit when the last read didn't read anything + // Move the next line to the beginning of the buffer + const size_t oldlinelen = strlen(line); + if (sizeof(line) == oldlinelen + 1) // oldlinelen took up entire line + line[0] = '\0'; + else // still other lines left to save + memmove(line, line + oldlinelen + 1, sizeof(line) - (oldlinelen + 1)); + // Terminate the new line, reading more if we can't find the newline + char* newline = strchr(line, '\n'); + if (newline == nullptr) { + const size_t linelen = strlen(line); + const size_t bytes_to_read = sizeof(line) - 1 - linelen; + CHECK(bytes_to_read > 0); // because the memmove recovered >=1 bytes + chars_read = read(fd, line + linelen, bytes_to_read); + line[linelen + chars_read] = '\0'; + newline = strchr(line, '\n'); + } + if (newline != nullptr) *newline = '\0'; + + // When parsing the "cpu MHz" and "bogomips" (fallback) entries, we only + // accept postive values. Some environments (virtual machines) report zero, + // which would cause infinite looping in WallTime_Init. + if (!saw_mhz && strncasecmp(line, "cpu MHz", sizeof("cpu MHz") - 1) == 0) { + const char* freqstr = strchr(line, ':'); + if (freqstr) { + cpuinfo_cycles_per_second = strtod(freqstr + 1, &err) * 1000000.0; + if (freqstr[1] != '\0' && *err == '\0' && cpuinfo_cycles_per_second > 0) + saw_mhz = true; + } + } else if (strncasecmp(line, "bogomips", sizeof("bogomips") - 1) == 0) { + const char* freqstr = strchr(line, ':'); + if (freqstr) { + bogo_clock = strtod(freqstr + 1, &err) * 1000000.0; + if (freqstr[1] != '\0' && *err == '\0' && bogo_clock > 0) + saw_bogo = true; + } + } else if (strncasecmp(line, "processor", sizeof("processor") - 1) == 0) { + num_cpus++; // count up every time we see an "processor :" entry + const char* freqstr = strchr(line, ':'); + if (freqstr) { + const long cpu_id = strtol(freqstr + 1, &err, 10); + if (freqstr[1] != '\0' && *err == '\0' && max_cpu_id < cpu_id) + max_cpu_id = cpu_id; + } + } + } while (chars_read > 0); + close(fd); + + if (!saw_mhz) { + if (saw_bogo) { + // If we didn't find anything better, we'll use bogomips, but + // we're not happy about it. + cpuinfo_cycles_per_second = bogo_clock; + } else { + // If we don't even have bogomips, we'll use the slow estimation. + cpuinfo_cycles_per_second = static_cast(EstimateCyclesPerSecond()); + } + } + if (num_cpus == 0) { + fprintf(stderr, "Failed to read num. CPUs correctly from /proc/cpuinfo\n"); + } else { + if ((max_cpu_id + 1) != num_cpus) { + fprintf(stderr, + "CPU ID assignments in /proc/cpuinfo seems messed up." + " This is usually caused by a bad BIOS.\n"); + } + cpuinfo_num_cpus = num_cpus; + } + +#elif defined BENCHMARK_OS_FREEBSD +// For this sysctl to work, the machine must be configured without +// SMP, APIC, or APM support. hz should be 64-bit in freebsd 7.0 +// and later. Before that, it's a 32-bit quantity (and gives the +// wrong answer on machines faster than 2^32 Hz). See +// http://lists.freebsd.org/pipermail/freebsd-i386/2004-November/001846.html +// But also compare FreeBSD 7.0: +// http://fxr.watson.org/fxr/source/i386/i386/tsc.c?v=RELENG70#L223 +// 231 error = sysctl_handle_quad(oidp, &freq, 0, req); +// To FreeBSD 6.3 (it's the same in 6-STABLE): +// http://fxr.watson.org/fxr/source/i386/i386/tsc.c?v=RELENG6#L131 +// 139 error = sysctl_handle_int(oidp, &freq, sizeof(freq), req); +#if __FreeBSD__ >= 7 + uint64_t hz = 0; +#else + unsigned int hz = 0; +#endif + size_t sz = sizeof(hz); + const char* sysctl_path = "machdep.tsc_freq"; + if (sysctlbyname(sysctl_path, &hz, &sz, nullptr, 0) != 0) { + fprintf(stderr, "Unable to determine clock rate from sysctl: %s: %s\n", + sysctl_path, strerror(errno)); + cpuinfo_cycles_per_second = static_cast(EstimateCyclesPerSecond()); + } else { + cpuinfo_cycles_per_second = hz; + } +// TODO: also figure out cpuinfo_num_cpus + +#elif defined BENCHMARK_OS_WINDOWS + // In NT, read MHz from the registry. If we fail to do so or we're in win9x + // then make a crude estimate. + DWORD data, data_size = sizeof(data); + if (IsWindowsXPOrGreater() && + SUCCEEDED( + SHGetValueA(HKEY_LOCAL_MACHINE, + "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", + "~MHz", nullptr, &data, &data_size))) + cpuinfo_cycles_per_second = static_cast((int64_t)data * (int64_t)(1000 * 1000)); // was mhz + else + cpuinfo_cycles_per_second = static_cast(EstimateCyclesPerSecond()); +// TODO: also figure out cpuinfo_num_cpus + +#elif defined BENCHMARK_OS_MACOSX + // returning "mach time units" per second. the current number of elapsed + // mach time units can be found by calling uint64 mach_absolute_time(); + // while not as precise as actual CPU cycles, it is accurate in the face + // of CPU frequency scaling and multi-cpu/core machines. + // Our mac users have these types of machines, and accuracy + // (i.e. correctness) trumps precision. + // See cycleclock.h: CycleClock::Now(), which returns number of mach time + // units on Mac OS X. + mach_timebase_info_data_t timebase_info; + mach_timebase_info(&timebase_info); + double mach_time_units_per_nanosecond = + static_cast(timebase_info.denom) / + static_cast(timebase_info.numer); + cpuinfo_cycles_per_second = mach_time_units_per_nanosecond * 1e9; + + int num_cpus = 0; + size_t size = sizeof(num_cpus); + int numcpus_name[] = {CTL_HW, HW_NCPU}; + if (::sysctl(numcpus_name, arraysize(numcpus_name), &num_cpus, &size, nullptr, 0) == + 0 && + (size == sizeof(num_cpus))) + cpuinfo_num_cpus = num_cpus; + +#else + // Generic cycles per second counter + cpuinfo_cycles_per_second = static_cast(EstimateCyclesPerSecond()); +#endif +} +} // end namespace + +// getrusage() based implementation of MyCPUUsage +static double MyCPUUsageRUsage() { +#ifndef BENCHMARK_OS_WINDOWS + struct rusage ru; + if (getrusage(RUSAGE_SELF, &ru) == 0) { + return (static_cast(ru.ru_utime.tv_sec) + + static_cast(ru.ru_utime.tv_usec) * 1e-6 + + static_cast(ru.ru_stime.tv_sec) + + static_cast(ru.ru_stime.tv_usec) * 1e-6); + } else { + return 0.0; + } +#else + HANDLE proc = GetCurrentProcess(); + FILETIME creation_time; + FILETIME exit_time; + FILETIME kernel_time; + FILETIME user_time; + ULARGE_INTEGER kernel; + ULARGE_INTEGER user; + GetProcessTimes(proc, &creation_time, &exit_time, &kernel_time, &user_time); + kernel.HighPart = kernel_time.dwHighDateTime; + kernel.LowPart = kernel_time.dwLowDateTime; + user.HighPart = user_time.dwHighDateTime; + user.LowPart = user_time.dwLowDateTime; + return (static_cast(kernel.QuadPart) + + static_cast(user.QuadPart)) * 1e-7; +#endif // OS_WINDOWS +} + +#ifndef BENCHMARK_OS_WINDOWS +static bool MyCPUUsageCPUTimeNsLocked(double* cputime) { + static int cputime_fd = -1; + if (cputime_fd == -1) { + cputime_fd = open("/proc/self/cputime_ns", O_RDONLY); + if (cputime_fd < 0) { + cputime_fd = -1; + return false; + } + } + char buff[64]; + memset(buff, 0, sizeof(buff)); + if (pread(cputime_fd, buff, sizeof(buff) - 1, 0) <= 0) { + close(cputime_fd); + cputime_fd = -1; + return false; + } + unsigned long long result = strtoull(buff, nullptr, 0); + if (result == (std::numeric_limits::max)()) { + close(cputime_fd); + cputime_fd = -1; + return false; + } + *cputime = static_cast(result) / 1e9; + return true; +} +#endif // OS_WINDOWS + +double MyCPUUsage() { +#ifndef BENCHMARK_OS_WINDOWS + { + std::lock_guard l(cputimens_mutex); + static bool use_cputime_ns = true; + if (use_cputime_ns) { + double value; + if (MyCPUUsageCPUTimeNsLocked(&value)) { + return value; + } + // Once MyCPUUsageCPUTimeNsLocked fails once fall back to getrusage(). + VLOG(1) << "Reading /proc/self/cputime_ns failed. Using getrusage().\n"; + use_cputime_ns = false; + } + } +#endif // OS_WINDOWS + return MyCPUUsageRUsage(); +} + +double ChildrenCPUUsage() { +#ifndef BENCHMARK_OS_WINDOWS + struct rusage ru; + if (getrusage(RUSAGE_CHILDREN, &ru) == 0) { + return (static_cast(ru.ru_utime.tv_sec) + + static_cast(ru.ru_utime.tv_usec) * 1e-6 + + static_cast(ru.ru_stime.tv_sec) + + static_cast(ru.ru_stime.tv_usec) * 1e-6); + } else { + return 0.0; + } +#else + // TODO: Not sure what this even means on Windows + return 0.0; +#endif // OS_WINDOWS +} + +double CyclesPerSecond(void) { + std::call_once(cpuinfo_init, InitializeSystemInfo); + return cpuinfo_cycles_per_second; +} + +int NumCPUs(void) { + std::call_once(cpuinfo_init, InitializeSystemInfo); + return cpuinfo_num_cpus; +} + +// The ""'s catch people who don't pass in a literal for "str" +#define strliterallen(str) (sizeof("" str "") - 1) + +// Must use a string literal for prefix. +#define memprefix(str, len, prefix) \ + ((((len) >= strliterallen(prefix)) && \ + std::memcmp(str, prefix, strliterallen(prefix)) == 0) \ + ? str + strliterallen(prefix) \ + : nullptr) + +bool CpuScalingEnabled() { +#ifndef BENCHMARK_OS_WINDOWS + // On Linux, the CPUfreq subsystem exposes CPU information as files on the + // local file system. If reading the exported files fails, then we may not be + // running on Linux, so we silently ignore all the read errors. + for (int cpu = 0, num_cpus = NumCPUs(); cpu < num_cpus; ++cpu) { + std::string governor_file = StrCat("/sys/devices/system/cpu/cpu", cpu, + "/cpufreq/scaling_governor"); + FILE* file = fopen(governor_file.c_str(), "r"); + if (!file) break; + char buff[16]; + size_t bytes_read = fread(buff, 1, sizeof(buff), file); + fclose(file); + if (memprefix(buff, bytes_read, "performance") == nullptr) return true; + } +#endif + return false; +} + +} // end namespace benchmark diff --git a/thirdparty/google-benchmark/src/sysinfo.h b/thirdparty/google-benchmark/src/sysinfo.h new file mode 100644 index 00000000..eaf77e07 --- /dev/null +++ b/thirdparty/google-benchmark/src/sysinfo.h @@ -0,0 +1,12 @@ +#ifndef BENCHMARK_SYSINFO_H_ +#define BENCHMARK_SYSINFO_H_ + +namespace benchmark { +double MyCPUUsage(); +double ChildrenCPUUsage(); +int NumCPUs(); +double CyclesPerSecond(); +bool CpuScalingEnabled(); +} // end namespace benchmark + +#endif // BENCHMARK_SYSINFO_H_ diff --git a/thirdparty/google-benchmark/src/walltime.cc b/thirdparty/google-benchmark/src/walltime.cc new file mode 100644 index 00000000..4bdbaa59 --- /dev/null +++ b/thirdparty/google-benchmark/src/walltime.cc @@ -0,0 +1,263 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "benchmark/macros.h" +#include "internal_macros.h" +#include "walltime.h" + +#if defined(BENCHMARK_OS_WINDOWS) +#include +#include // for timeval +#else +#include +#endif + +#include +#include +#include +#include + +#include +#include +#include + +#include "arraysize.h" +#include "check.h" +#include "cycleclock.h" +#include "log.h" +#include "sysinfo.h" + +namespace benchmark { +namespace walltime { + +namespace { + +#if defined(HAVE_STEADY_CLOCK) +template +struct ChooseSteadyClock { + typedef std::chrono::high_resolution_clock type; +}; + +template <> +struct ChooseSteadyClock { + typedef std::chrono::steady_clock type; +}; +#endif + +struct ChooseClockType { +#if defined(HAVE_STEADY_CLOCK) + typedef ChooseSteadyClock<>::type type; +#else + typedef std::chrono::high_resolution_clock type; +#endif +}; + +class WallTimeImp +{ +public: + WallTime Now(); + + static WallTimeImp& GetWallTimeImp() { + static WallTimeImp* imp = new WallTimeImp(); + return *imp; + } + +private: + WallTimeImp(); + // Helper routines to load/store a float from an AtomicWord. Required because + // g++ < 4.7 doesn't support std::atomic correctly. I cannot wait to + // get rid of this horror show. + void SetDrift(float f) { + int32_t w; + memcpy(&w, &f, sizeof(f)); + std::atomic_store(&drift_adjust_, w); + } + + float GetDrift() const { + float f; + int32_t w = std::atomic_load(&drift_adjust_); + memcpy(&f, &w, sizeof(f)); + return f; + } + + WallTime Slow() const { + struct timeval tv; +#if defined(BENCHMARK_OS_WINDOWS) + FILETIME file_time; + SYSTEMTIME system_time; + ULARGE_INTEGER ularge; + const unsigned __int64 epoch = 116444736000000000LL; + + GetSystemTime(&system_time); + SystemTimeToFileTime(&system_time, &file_time); + ularge.LowPart = file_time.dwLowDateTime; + ularge.HighPart = file_time.dwHighDateTime; + + tv.tv_sec = (long)((ularge.QuadPart - epoch) / (10L * 1000 * 1000)); + tv.tv_usec = (long)(system_time.wMilliseconds * 1000); +#else + gettimeofday(&tv, nullptr); +#endif + return tv.tv_sec + tv.tv_usec * 1e-6; + } + +private: + static_assert(sizeof(float) <= sizeof(int32_t), + "type sizes don't allow the drift_adjust hack"); + + WallTime base_walltime_; + int64_t base_cycletime_; + int64_t cycles_per_second_; + double seconds_per_cycle_; + uint32_t last_adjust_time_; + std::atomic drift_adjust_; + int64_t max_interval_cycles_; + + BENCHMARK_DISALLOW_COPY_AND_ASSIGN(WallTimeImp); +}; + + +WallTime WallTimeImp::Now() { + WallTime now = 0.0; + WallTime result = 0.0; + int64_t ct = 0; + uint32_t top_bits = 0; + do { + ct = cycleclock::Now(); + int64_t cycle_delta = ct - base_cycletime_; + result = base_walltime_ + cycle_delta * seconds_per_cycle_; + + top_bits = static_cast(uint64_t(ct) >> 32); + // Recompute drift no more often than every 2^32 cycles. + // I.e., @2GHz, ~ every two seconds + if (top_bits == last_adjust_time_) { // don't need to recompute drift + return result + GetDrift(); + } + + now = Slow(); + } while (cycleclock::Now() - ct > max_interval_cycles_); + // We are now sure that "now" and "result" were produced within + // kMaxErrorInterval of one another. + + SetDrift(static_cast(now - result)); + last_adjust_time_ = top_bits; + return now; +} + + +WallTimeImp::WallTimeImp() + : base_walltime_(0.0), base_cycletime_(0), + cycles_per_second_(0), seconds_per_cycle_(0.0), + last_adjust_time_(0), drift_adjust_(0), + max_interval_cycles_(0) { + const double kMaxErrorInterval = 100e-6; + cycles_per_second_ = static_cast(CyclesPerSecond()); + CHECK(cycles_per_second_ != 0); + seconds_per_cycle_ = 1.0 / cycles_per_second_; + max_interval_cycles_ = + static_cast(cycles_per_second_ * kMaxErrorInterval); + do { + base_cycletime_ = cycleclock::Now(); + base_walltime_ = Slow(); + } while (cycleclock::Now() - base_cycletime_ > max_interval_cycles_); + // We are now sure that "base_walltime" and "base_cycletime" were produced + // within kMaxErrorInterval of one another. + + SetDrift(0.0); + last_adjust_time_ = static_cast(uint64_t(base_cycletime_) >> 32); +} + +WallTime CPUWalltimeNow() { + static WallTimeImp& imp = WallTimeImp::GetWallTimeImp(); + return imp.Now(); +} + +WallTime ChronoWalltimeNow() { + typedef ChooseClockType::type Clock; + typedef std::chrono::duration + FPSeconds; + static_assert(std::chrono::treat_as_floating_point::value, + "This type must be treated as a floating point type."); + auto now = Clock::now().time_since_epoch(); + return std::chrono::duration_cast(now).count(); +} + +bool UseCpuCycleClock() { + bool useWallTime = !CpuScalingEnabled(); + if (useWallTime) { + VLOG(1) << "Using the CPU cycle clock to provide walltime::Now().\n"; + } else { + VLOG(1) << "Using std::chrono to provide walltime::Now().\n"; + } + return useWallTime; +} + + +} // end anonymous namespace + +// WallTimeImp doesn't work when CPU Scaling is enabled. If CPU Scaling is +// enabled at the start of the program then std::chrono::system_clock is used +// instead. +WallTime Now() +{ + static bool useCPUClock = UseCpuCycleClock(); + if (useCPUClock) { + return CPUWalltimeNow(); + } else { + return ChronoWalltimeNow(); + } +} + +} // end namespace walltime + + +namespace { + +std::string DateTimeString(bool local) { + typedef std::chrono::system_clock Clock; + std::time_t now = Clock::to_time_t(Clock::now()); + char storage[128]; + std::size_t written; + + if (local) { +#if defined(BENCHMARK_OS_WINDOWS) + written = std::strftime(storage, sizeof(storage), "%x %X", ::localtime(&now)); +#else + std::tm timeinfo; + std::memset(&timeinfo, 0, sizeof(std::tm)); + ::localtime_r(&now, &timeinfo); + written = std::strftime(storage, sizeof(storage), "%F %T", &timeinfo); +#endif + } else { +#if defined(BENCHMARK_OS_WINDOWS) + written = std::strftime(storage, sizeof(storage), "%x %X", ::gmtime(&now)); +#else + std::tm timeinfo; + std::memset(&timeinfo, 0, sizeof(std::tm)); + ::gmtime_r(&now, &timeinfo); + written = std::strftime(storage, sizeof(storage), "%F %T", &timeinfo); +#endif + } + CHECK(written < arraysize(storage)); + ((void)written); // prevent unused variable in optimized mode. + return std::string(storage); +} + +} // end namespace + +std::string LocalDateTimeString() { + return DateTimeString(true); +} + +} // end namespace benchmark diff --git a/thirdparty/google-benchmark/src/walltime.h b/thirdparty/google-benchmark/src/walltime.h new file mode 100644 index 00000000..38c26f33 --- /dev/null +++ b/thirdparty/google-benchmark/src/walltime.h @@ -0,0 +1,17 @@ +#ifndef BENCHMARK_WALLTIME_H_ +#define BENCHMARK_WALLTIME_H_ + +#include + +namespace benchmark { +typedef double WallTime; + +namespace walltime { +WallTime Now(); +} // end namespace walltime + +std::string LocalDateTimeString(); + +} // end namespace benchmark + +#endif // BENCHMARK_WALLTIME_H_ diff --git a/thirdparty/google-benchmark/test/CMakeLists.txt b/thirdparty/google-benchmark/test/CMakeLists.txt new file mode 100644 index 00000000..7e4f4854 --- /dev/null +++ b/thirdparty/google-benchmark/test/CMakeLists.txt @@ -0,0 +1,89 @@ +# Enable the tests + +find_package(Threads REQUIRED) + +set(CXX03_FLAGS "${CMAKE_CXX_FLAGS}") +string(REPLACE "-std=c++11" "-std=c++03" CXX03_FLAGS "${CXX03_FLAGS}") +string(REPLACE "-std=c++0x" "-std=c++03" CXX03_FLAGS "${CXX03_FLAGS}") + +macro(compile_benchmark_test name) + add_executable(${name} "${name}.cc") + target_link_libraries(${name} benchmark ${CMAKE_THREAD_LIBS_INIT}) +endmacro(compile_benchmark_test) + +# Demonstration executable +compile_benchmark_test(benchmark_test) +add_test(benchmark benchmark_test --benchmark_min_time=0.01) + +compile_benchmark_test(filter_test) +macro(add_filter_test name filter expect) + add_test(${name} filter_test --benchmark_min_time=0.01 --benchmark_filter=${filter} ${expect}) +endmacro(add_filter_test) + +add_filter_test(filter_simple "Foo" 3) +add_filter_test(filter_suffix "BM_.*" 4) +add_filter_test(filter_regex_all ".*" 5) +add_filter_test(filter_regex_blank "" 5) +add_filter_test(filter_regex_none "monkey" 0) +add_filter_test(filter_regex_wildcard ".*Foo.*" 3) +add_filter_test(filter_regex_begin "^BM_.*" 4) +add_filter_test(filter_regex_begin2 "^N" 1) +add_filter_test(filter_regex_end ".*Ba$" 1) + +compile_benchmark_test(options_test) +add_test(options_benchmarks options_test --benchmark_min_time=0.01) + +compile_benchmark_test(basic_test) +add_test(basic_benchmark basic_test --benchmark_min_time=0.01) + +compile_benchmark_test(fixture_test) +add_test(fixture_test fixture_test --benchmark_min_time=0.01) + +compile_benchmark_test(cxx03_test) +set_target_properties(cxx03_test + PROPERTIES COMPILE_FLAGS "${CXX03_FLAGS}") +add_test(cxx03 cxx03_test --benchmark_min_time=0.01) + +# Add the coverage command(s) +if(CMAKE_BUILD_TYPE) + string(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_LOWER) +endif() +if (${CMAKE_BUILD_TYPE_LOWER} MATCHES "coverage") + find_program(GCOV gcov) + find_program(LCOV lcov) + find_program(GENHTML genhtml) + find_program(CTEST ctest) + if (GCOV AND LCOV AND GENHTML AND CTEST AND HAVE_CXX_FLAG_COVERAGE) + add_custom_command( + OUTPUT ${CMAKE_BINARY_DIR}/lcov/index.html + COMMAND ${LCOV} -q -z -d . + COMMAND ${LCOV} -q --no-external -c -b "${CMAKE_SOURCE_DIR}" -d . -o before.lcov -i + COMMAND ${CTEST} --force-new-ctest-process + COMMAND ${LCOV} -q --no-external -c -b "${CMAKE_SOURCE_DIR}" -d . -o after.lcov + COMMAND ${LCOV} -q -a before.lcov -a after.lcov --output-file final.lcov + COMMAND ${LCOV} -q -r final.lcov "'${CMAKE_SOURCE_DIR}/test/*'" -o final.lcov + COMMAND ${GENHTML} final.lcov -o lcov --demangle-cpp --sort -p "${CMAKE_BINARY_DIR}" -t benchmark + DEPENDS filter_test benchmark_test options_test basic_test fixture_test cxx03_test + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Running LCOV" + ) + add_custom_target(coverage + DEPENDS ${CMAKE_BINARY_DIR}/lcov/index.html + COMMENT "LCOV report at lcov/index.html" + ) + message(STATUS "Coverage command added") + else() + if (HAVE_CXX_FLAG_COVERAGE) + set(CXX_FLAG_COVERAGE_MESSAGE supported) + else() + set(CXX_FLAG_COVERAGE_MESSAGE unavailable) + endif() + message(WARNING + "Coverage not available:\n" + " gcov: ${GCOV}\n" + " lcov: ${LCOV}\n" + " genhtml: ${GENHTML}\n" + " ctest: ${CTEST}\n" + " --coverage flag: ${CXX_FLAG_COVERAGE_MESSAGE}") + endif() +endif() diff --git a/thirdparty/google-benchmark/test/basic_test.cc b/thirdparty/google-benchmark/test/basic_test.cc new file mode 100644 index 00000000..34354154 --- /dev/null +++ b/thirdparty/google-benchmark/test/basic_test.cc @@ -0,0 +1,102 @@ + +#include "benchmark/benchmark_api.h" + +#define BASIC_BENCHMARK_TEST(x) \ + BENCHMARK(x)->Arg(8)->Arg(512)->Arg(8192) + +void BM_empty(benchmark::State& state) { + while (state.KeepRunning()) { + benchmark::DoNotOptimize(state.iterations()); + } +} +BENCHMARK(BM_empty); +BENCHMARK(BM_empty)->ThreadPerCpu(); + +void BM_spin_empty(benchmark::State& state) { + while (state.KeepRunning()) { + for (int x = 0; x < state.range_x(); ++x) { + benchmark::DoNotOptimize(x); + } + } +} +BASIC_BENCHMARK_TEST(BM_spin_empty); +BASIC_BENCHMARK_TEST(BM_spin_empty)->ThreadPerCpu(); + +void BM_spin_pause_before(benchmark::State& state) { + for (int i = 0; i < state.range_x(); ++i) { + benchmark::DoNotOptimize(i); + } + while(state.KeepRunning()) { + for (int i = 0; i < state.range_x(); ++i) { + benchmark::DoNotOptimize(i); + } + } +} +BASIC_BENCHMARK_TEST(BM_spin_pause_before); +BASIC_BENCHMARK_TEST(BM_spin_pause_before)->ThreadPerCpu(); + + +void BM_spin_pause_during(benchmark::State& state) { + while(state.KeepRunning()) { + state.PauseTiming(); + for (int i = 0; i < state.range_x(); ++i) { + benchmark::DoNotOptimize(i); + } + state.ResumeTiming(); + for (int i = 0; i < state.range_x(); ++i) { + benchmark::DoNotOptimize(i); + } + } +} +BASIC_BENCHMARK_TEST(BM_spin_pause_during); +BASIC_BENCHMARK_TEST(BM_spin_pause_during)->ThreadPerCpu(); + +void BM_pause_during(benchmark::State& state) { + while(state.KeepRunning()) { + state.PauseTiming(); + state.ResumeTiming(); + } +} +BENCHMARK(BM_pause_during); +BENCHMARK(BM_pause_during)->ThreadPerCpu(); +BENCHMARK(BM_pause_during)->UseRealTime(); +BENCHMARK(BM_pause_during)->UseRealTime()->ThreadPerCpu(); + +void BM_spin_pause_after(benchmark::State& state) { + while(state.KeepRunning()) { + for (int i = 0; i < state.range_x(); ++i) { + benchmark::DoNotOptimize(i); + } + } + for (int i = 0; i < state.range_x(); ++i) { + benchmark::DoNotOptimize(i); + } +} +BASIC_BENCHMARK_TEST(BM_spin_pause_after); +BASIC_BENCHMARK_TEST(BM_spin_pause_after)->ThreadPerCpu(); + + +void BM_spin_pause_before_and_after(benchmark::State& state) { + for (int i = 0; i < state.range_x(); ++i) { + benchmark::DoNotOptimize(i); + } + while(state.KeepRunning()) { + for (int i = 0; i < state.range_x(); ++i) { + benchmark::DoNotOptimize(i); + } + } + for (int i = 0; i < state.range_x(); ++i) { + benchmark::DoNotOptimize(i); + } +} +BASIC_BENCHMARK_TEST(BM_spin_pause_before_and_after); +BASIC_BENCHMARK_TEST(BM_spin_pause_before_and_after)->ThreadPerCpu(); + + +void BM_empty_stop_start(benchmark::State& state) { + while (state.KeepRunning()) { } +} +BENCHMARK(BM_empty_stop_start); +BENCHMARK(BM_empty_stop_start)->ThreadPerCpu(); + +BENCHMARK_MAIN() diff --git a/thirdparty/google-benchmark/test/benchmark_test.cc b/thirdparty/google-benchmark/test/benchmark_test.cc new file mode 100644 index 00000000..2d268ce4 --- /dev/null +++ b/thirdparty/google-benchmark/test/benchmark_test.cc @@ -0,0 +1,154 @@ +#include "benchmark/benchmark.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__GNUC__) +# define BENCHMARK_NOINLINE __attribute__((noinline)) +#else +# define BENCHMARK_NOINLINE +#endif + +namespace { + +int BENCHMARK_NOINLINE Factorial(uint32_t n) { + return (n == 1) ? 1 : n * Factorial(n - 1); +} + +double CalculatePi(int depth) { + double pi = 0.0; + for (int i = 0; i < depth; ++i) { + double numerator = static_cast(((i % 2) * 2) - 1); + double denominator = static_cast((2 * i) - 1); + pi += numerator / denominator; + } + return (pi - 1.0) * 4; +} + +std::set ConstructRandomSet(int size) { + std::set s; + for (int i = 0; i < size; ++i) + s.insert(i); + return s; +} + +std::mutex test_vector_mu; +std::vector* test_vector = nullptr; + +} // end namespace + +static void BM_Factorial(benchmark::State& state) { + int fac_42 = 0; + while (state.KeepRunning()) + fac_42 = Factorial(8); + // Prevent compiler optimizations + std::stringstream ss; + ss << fac_42; + state.SetLabel(ss.str()); +} +BENCHMARK(BM_Factorial); +BENCHMARK(BM_Factorial)->UseRealTime(); + +static void BM_CalculatePiRange(benchmark::State& state) { + double pi = 0.0; + while (state.KeepRunning()) + pi = CalculatePi(state.range_x()); + std::stringstream ss; + ss << pi; + state.SetLabel(ss.str()); +} +BENCHMARK_RANGE(BM_CalculatePiRange, 1, 1024 * 1024); + +static void BM_CalculatePi(benchmark::State& state) { + static const int depth = 1024; + while (state.KeepRunning()) { + benchmark::DoNotOptimize(CalculatePi(depth)); + } +} +BENCHMARK(BM_CalculatePi)->Threads(8); +BENCHMARK(BM_CalculatePi)->ThreadRange(1, 32); +BENCHMARK(BM_CalculatePi)->ThreadPerCpu(); + +static void BM_SetInsert(benchmark::State& state) { + while (state.KeepRunning()) { + state.PauseTiming(); + std::set data = ConstructRandomSet(state.range_x()); + state.ResumeTiming(); + for (int j = 0; j < state.range_y(); ++j) + data.insert(rand()); + } + state.SetItemsProcessed(state.iterations() * state.range_y()); + state.SetBytesProcessed(state.iterations() * state.range_y() * sizeof(int)); +} +BENCHMARK(BM_SetInsert)->RangePair(1<<10,8<<10, 1,10); + +template +static void BM_Sequential(benchmark::State& state) { + ValueType v = 42; + while (state.KeepRunning()) { + Container c; + for (int i = state.range_x(); --i; ) + c.push_back(v); + } + const size_t items_processed = state.iterations() * state.range_x(); + state.SetItemsProcessed(items_processed); + state.SetBytesProcessed(items_processed * sizeof(v)); +} +BENCHMARK_TEMPLATE2(BM_Sequential, std::vector, int)->Range(1 << 0, 1 << 10); +BENCHMARK_TEMPLATE(BM_Sequential, std::list)->Range(1 << 0, 1 << 10); +// Test the variadic version of BENCHMARK_TEMPLATE in C++11 and beyond. +#if __cplusplus >= 201103L +BENCHMARK_TEMPLATE(BM_Sequential, std::vector, int)->Arg(512); +#endif + +static void BM_StringCompare(benchmark::State& state) { + std::string s1(state.range_x(), '-'); + std::string s2(state.range_x(), '-'); + while (state.KeepRunning()) + benchmark::DoNotOptimize(s1.compare(s2)); +} +BENCHMARK(BM_StringCompare)->Range(1, 1<<20); + +static void BM_SetupTeardown(benchmark::State& state) { + if (state.thread_index == 0) { + // No need to lock test_vector_mu here as this is running single-threaded. + test_vector = new std::vector(); + } + int i = 0; + while (state.KeepRunning()) { + std::lock_guard l(test_vector_mu); + if (i%2 == 0) + test_vector->push_back(i); + else + test_vector->pop_back(); + ++i; + } + if (state.thread_index == 0) { + delete test_vector; + } +} +BENCHMARK(BM_SetupTeardown)->ThreadPerCpu(); + +static void BM_LongTest(benchmark::State& state) { + double tracker = 0.0; + while (state.KeepRunning()) { + for (int i = 0; i < state.range_x(); ++i) + benchmark::DoNotOptimize(tracker += i); + } +} +BENCHMARK(BM_LongTest)->Range(1<<16,1<<28); + +BENCHMARK_MAIN() + diff --git a/thirdparty/google-benchmark/test/cxx03_test.cc b/thirdparty/google-benchmark/test/cxx03_test.cc new file mode 100644 index 00000000..56779d66 --- /dev/null +++ b/thirdparty/google-benchmark/test/cxx03_test.cc @@ -0,0 +1,31 @@ + +#include + +#include "benchmark/benchmark.h" + +#if __cplusplus >= 201103L +#error C++11 or greater detected. Should be C++03. +#endif + +void BM_empty(benchmark::State& state) { + while (state.KeepRunning()) { + volatile std::size_t x = state.iterations(); + ((void)x); + } +} +BENCHMARK(BM_empty); + +template +void BM_template2(benchmark::State& state) { + BM_empty(state); +} +BENCHMARK_TEMPLATE2(BM_template2, int, long); + +template +void BM_template1(benchmark::State& state) { + BM_empty(state); +} +BENCHMARK_TEMPLATE(BM_template1, long); +BENCHMARK_TEMPLATE1(BM_template1, int); + +BENCHMARK_MAIN() diff --git a/thirdparty/google-benchmark/test/filter_test.cc b/thirdparty/google-benchmark/test/filter_test.cc new file mode 100644 index 00000000..2a278ff4 --- /dev/null +++ b/thirdparty/google-benchmark/test/filter_test.cc @@ -0,0 +1,91 @@ +#include "benchmark/benchmark.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace { + +class TestReporter : public benchmark::ConsoleReporter { + public: + virtual bool ReportContext(const Context& context) { + return ConsoleReporter::ReportContext(context); + }; + + virtual void ReportRuns(const std::vector& report) { + ++count_; + ConsoleReporter::ReportRuns(report); + }; + + TestReporter() : count_(0) {} + + virtual ~TestReporter() {} + + size_t GetCount() const { + return count_; + } + + private: + mutable size_t count_; +}; + +} // end namespace + + +static void NoPrefix(benchmark::State& state) { + while (state.KeepRunning()) {} +} +BENCHMARK(NoPrefix); + +static void BM_Foo(benchmark::State& state) { + while (state.KeepRunning()) {} +} +BENCHMARK(BM_Foo); + + +static void BM_Bar(benchmark::State& state) { + while (state.KeepRunning()) {} +} +BENCHMARK(BM_Bar); + + +static void BM_FooBar(benchmark::State& state) { + while (state.KeepRunning()) {} +} +BENCHMARK(BM_FooBar); + + +static void BM_FooBa(benchmark::State& state) { + while (state.KeepRunning()) {} +} +BENCHMARK(BM_FooBa); + + + +int main(int argc, char* argv[]) { + benchmark::Initialize(&argc, argv); + + TestReporter test_reporter; + benchmark::RunSpecifiedBenchmarks(&test_reporter); + + if (argc == 2) { + // Make sure we ran all of the tests + std::stringstream ss(argv[1]); + size_t expected; + ss >> expected; + + const size_t count = test_reporter.GetCount(); + if (count != expected) { + std::cerr << "ERROR: Expected " << expected << " tests to be ran but only " + << count << " completed" << std::endl; + return -1; + } + } + return 0; +} diff --git a/thirdparty/google-benchmark/test/fixture_test.cc b/thirdparty/google-benchmark/test/fixture_test.cc new file mode 100644 index 00000000..8aea6ef0 --- /dev/null +++ b/thirdparty/google-benchmark/test/fixture_test.cc @@ -0,0 +1,42 @@ + +#include "benchmark/benchmark.h" + +#include + +class MyFixture : public ::benchmark::Fixture +{ +public: + void SetUp() { + data = new int(42); + } + + void TearDown() { + assert(data != nullptr); + delete data; + data = nullptr; + } + + ~MyFixture() { + assert(data == nullptr); + } + + int* data; +}; + + +BENCHMARK_F(MyFixture, Foo)(benchmark::State& st) { + assert(data != nullptr); + assert(*data == 42); + while (st.KeepRunning()) { + } +} + +BENCHMARK_DEFINE_F(MyFixture, Bar)(benchmark::State& st) { + while (st.KeepRunning()) { + } + st.SetItemsProcessed(st.range_x()); +} +BENCHMARK_REGISTER_F(MyFixture, Bar)->Arg(42); + + +BENCHMARK_MAIN() diff --git a/thirdparty/google-benchmark/test/options_test.cc b/thirdparty/google-benchmark/test/options_test.cc new file mode 100644 index 00000000..d4c682d4 --- /dev/null +++ b/thirdparty/google-benchmark/test/options_test.cc @@ -0,0 +1,26 @@ +#include "benchmark/benchmark_api.h" + +void BM_basic(benchmark::State& state) { + while (state.KeepRunning()) { + } +} +BENCHMARK(BM_basic); +BENCHMARK(BM_basic)->Arg(42); +BENCHMARK(BM_basic)->Range(1, 8); +BENCHMARK(BM_basic)->DenseRange(10, 15); +BENCHMARK(BM_basic)->ArgPair(42, 42); +BENCHMARK(BM_basic)->RangePair(64, 512, 64, 512); +BENCHMARK(BM_basic)->MinTime(0.7); +BENCHMARK(BM_basic)->UseRealTime(); +BENCHMARK(BM_basic)->ThreadRange(2, 4); +BENCHMARK(BM_basic)->ThreadPerCpu(); + +void CustomArgs(benchmark::internal::Benchmark* b) { + for (int i = 0; i < 10; ++i) { + b->Arg(i); + } +} + +BENCHMARK(BM_basic)->Apply(CustomArgs); + +BENCHMARK_MAIN() From 735f10134f018c3eb97479e976481ec73e269887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Thu, 4 Feb 2016 16:07:55 +0100 Subject: [PATCH 044/402] fixed bug : the parallel algos could terminate while some threads still had work to do. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/map_base.h | 40 +++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index c2dd7e14..f91eaa7c 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -579,9 +579,10 @@ class MapBase : public MapBaseData { for (unsigned i = 0u; i < 2u; ++i) { - for (unsigned int j = 0u; j < cgogn::MAX_NB_THREADS && it != end ; ++j) + for (unsigned int j = 0u; j < nb_threads_pool && it != end ; ++j) { dart_buffers[i].push_back(dbuffs->get_buffer()); + cgogn_assert(dart_buffers[i].size() <= nb_threads_pool); std::vector& darts = *dart_buffers[i].back(); darts.reserve(PARALLEL_BUFFER_SIZE); for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != end; ++k) @@ -602,7 +603,17 @@ class MapBase : public MapBaseData futures[id].clear(); dart_buffers[id].clear(); + + // if we reach the end of the map while filling buffers from the second set we need to clean them too. + if (it == end && i == 1u) + { + for (auto& fu: futures[1u]) + fu.wait(); + for (auto &b : dart_buffers[1u]) + dbuffs->release_buffer(b); + } } + } } @@ -793,6 +804,15 @@ class MapBase : public MapBaseData futures[id].clear(); cells_buffers[id].clear(); + + // if we reach the end of the map while filling buffers from the second set we need to clean them too. + if (it == end && i == 1u) + { + for (auto& fu: futures[1u]) + fu.wait(); + for (auto &b : cells_buffers[1u]) + dbuffs->release_cell_buffer(b); + } } } } @@ -867,6 +887,15 @@ class MapBase : public MapBaseData futures[id].clear(); cells_buffers[id].clear(); + + // if we reach the end of the map while filling buffers from the second set we need to clean them too. + if (it == end && i == 1u) + { + for (auto& fu: futures[1u]) + fu.wait(); + for (auto &b : cells_buffers[1u]) + dbuffs->release_cell_buffer(b); + } } } } @@ -934,6 +963,15 @@ class MapBase : public MapBaseData futures[id].clear(); cells_buffers[id].clear(); + + // if we reach the end of the map while filling buffers from the second set we need to clean them too. + if (it == end && i == 1u) + { + for (auto& fu: futures[1u]) + fu.wait(); + for (auto &b : cells_buffers[1u]) + dbuffs->release_cell_buffer(b); + } } } } From ee05ce0a628a7e9b2adddc37bf6960aeb3e1e0b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Thu, 4 Feb 2016 16:08:20 +0100 Subject: [PATCH 045/402] The multithreading bench now uses google benchmark. Try it ! MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- benchmarks/multithreading/CMakeLists.txt | 3 +- .../multithreading/bench_multithreading.cpp | 481 +++++------------- 2 files changed, 133 insertions(+), 351 deletions(-) diff --git a/benchmarks/multithreading/CMakeLists.txt b/benchmarks/multithreading/CMakeLists.txt index 48b1218e..bfa3a167 100644 --- a/benchmarks/multithreading/CMakeLists.txt +++ b/benchmarks/multithreading/CMakeLists.txt @@ -8,4 +8,5 @@ set(CGOGN_TEST_MESHES_PATH "${CMAKE_SOURCE_DIR}/data/meshes/") add_definitions("-DCGOGN_TEST_MESHES_PATH=${CGOGN_TEST_MESHES_PATH}") add_executable(${PROJECT_NAME} bench_multithreading.cpp) -target_link_libraries(${PROJECT_NAME} cgogn_core cgogn_io cgogn_geometry) +target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/thirdparty/google-benchmark/include) +target_link_libraries(${PROJECT_NAME} cgogn_core cgogn_io cgogn_geometry benchmark) diff --git a/benchmarks/multithreading/bench_multithreading.cpp b/benchmarks/multithreading/bench_multithreading.cpp index 52a90355..7bb055c5 100644 --- a/benchmarks/multithreading/bench_multithreading.cpp +++ b/benchmarks/multithreading/bench_multithreading.cpp @@ -29,12 +29,12 @@ #include #include +#include #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) - - using Map2 = cgogn::CMap2; +Map2 map; const cgogn::Orbit VERTEX = Map2::VERTEX; using Vertex = cgogn::Cell; @@ -52,410 +52,191 @@ using VertexAttributeHandler = Map2::VertexAttributeHandler; template using FaceAttributeHandler = Map2::FaceAttributeHandler; -int main(int argc, char** argv) +static void BENCH_Dart_count_single_threaded(benchmark::State& state) { - std::string surfaceMesh; - if (argc < 2) + while (state.KeepRunning()) { - std::cout << "USAGE: " << argv[0] << " [filename]" << std::endl; - surfaceMesh = std::string(DEFAULT_MESH_PATH) + std::string("aneurysm3D_1.off"); - std::cout << "Using default mesh : " << surfaceMesh << std::endl; + unsigned nb_darts = 0u; + map.foreach_dart([&nb_darts] (cgogn::Dart) { nb_darts++; }); } - else - surfaceMesh = std::string(argv[1]); - - Map2 map; - cgogn::io::import_surface(map, surfaceMesh); +} +static void BENCH_Dart_count_multi_threaded(benchmark::State& state) +{ + while (state.KeepRunning()) { - // COUNTING DARTS SINGLE THREAD - unsigned int nb_darts = 0u; - { - std::chrono::time_point start, end; - start = std::chrono::system_clock::now(); - for (unsigned int i = 0u; i < ITERATIONS; ++i) - { - nb_darts = 0u; - map.foreach_dart([&nb_darts] (cgogn::Dart) { nb_darts++; }); - } - end = std::chrono::system_clock::now(); - std::chrono::duration elapsed_seconds = end - start; - std::cout << std::fixed << "SINGLE THREAD "<< elapsed_seconds.count() << "s || nb darts :" << nb_darts << std::endl; - } - // END COUNTING DARTS SINGLE THREAD - - // COUNTING DARTS MULTI-THREADS unsigned int nb_darts_2 = 0u; - std::vector nb_darts_per_thread(cgogn::get_thread_pool()->get_nb_threads()); - { - std::chrono::time_point start, end; - start = std::chrono::system_clock::now(); - - for (unsigned int i = 0u; i < ITERATIONS; ++i) - { - for (auto& n : nb_darts_per_thread) - n = 0u; - nb_darts_2 = 0u; - // clock_gettime(CLOCK_REALTIME,&tbegin); - map.parallel_foreach_dart([&nb_darts_per_thread] (cgogn::Dart, unsigned int thread_index) - { - cgogn_assert(thread_index< 7); - nb_darts_per_thread[thread_index]++; - }); - // clock_gettime(CLOCK_REALTIME,&tend); - // std::cout << __FILE__ << ":" << __LINE__ << " : " << (1000000000u*(tend.tv_sec - tbegin.tv_sec) +tend.tv_nsec - tbegin.tv_nsec)/1000u << " microseconds."< elapsed_seconds = end - start; - std::cout << std::fixed << cgogn::NB_THREADS << " THREADS "<< elapsed_seconds.count() << "s || nb darts :" << nb_darts_2 << std::endl; - } - // END COUNTING DARTS MULTI-THREADS - - VertexAttributeHandler vertex_position = map.get_attribute("position"); - FaceAttributeHandler face_normal = map.add_attribute("normal"); - FaceAttributeHandler face_normal_mt = map.add_attribute("normal_mt"); - - - - // DART MARKING - { - std::chrono::time_point start, end; - start = std::chrono::system_clock::now(); - - for (unsigned int i = 0u ; i < ITERATIONS; ++i) - { - map.template foreach_cell([&] (Face f) - { - face_normal[f] = cgogn::geometry::face_normal(map, f, vertex_position); - }); - } - end = std::chrono::system_clock::now(); - std::chrono::duration elapsed_seconds = end - start; - std::cout << std::fixed << "SINGLE THREAD "<< elapsed_seconds.count() << "s || compute_normal_faces dart marking" << std::endl; - } - + std::vector nb_darts_per_thread(cgogn::get_nb_threads()+2); + for (auto& n : nb_darts_per_thread) + n = 0u; + nb_darts_2 = 0u; + map.parallel_foreach_dart([&nb_darts_per_thread] (cgogn::Dart, unsigned int thread_index) { - std::chrono::time_point start, end; - start = std::chrono::system_clock::now(); - for (unsigned int i = 0u ; i < ITERATIONS; ++i) - { - map.template parallel_foreach_cell([&] (Face f, unsigned int) - { - face_normal_mt[f] = cgogn::geometry::face_normal(map, f, vertex_position); - }); - } - + nb_darts_per_thread[thread_index]++; + }); + for (unsigned int n : nb_darts_per_thread) + nb_darts_2 += n; - end = std::chrono::system_clock::now(); - std::chrono::duration elapsed_seconds = end - start; - std::cout << std::fixed << cgogn::NB_THREADS << " THREADS "<< elapsed_seconds.count() << "s || compute_normal_faces dart marking" << std::endl; - } + cgogn_assert(nb_darts_2 = map.nb_darts()); + } +} - // END DART MARKING +template +static void BENCH_faces_normals_single_threaded(benchmark::State& state) +{ + while(state.KeepRunning()) + { + state.PauseTiming(); + VertexAttributeHandler vertex_position = map.get_attribute("position"); + cgogn_assert(vertex_position.is_valid()); + FaceAttributeHandler face_normal = map.get_attribute("normal"); + cgogn_assert(face_normal.is_valid()); + state.ResumeTiming(); + map.template foreach_cell([&] (Face f) { - // CHECKING NORMALS - map.template foreach_cell([&] (Face f) - { - Vec3 error = face_normal[f] - face_normal_mt[f]; - if (!cgogn::almost_equal_absolute(error.squaredNorm(), 0., 1e-9 )) - { - std::cerr << __FILE__ << ":" << __LINE__ << " : there was an error during computation of normals" << std::endl; - std::abort; - } - - }); - } + face_normal[f] = cgogn::geometry::face_normal(map, f, vertex_position); + }); + } +} - // CELL MARKING +template +static void BENCH_faces_normals_multi_threaded(benchmark::State& state) +{ + while(state.KeepRunning()) + { + state.PauseTiming(); + VertexAttributeHandler vertex_position = map.get_attribute("position"); + cgogn_assert(vertex_position.is_valid()); + FaceAttributeHandler face_normal_mt = map.get_attribute("normal_mt"); + cgogn_assert(face_normal_mt.is_valid()); + state.ResumeTiming(); + map.template parallel_foreach_cell([&] (Face f,unsigned int) { - std::chrono::time_point start, end; - start = std::chrono::system_clock::now(); - - for (unsigned int i = 0u ; i < ITERATIONS; ++i) - { - map.template foreach_cell([&] (Face f) - { - face_normal[f] = cgogn::geometry::face_normal(map, f, vertex_position); - }); - } - end = std::chrono::system_clock::now(); - std::chrono::duration elapsed_seconds = end - start; - std::cout << std::fixed << "SINGLE THREAD "<< elapsed_seconds.count() << "s || compute_normal_faces cell marking" << std::endl; - } + face_normal_mt[f] = cgogn::geometry::face_normal(map, f, vertex_position); + }); { - std::chrono::time_point start, end; - start = std::chrono::system_clock::now(); - for (unsigned int i = 0u ; i < ITERATIONS; ++i) - { - map.template parallel_foreach_cell([&] (Face f, unsigned int) - { - face_normal_mt[f] = cgogn::geometry::face_normal(map, f, vertex_position); - }); - } - - - end = std::chrono::system_clock::now(); - std::chrono::duration elapsed_seconds = end - start; - std::cout << std::fixed << cgogn::NB_THREADS << " THREADS "<< elapsed_seconds.count() << "s || compute_normal_faces cell marking" << std::endl; - } - - // END CELL MARKING - + state.PauseTiming(); - { - // CHECKING NORMALS + FaceAttributeHandler face_normal = map.get_attribute("normal"); map.template foreach_cell([&] (Face f) { Vec3 error = face_normal[f] - face_normal_mt[f]; if (!cgogn::almost_equal_absolute(error.squaredNorm(), 0., 1e-9 )) { std::cerr << __FILE__ << ":" << __LINE__ << " : there was an error during computation of normals" << std::endl; - std::abort; + std::cerr << "face_normal " << face_normal[f] << std::endl; + std::cerr << "face_normal_mt " << face_normal_mt[f] << std::endl; } }); + state.ResumeTiming(); } - map.enable_topo_cache(); - - -// // TOPO CACHE - - { - std::chrono::time_point start, end; - start = std::chrono::system_clock::now(); - - for (unsigned int i = 0u ; i < ITERATIONS; ++i) - { - map.template foreach_cell([&] (Face f) - { - face_normal[f] = cgogn::geometry::face_normal(map, f, vertex_position); - }); - } - end = std::chrono::system_clock::now(); - std::chrono::duration elapsed_seconds = end - start; - std::cout << std::fixed << "SINGLE THREAD "<< elapsed_seconds.count() << "s || compute_normal_faces topo cache" << std::endl; - } - - { - std::chrono::time_point start, end; - start = std::chrono::system_clock::now(); - for (unsigned int i = 0u ; i < ITERATIONS; ++i) - { - map.template parallel_foreach_cell([&] (Face f, unsigned int) - { - face_normal_mt[f] = cgogn::geometry::face_normal(map, f, vertex_position); - }); - } - - - end = std::chrono::system_clock::now(); - std::chrono::duration elapsed_seconds = end - start; - std::cout << std::fixed << cgogn::NB_THREADS << " THREADS "<< elapsed_seconds.count() << "s || compute_normal_faces topo cache" << std::endl; - } - - // END TOPO CACHE - { - // CHECKING NORMALS - map.template foreach_cell([&] (Face f) - { - Vec3 error = face_normal[f] - face_normal_mt[f]; - if (!cgogn::almost_equal_absolute(error.squaredNorm(), 0., 1e-9 )) - { - std::cerr << __FILE__ << ":" << __LINE__ << " : there was an error during computation of normals" << std::endl; - std::abort; - } - - }); - } - - - - VertexAttributeHandler vertex_normal = map.add_attribute("normal"); - VertexAttributeHandler vertex_normal_mt = map.add_attribute("normal_mt"); - - - // VERTICES NORMALS - - - - // DART MARKING - - { - std::chrono::time_point start, end; - start = std::chrono::system_clock::now(); - - for (unsigned int i = 0u ; i < ITERATIONS; ++i) - { - map.template foreach_cell([&] (Vertex v) - { - vertex_normal[v] = cgogn::geometry::vertex_normal(map, v, vertex_position); - }); - } - end = std::chrono::system_clock::now(); - std::chrono::duration elapsed_seconds = end - start; - std::cout << std::fixed << "SINGLE THREAD "<< elapsed_seconds.count() << "s || compute_normal_vertices dart marking" << std::endl; } +} - { - std::chrono::time_point start, end; - start = std::chrono::system_clock::now(); - for (unsigned int i = 0u ; i < ITERATIONS; ++i) - { - map.template parallel_foreach_cell([&] (Vertex v, unsigned int) - { - vertex_normal_mt[v] = cgogn::geometry::vertex_normal(map, v, vertex_position); - }); - } - - // END DART MARKING - - end = std::chrono::system_clock::now(); - std::chrono::duration elapsed_seconds = end - start; - std::cout << std::fixed << cgogn::NB_THREADS << " THREADS "<< elapsed_seconds.count() << "s || compute_normal_vertices dart marking" << std::endl; - } - - - { - // CHECKING VERTEX NORMALS - map.template foreach_cell([&] (Vertex v) - { - Vec3 error = vertex_normal[v] - vertex_normal_mt[v]; - if (!cgogn::almost_equal_absolute(error.squaredNorm(), 0., 1e-9 )) - { - std::cerr << __FILE__ << ":" << __LINE__ << " : there was an error during computation of normals" << std::endl; - std::cerr << "vertex_normal " << vertex_normal[v] << std::endl; - std::cerr << "vertex_normal_mt " < +static void BENCH_vertices_normals_single_threaded(benchmark::State& state) +{ + while(state.KeepRunning()) { - std::chrono::time_point start, end; - start = std::chrono::system_clock::now(); + state.PauseTiming(); + VertexAttributeHandler vertex_position = map.get_attribute("position"); + cgogn_assert(vertex_position.is_valid()); + VertexAttributeHandler vartices_normal = map.get_attribute("normal"); + cgogn_assert(vartices_normal.is_valid()); + state.ResumeTiming(); - for (unsigned int i = 0u ; i < ITERATIONS; ++i) + map.template foreach_cell([&] (Vertex v) { - map.template foreach_cell([&] (Vertex v) - { - vertex_normal[v] = cgogn::geometry::vertex_normal(map, v, vertex_position); - }); - } - end = std::chrono::system_clock::now(); - std::chrono::duration elapsed_seconds = end - start; - std::cout << std::fixed << "SINGLE THREAD "<< elapsed_seconds.count() << "s || compute_normal_vertices cell marking" << std::endl; + vartices_normal[v] = cgogn::geometry::vertex_normal(map, v, vertex_position); + }); } +} +template +static void BENCH_vertices_normals_multi_threaded(benchmark::State& state) +{ + while(state.KeepRunning()) { - std::chrono::time_point start, end; - start = std::chrono::system_clock::now(); - for (unsigned int i = 0u ; i < ITERATIONS; ++i) - { - map.template parallel_foreach_cell([&] (Vertex v, unsigned int) - { - vertex_normal_mt[v] = cgogn::geometry::vertex_normal(map, v, vertex_position); - }); - } - - - end = std::chrono::system_clock::now(); - std::chrono::duration elapsed_seconds = end - start; - std::cout << std::fixed << cgogn::NB_THREADS << " THREADS "<< elapsed_seconds.count() << "s || compute_normal_vertices cell marking" << std::endl; - } - - // END CELL MARKING - + state.PauseTiming(); + VertexAttributeHandler vertex_position = map.get_attribute("position"); + cgogn_assert(vertex_position.is_valid()); + VertexAttributeHandler vertices_normal_mt = map.get_attribute("normal_mt"); + cgogn_assert(vertices_normal_mt.is_valid()); + state.ResumeTiming(); - { - // CHECKING VERTEX NORMALS - map.template foreach_cell([&] (Vertex v) + map.template parallel_foreach_cell([&] (Vertex v, unsigned int) { - Vec3 error = vertex_normal[v] - vertex_normal_mt[v]; - if (!cgogn::almost_equal_absolute(error.squaredNorm(), 0., 1e-9 )) - { - std::cerr << __FILE__ << ":" << __LINE__ << " : there was an error during computation of normals" << std::endl; - std::cerr << "vertex_normal " << vertex_normal[v] << std::endl; - std::cerr << "vertex_normal_mt " <(map, v, vertex_position); }); - } - - - - // TOPO CACHE - map.enable_topo_cache(); - - { - std::chrono::time_point start, end; - start = std::chrono::system_clock::now(); - - for (unsigned int i = 0u ; i < ITERATIONS; ++i) { - map.template foreach_cell([&] (Vertex v) - { - vertex_normal[v] = cgogn::geometry::vertex_normal(map, v, vertex_position); - }); - } - end = std::chrono::system_clock::now(); - std::chrono::duration elapsed_seconds = end - start; - std::cout << std::fixed << "SINGLE THREAD "<< elapsed_seconds.count() << "s || compute_normal_vertices topo cache" << std::endl; - } + state.PauseTiming(); - { - std::chrono::time_point start, end; - start = std::chrono::system_clock::now(); - for (unsigned int i = 0u ; i < ITERATIONS; ++i) - { - map.template parallel_foreach_cell([&] (Vertex v, unsigned int) + VertexAttributeHandler vertices_normal = map.get_attribute("normal"); + map.template foreach_cell([&] (Vertex v) { - vertex_normal_mt[v] = cgogn::geometry::vertex_normal(map, v, vertex_position); + Vec3 error = vertices_normal[v] - vertices_normal_mt[v]; + if (!cgogn::almost_equal_absolute(error.squaredNorm(), 0., 1e-9 )) + { + std::cerr << __FILE__ << ":" << __LINE__ << " : there was an error during computation of vertices normals" << std::endl; + std::cerr << "vertices_normal " << vertices_normal[v] << std::endl; + std::cerr << "vertices_normal_mt " << vertices_normal_mt[v] << std::endl; + } + }); + state.ResumeTiming(); } - - - end = std::chrono::system_clock::now(); - std::chrono::duration elapsed_seconds = end - start; - std::cout << std::fixed << cgogn::NB_THREADS << " THREADS "<< elapsed_seconds.count() << "s || compute_normal_vertices topo cache" << std::endl; } +} +BENCHMARK(BENCH_Dart_count_single_threaded); +BENCHMARK(BENCH_Dart_count_multi_threaded)->UseRealTime(); - { - // CHECKING VERTEX NORMALS - map.template foreach_cell([&] (Vertex v) - { - Vec3 error = vertex_normal[v] - vertex_normal_mt[v]; - if (!cgogn::almost_equal_absolute(error.squaredNorm(), 0., 1e-9 )) - { - std::cerr << __FILE__ << ":" << __LINE__ << " : there was an error during computation of normals" << std::endl; - std::cerr << "vertex_normal " << vertex_normal[v] << std::endl; - std::cerr << "vertex_normal_mt " <UseRealTime(); +BENCHMARK_TEMPLATE(BENCH_faces_normals_multi_threaded, cgogn::TraversalStrategy::FORCE_DART_MARKING)->UseRealTime(); +BENCHMARK_TEMPLATE(BENCH_faces_normals_single_threaded, cgogn::TraversalStrategy::FORCE_CELL_MARKING)->UseRealTime(); +BENCHMARK_TEMPLATE(BENCH_faces_normals_multi_threaded, cgogn::TraversalStrategy::FORCE_CELL_MARKING)->UseRealTime(); +BENCHMARK_TEMPLATE(BENCH_faces_normals_single_threaded, cgogn::TraversalStrategy::FORCE_TOPO_CACHE)->UseRealTime(); +BENCHMARK_TEMPLATE(BENCH_faces_normals_multi_threaded, cgogn::TraversalStrategy::FORCE_TOPO_CACHE)->UseRealTime(); - }); - } +BENCHMARK_TEMPLATE(BENCH_vertices_normals_single_threaded, cgogn::TraversalStrategy::FORCE_DART_MARKING)->UseRealTime(); +BENCHMARK_TEMPLATE(BENCH_vertices_normals_multi_threaded, cgogn::TraversalStrategy::FORCE_DART_MARKING)->UseRealTime(); +BENCHMARK_TEMPLATE(BENCH_vertices_normals_single_threaded, cgogn::TraversalStrategy::FORCE_CELL_MARKING)->UseRealTime(); +BENCHMARK_TEMPLATE(BENCH_vertices_normals_multi_threaded, cgogn::TraversalStrategy::FORCE_CELL_MARKING)->UseRealTime(); +BENCHMARK_TEMPLATE(BENCH_vertices_normals_single_threaded, cgogn::TraversalStrategy::FORCE_TOPO_CACHE)->UseRealTime(); +BENCHMARK_TEMPLATE(BENCH_vertices_normals_multi_threaded, cgogn::TraversalStrategy::FORCE_TOPO_CACHE)->UseRealTime(); +int main(int argc, char** argv) +{ + ::benchmark::Initialize(&argc, argv); + std::string surfaceMesh; + if (argc < 2) + { + std::cout << "USAGE: " << argv[0] << " [filename]" << std::endl; + surfaceMesh = std::string(DEFAULT_MESH_PATH) + std::string("aneurysm3D_1.off"); + std::cout << "Using default mesh : " << surfaceMesh << std::endl; } + else + surfaceMesh = std::string(argv[1]); + cgogn::io::import_surface(map, surfaceMesh); + map.add_attribute("normal"); + map.add_attribute("normal_mt"); + map.add_attribute("normal"); + map.add_attribute("normal_mt"); + map.enable_topo_cache(); + map.enable_topo_cache(); + ::benchmark::RunSpecifiedBenchmarks(); return 0; } + From dae99cf205fd14647f6089fc4c8a597bb4223178 Mon Sep 17 00:00:00 2001 From: lionel untereiner Date: Thu, 4 Feb 2016 18:48:20 +0100 Subject: [PATCH 046/402] moving mrcmaps from core to multiresolution --- cgogn/multiresolution/CMakeLists.txt | 2 ++ cgogn/{core => multiresolution}/mrcmap/mrcmap2.h | 0 2 files changed, 2 insertions(+) rename cgogn/{core => multiresolution}/mrcmap/mrcmap2.h (100%) diff --git a/cgogn/multiresolution/CMakeLists.txt b/cgogn/multiresolution/CMakeLists.txt index ced12802..4dae2b3f 100644 --- a/cgogn/multiresolution/CMakeLists.txt +++ b/cgogn/multiresolution/CMakeLists.txt @@ -9,6 +9,8 @@ set(HEADER_FILES cph/ihcmap2_adaptive.h cph/ihcmap2_regular.h + mrcmap/mrcmap2.h + mranalysis/lerp_triquad_mra.h ) diff --git a/cgogn/core/mrcmap/mrcmap2.h b/cgogn/multiresolution/mrcmap/mrcmap2.h similarity index 100% rename from cgogn/core/mrcmap/mrcmap2.h rename to cgogn/multiresolution/mrcmap/mrcmap2.h From 6c49769f8bf71f32d7b05b58a91738b8090e9d6f Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Fri, 5 Feb 2016 11:10:40 +0100 Subject: [PATCH 047/402] Handling unknown threads and using std::arrays instead of c-style arrays. Signed-off-by: Etienne Schmitt --- cgogn/core/cmap/map_base_data.h | 82 ++++++++++++++++++++++++++------- 1 file changed, 66 insertions(+), 16 deletions(-) diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index 11a25050..dbc16150 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -36,6 +36,7 @@ #include #include #include +#include namespace cgogn { @@ -88,7 +89,7 @@ class MapBaseData : public MapGen typedef MapBaseData Self; static const unsigned int CHUNKSIZE = MAP_TRAITS::CHUNK_SIZE; - + static const unsigned int NB_UNKNOWN_THREADS = 4u; template friend class AttributeHandlerOrbit; template @@ -103,28 +104,30 @@ class MapBaseData : public MapGen ChunkArrayContainer topology_; /// per orbit attributes - ChunkArrayContainer attributes_[NB_ORBITS]; + std::array, NB_ORBITS> attributes_; /// embedding indices shortcuts - ChunkArray* embeddings_[NB_ORBITS]; + std::array*, NB_ORBITS> embeddings_; /// boundary markers shortcuts - ChunkArray* boundary_markers_[2]; + std::array*, 2> boundary_markers_; // TODO: ?? store in a std::vector ? /// vector of available mark attributes per thread on the topology container - std::vector*> mark_attributes_topology_[MAX_NB_THREADS]; + std::vector*>> mark_attributes_topology_; std::mutex mark_attributes_topology_mutex_; /// vector of available mark attributes per orbit per thread on attributes containers - std::vector*> mark_attributes_[NB_ORBITS][MAX_NB_THREADS]; - std::mutex mark_attributes_mutex_[NB_ORBITS]; + std::array*>>, NB_ORBITS> mark_attributes_; + std::array mark_attributes_mutex_; - /// vector of thread ids known by the map that can pretend to data such as mark vectors + /// Before accessing the map, a thread should call map.add_thread(std::this_thread::get_id()) (and do a map.remove_thread(std::this_thread::get_id() before it terminates) + /// The first part of the vector ( 0 to NB_UNKNOWN_THREADS -1) stores threads that want to access the map without using this interface. They might be deleted if we have too many of them. + /// The second part (NB_UNKNOWN_THREADS to infinity) of the vector stores threads IDs added using this interface and they are guaranteed not to be deleted. mutable std::vector thread_ids_; /// global topo cache shortcuts - ChunkArray* global_topo_cache_[NB_ORBITS]; + std::array*, NB_ORBITS> global_topo_cache_; public: @@ -137,15 +140,23 @@ class MapBaseData : public MapGen } for (unsigned int i = 0; i < NB_ORBITS; ++i) { + mark_attributes_[i].reserve(NB_UNKNOWN_THREADS + 2u*MAX_NB_THREADS); + mark_attributes_[i].resize(NB_UNKNOWN_THREADS + MAX_NB_THREADS); + embeddings_[i] = nullptr; global_topo_cache_[i] = nullptr; - for (unsigned int j = 0; j < MAX_NB_THREADS; ++j) + for (unsigned int j = 0; j < NB_UNKNOWN_THREADS + MAX_NB_THREADS; ++j) mark_attributes_[i][j].reserve(8); } + + mark_attributes_topology_.reserve(NB_UNKNOWN_THREADS + 2u*MAX_NB_THREADS); + mark_attributes_topology_.resize(NB_UNKNOWN_THREADS + MAX_NB_THREADS); + for (unsigned int i = 0; i < MAX_NB_THREADS; ++i) mark_attributes_topology_[i].reserve(8); - thread_ids_.reserve(MAX_NB_THREADS); + thread_ids_.reserve(NB_UNKNOWN_THREADS + 2u*MAX_NB_THREADS); + thread_ids_.resize(NB_UNKNOWN_THREADS); this->add_thread(std::this_thread::get_id()); const auto& pool_threads_ids = cgogn::get_thread_pool()->get_threads_ids(); for (const std::thread::id& ids : pool_threads_ids) @@ -269,23 +280,62 @@ class MapBaseData : public MapGen * Thread management *******************************************************************************/ + inline unsigned int add_unknown_thread() const + { + static unsigned int index = 0u; + const std::thread::id& th_id = std::this_thread::get_id(); + std::cerr << "WARNING: registration of an unknown thread (id :" << th_id << ") in the map." << std::endl; + std::cerr << "Data can be lost. Please use add_thread and remove_thread interface." << std::endl; + thread_ids_[index] = th_id; + const unsigned old_index = index; + index = (index+1u)% NB_UNKNOWN_THREADS; + return old_index; + } + + inline unsigned int get_unknown_thread_index(std::thread::id thread_id) const + { + auto end = thread_ids_.begin(); + std::advance(end, NB_UNKNOWN_THREADS); + auto res_it = std::find(thread_ids_.begin(), end, thread_id); + if (res_it != end) + return std::distance(thread_ids_.begin(), res_it); + + return add_unknown_thread(); + } + inline unsigned int get_current_thread_index() const { - cgogn_message_assert(std::binary_search(thread_ids_.begin(), thread_ids_.end(), std::this_thread::get_id()),"Unable to find currend thread ID."); - return std::distance(thread_ids_.begin(), std::lower_bound(thread_ids_.begin(), thread_ids_.end(), std::this_thread::get_id())); + // avoid the unknown threads stored at the beginning of the vector + auto real_begin =thread_ids_.begin(); + std::advance(real_begin, NB_UNKNOWN_THREADS); + + const auto end = thread_ids_.end(); + auto it_lower_bound = std::lower_bound(real_begin, end, std::this_thread::get_id()); + if (it_lower_bound != end) + return std::distance(thread_ids_.begin(),it_lower_bound); + + return get_unknown_thread_index(std::this_thread::get_id()); } inline void remove_thread(std::thread::id thread_id) const { - cgogn_message_assert(std::binary_search(thread_ids_.begin(), thread_ids_.end(), thread_id),"Unable to find the thread."); - auto it = std::lower_bound(thread_ids_.begin(), thread_ids_.end(),thread_id); + // avoid the unknown threads stored at the beginning of the vector + auto real_begin =thread_ids_.begin(); + std::advance(real_begin, NB_UNKNOWN_THREADS); + + cgogn_message_assert(std::binary_search(real_begin, thread_ids_.end(), thread_id),"Unable to find the thread."); + auto it = std::lower_bound(real_begin, thread_ids_.end(),thread_id); cgogn_message_assert((*it) == thread_id,"Unable to find the thread."); thread_ids_.erase(it); } inline void add_thread(std::thread::id thread_id) const { - auto it = std::lower_bound(thread_ids_.begin(), thread_ids_.end(),thread_id); + // avoid the unknown threads stored at the beginning of the vector + auto real_begin =thread_ids_.begin(); + std::advance(real_begin, NB_UNKNOWN_THREADS); + + auto it = std::lower_bound(real_begin, thread_ids_.end(),thread_id); if ((it == thread_ids_.end()) || (*it != thread_id)) { thread_ids_.insert(it,thread_id); From 167c37c24c8a4a22a33590b7c843beb202f8ba97 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Fri, 5 Feb 2016 17:31:52 +0100 Subject: [PATCH 048/402] Added CGOGN_USE_CXX11_ABI option. Signed-off-by: Etienne Schmitt --- CMakeLists.txt | 5 +++-- cmake/CompilerOptions.cmake | 12 ++++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c44ba6a..12b93c2d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,15 +40,16 @@ set(CGOGN_THIRDPARTY_DIR ${CMAKE_SOURCE_DIR}/thirdparty) option(CGOGN_PROVIDE_EIGEN "Use the version of eigen that is packaged with CGoGN." ON) option(CGOGN_PROVIDE_TINYXML2 "Use the version of tinyxml2 that is packaged with CGoGN." ON) option(CGOGN_BUILD_TESTS "Build cgogn unit tests using google test framework." ON) -option(CGOGN_BUILD_BENCHS "Build the benchmarks using google benchmark framework" ON) +option(CGOGN_BUILD_BENCHS "Build the benchmarks using google benchmark framework." ON) option(CGOGN_USE_OPENMP "Activate openMP directives." OFF) if (NOT MSVC) - option(CGOGN_USE_PARALLEL_GLIBCXX "Highly experimental : compiles using the parallel mode." OFF) option(CGOGN_USE_GLIBCXX_DEBUG "Use the debug version of STL (useful for bounds checking)." OFF) option(CGOGN_USE_GLIBCXX_DEBUG_PEDANTIC "Use an extremely picky debug version of STL." OFF) + option(CGOGN_USE_PARALLEL_GLIBCXX "Highly experimental : compiles using the parallel mode." OFF) if (${CGOGN_USE_GLIBCXX_DEBUG_PEDANTIC}) set(CGOGN_USE_GLIBCXX_DEBUG "ON") endif(${CGOGN_USE_GLIBCXX_DEBUG_PEDANTIC}) + option(CGOGN_USE_CXX11_ABI "use the CXX11 ABI." ON) endif(NOT MSVC) if (${CGOGN_USE_PARALLEL_GLIBCXX}) set(CGOGN_USE_OPENMP "ON") diff --git a/cmake/CompilerOptions.cmake b/cmake/CompilerOptions.cmake index 2fc5d650..f1329e07 100644 --- a/cmake/CompilerOptions.cmake +++ b/cmake/CompilerOptions.cmake @@ -81,6 +81,16 @@ if (NOT MSVC) add_flags(CMAKE_CXX_FLAGS "-Wnon-virtual-dtor") + + + if(${CGOGN_USE_CXX11_ABI}) + add_flags(CMAKE_CXX_FLAGS "-D_GLIBCXX_USE_CXX11_ABI") + else() + remove_definitions("-D_GLIBCXX_USE_CXX11_ABI") + endif() + + remove_definitions("-D_GLIBCXX_USE_DEPRECATED") + # see https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_macros.html if (${CGOGN_USE_GLIBCXX_DEBUG}) add_flags(CMAKE_CXX_FLAGS "-D_GLIBCXX_DEBUG") @@ -97,8 +107,6 @@ if (NOT MSVC) endif(${CGOGN_USE_GLIBCXX_DEBUG}) endif(${CGOGN_USE_PARALLEL_GLIBCXX}) - remove_definitions("-D_GLIBCXX_USE_DEPRECATED") - # Enable SSE3 instruction set add_flags(CMAKE_CXX_FLAGS "-msse3") add_flags(CMAKE_C_FLAGS "-msse3") From 7e3139bd706467bddc15f20661710ca1470eca95 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Fri, 5 Feb 2016 17:33:44 +0100 Subject: [PATCH 049/402] added name_of_type_impl overload for std::arrays Signed-off-by: Etienne Schmitt --- cgogn/core/utils/name_types.h | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/cgogn/core/utils/name_types.h b/cgogn/core/utils/name_types.h index 6eb54e14..8a9ad97c 100644 --- a/cgogn/core/utils/name_types.h +++ b/cgogn/core/utils/name_types.h @@ -77,6 +77,9 @@ template inline auto name_of_type_impl(const T&) -> typename std::enable_if::value == false, std::string>::type; // implementation for other classes and type + +// declarations + template inline auto name_of_type_impl(const T&) -> typename std::enable_if::value == true, std::string>::type; @@ -89,11 +92,14 @@ inline std::string name_of_type_impl(const std::vector&); template inline std::string name_of_type_impl(const std::basic_string&); +template +inline std::string name_of_type_impl(const std::array&); + +// definitions + template inline std::string name_of_type_impl(const std::basic_string&) -{ - return std::string("std::basic_string<") + name_of_type(T()) + std::string(">"); -} +{ return std::string("std::basic_string<") + name_of_type(T()) + std::string(">"); } template inline std::string name_of_type_impl(const std::list&) @@ -103,6 +109,10 @@ template inline std::string name_of_type_impl(const std::vector&) { return std::string("std::vector<") + name_of_type(T()) + std::string(">"); } +template +inline std::string name_of_type_impl(const std::array&) +{ return std::string("std::array<") + name_of_type(T()) + std::string(",") + std::to_string(N) + std::string(">"); } + template inline auto name_of_type_impl(const T&)->typename std::enable_if::value == true, std::string>::type From 930517f2ce9cbf807745fd6473fd6e5b13abacd9 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Fri, 5 Feb 2016 17:34:21 +0100 Subject: [PATCH 050/402] fixed bug when failing to load an attribute. Signed-off-by: Etienne Schmitt --- cgogn/core/container/chunk_array_container.h | 7 +++++-- cgogn/core/container/chunk_array_factory.h | 6 ++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/cgogn/core/container/chunk_array_container.h b/cgogn/core/container/chunk_array_container.h index 49baf243..073613d1 100644 --- a/cgogn/core/container/chunk_array_container.h +++ b/cgogn/core/container/chunk_array_container.h @@ -916,17 +916,20 @@ class ChunkArrayContainer // read chunk array table_arrays_.reserve(buff1[0]); bool ok = true; - for (unsigned int i = 0u; i < buff1[0]; ++i) + for (unsigned int i = 0u; i < names_.size();) { ChunkArrayGen* cag = ChunkArrayFactory::create(type_names_[i]); if (cag) { table_arrays_.push_back(cag); ok &= table_arrays_.back()->load(fs); + ++i; } else { - std::cerr << "ChunkArrayContainer: could not load attribute of type "<< type_names_[i] << std::endl; + std::cerr << "ChunkArrayContainer: could not load attribute" << names_[i] << " of type "<< type_names_[i] << std::endl; + type_names_.erase(type_names_.begin()+i); + names_.erase(names_.begin()+i); ChunkArrayGen::skip(fs); } } diff --git a/cgogn/core/container/chunk_array_factory.h b/cgogn/core/container/chunk_array_factory.h index 8c459355..98b3136e 100644 --- a/cgogn/core/container/chunk_array_factory.h +++ b/cgogn/core/container/chunk_array_factory.h @@ -47,7 +47,6 @@ class ChunkArrayFactory typedef std::map NamePtrMap; static NamePtrMap map_CA_; - static bool known_types_initialized_; /** * @brief register a type @@ -64,6 +63,8 @@ class ChunkArrayFactory static void register_known_types() { + static bool known_types_initialized_ = false; + if (known_types_initialized_) return; @@ -118,9 +119,6 @@ class ChunkArrayFactory template typename ChunkArrayFactory::NamePtrMap ChunkArrayFactory::map_CA_= typename ChunkArrayFactory::NamePtrMap(); -template -bool ChunkArrayFactory::known_types_initialized_= false; - #if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_CONTAINER_CHUNK_ARRAY_FACTORY_CPP_)) extern template class CGOGN_CORE_API ChunkArrayFactory; From 850cc6f7715570a95604804a4a1c7b1bbfa42ad9 Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Sat, 6 Feb 2016 23:27:33 +0100 Subject: [PATCH 051/402] change variable name --- cgogn/core/cmap/cmap1.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 1d9d9e6d..7b9f7011 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -343,9 +343,9 @@ class CMap1_T : public MapBase public: - inline unsigned int degree(Face d) const + inline unsigned int degree(Face f) const { - return this->nb_darts(d); + return this->nb_darts(f); } protected: From cb5dbc9aa8f4609145055e5e12646fa2138d97aa Mon Sep 17 00:00:00 2001 From: lionel untereiner Date: Mon, 8 Feb 2016 11:14:50 +0100 Subject: [PATCH 052/402] revert cmap2 --- cgogn/core/cmap/cmap2.h | 109 ---------------------------------------- 1 file changed, 109 deletions(-) diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 1e3fce63..6f530012 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -260,120 +260,11 @@ class CMap2_T : public CMap1_T return f; } - inline Vertex cut_edge(Edge e) - { - Dart nd = cut_edge_topo(e); - - Vertex v(nd); - - if(this->template is_orbit_embedded()) - { - init_orbit_embedding(this->phi1(e), this->template add_attribute_element()); - init_orbit_embedding(phi2(e), this->template add_attribute_element()); - } - - if (this->template is_orbit_embedded()) - { - init_orbit_embedding(v, this->template add_attribute_element()); - } - - if (this->template is_orbit_embedded()) - { - this->template init_embedding(phi2(e), this->template get_embedding(e)); - init_orbit_embedding(this->phi1(e), this->template add_attribute_element()); - } - - if (this->template is_orbit_embedded()) - { - this->template init_embedding(nd, this->template get_embedding(e.dart)); - Dart nd2 = phi2(nd); - this->template init_embedding(this->phi1(nd2), this->template get_embedding(nd2)); - } - - if (this->template is_orbit_embedded()) - { - this->template init_embedding(nd, this->template get_embedding(e.dart)); - Dart nd2 = phi2(nd); - this->template init_embedding(this->phi1(nd2), this->template get_embedding(nd2)); - } - - return v; - } - - inline void split_face(Dart d, Dart e) - { - split_face_topo(d,e); - - if(this->template is_orbit_embedded()) - { - init_orbit_embedding(this->phi_1(e), this->template add_attribute_element()); - init_orbit_embedding(this->phi_1(d), this->template add_attribute_element()); - } - - if (this->template is_orbit_embedded()) - { - this->template init_embedding(this->phi_1(e), this->template get_embedding(d)); - this->template init_embedding(this->phi_1(d), this->template get_embedding(e)); - } - - if (this->template is_orbit_embedded()) - { - init_orbit_embedding(this->phi_1(d), this->template add_attribute_element()); - } - - if (this->template is_orbit_embedded()) - { - this->template init_embedding(this->phi_1(d), this->template get_embedding(d)); - init_orbit_embedding(e, this->template add_attribute_element()); - } - - if (this->template is_orbit_embedded()) - { - init_orbit_embedding(this->phi_1(e), this->template get_embedding(d)); - init_orbit_embedding(this->phi_1(d), this->template get_embedding(d)); - } - } - - inline unsigned int degree(Face f) const { return Inherit::degree(f); } - -protected: - - inline Dart cut_edge_topo(Dart d) - { - Dart e = phi2(d); - - //remove old phi2 links - phi2_unsew(d); - - //cut the 1-edge of d - Dart nd = Inherit::cut_edge_topo(d); - //cut the 1-edge of e = phi2(d) - Dart ne = Inherit::cut_edge_topo(e); - - //add new phi2links - phi2_sew(d, ne); - phi2_sew(e, nd); - - return nd; - } - - inline void split_face_topo(Dart d, Dart e) - { - cgogn_message_assert(d != e, "split_face: d == e"); - // cgogn_message_assert(this->same_face(d,e), "split_face: d et e are not from same face"); - - Dart dd = Inherit::cut_edge_topo(this->phi_1(d)); - Dart ee = Inherit::cut_edge_topo(this->phi_1(e)); - - Inherit::split_face_topo(dd, ee); - phi2_sew(dd, ee); - } - protected: inline void close_hole_topo(Dart d) From 4167e38d7dae478812c2633e7235987280fb7485 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Mon, 8 Feb 2016 18:40:25 +0100 Subject: [PATCH 053/402] CMap2 : cut_edge and split_face --- cgogn/core/cmap/cmap1.h | 11 ++-- cgogn/core/cmap/cmap2.h | 109 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 111 insertions(+), 9 deletions(-) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 7b9f7011..8ae80dda 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -301,15 +301,10 @@ class CMap1_T : public MapBase { cgogn_assert(d != e && !this->same_cell(Face(d), Face(e))); - // cut the edge before d (insert a new dart before d) - cut_edge_topo(phi_1(d)); + Dart nd = cut_edge_topo(phi_1(d)); // cut the edge before d (insert a new dart before d) + Dart ne = cut_edge_topo(phi_1(e)); // cut the edge before e (insert a new dart before e) - // cut the edge before e (insert a new dart before e) - cut_edge_topo(phi_1(e)); - - // phi1sew between the 2 new inserted darts - phi1_sew(phi_1(d), phi_1(e)); - + phi1_sew(nd, ne); // subdivide phi1 cycle at the inserted darts } inline void reverse_face_topo(Dart d) diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 6f530012..efc6a92b 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -260,13 +260,120 @@ class CMap2_T : public CMap1_T return f; } - inline unsigned int degree(Face f) const + inline Vertex cut_edge(Edge d) + { + Dart e = phi2(d); + Dart nd = cut_edge_topo(d); + Dart ne = phi2(nd); + + Vertex v(nd); + + if(this->template is_orbit_embedded()) + { + this->template init_embedding(nd, this->template add_attribute_element()); + this->template init_embedding(ne, this->template add_attribute_element()); + } + + if (this->template is_orbit_embedded()) + { + init_orbit_embedding(v, this->template add_attribute_element()); + } + + if (this->template is_orbit_embedded()) + { + this->template init_embedding(ne, this->template get_embedding(d.dart)); + // pour que le unref du set_orbit suivant fonctionne + this->template init_embedding(nd, this->template get_embedding(e)); + set_orbit_embedding(nd, this->template add_attribute_element()); + } + + if (this->template is_orbit_embedded()) + { + this->template init_embedding(nd, this->template get_embedding(d.dart)); + this->template init_embedding(ne, this->template get_embedding(e)); + } + + if (this->template is_orbit_embedded()) + { + this->template init_embedding(nd, this->template get_embedding(d.dart)); + this->template init_embedding(ne, this->template get_embedding(e)); + } + + return v; + } + + inline void split_face(Dart d, Dart e) + { + split_face_topo(d,e); + Dart nd = this->phi_1(e); + Dart ne = this->phi_1(d); + + if(this->template is_orbit_embedded()) + { + this->template init_embedding(nd, this->template add_attribute_element()); + this->template init_embedding(ne, this->template add_attribute_element()); + } + + if (this->template is_orbit_embedded()) + { + this->template init_embedding(nd, this->template get_embedding(d)); + this->template init_embedding(ne, this->template get_embedding(e)); + } + + if (this->template is_orbit_embedded()) + { + init_orbit_embedding(nd, this->template add_attribute_element()); + } + + if (this->template is_orbit_embedded()) + { + this->template init_embedding(ne, this->template get_embedding(d)); + // pour que le unref du set_orbit suivant fonctionne + this->template init_embedding(nd, this->template get_embedding(e)); + init_orbit_embedding(e, this->template add_attribute_element()); + } + + if (this->template is_orbit_embedded()) + { + init_orbit_embedding(nd, this->template get_embedding(d)); + init_orbit_embedding(ne, this->template get_embedding(d)); + } + } + + inline unsigned int degree(Face f) const { return Inherit::degree(f); } protected: + inline Dart cut_edge_topo(Dart d) + { + Dart e = phi2(d); // Get the adjacent 1D-edge + + phi2_unsew(d); // Unsew the initial 2D-edge, + // separating its two 1D-edges + Dart nd = Inherit::cut_edge_topo(d); + Dart ne = Inherit::cut_edge_topo(e); // Cut the two adjacent 1D-edges + + phi2_sew(d, ne); // Sew the new 1D-edges + phi2_sew(e, nd); // To build the new 2D-edges + + return nd; + } + + inline void split_face_topo(Dart d, Dart e) + { + cgogn_message_assert(d != e, "split_face: d and e should be distinct"); + cgogn_message_assert(this->same_cell(Face(d), Face(e)), "split_face: d and e should belong to the same face"); + + Dart nd = Inherit::cut_edge_topo(this->phi_1(d)); // cut the edge before d (insert a new dart before d) + Dart ne = Inherit::cut_edge_topo(this->phi_1(e)); // cut the edge before e (insert a new dart before e) + + Inherit::split_face_topo(nd, ne); // subdivide phi1 cycle at the inserted darts + phi2_sew(nd, ne); // build the new 2D-edge from the inserted darts + } + inline void close_hole_topo(Dart d) { cgogn_message_assert(phi2(d) == d, "CMap2: close hole called on a dart that is not a phi2 fix point"); From eae118b725e02a02179d6f0b8a10deeb18b5ce6d Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Tue, 9 Feb 2016 09:52:02 +0100 Subject: [PATCH 054/402] embnull is back --- cgogn/core/basic/cell.h | 3 +- cgogn/core/cmap/cmap1.h | 32 ++--------------- cgogn/core/cmap/cmap2.h | 36 +++++--------------- cgogn/core/cmap/cmap2_builder.h | 4 +-- cgogn/core/cmap/cmap3.h | 18 ---------- cgogn/core/cmap/cmap3_builder.h | 4 +-- cgogn/core/cmap/map_base.h | 32 +++++++++++++++-- cgogn/core/cmap/map_base_data.h | 16 +++------ cgogn/core/container/chunk_array_container.h | 2 ++ cgogn/io/surface_import.h | 2 +- 10 files changed, 53 insertions(+), 96 deletions(-) diff --git a/cgogn/core/basic/cell.h b/cgogn/core/basic/cell.h index 3bbbe5ef..d5508e3e 100644 --- a/cgogn/core/basic/cell.h +++ b/cgogn/core/basic/cell.h @@ -50,6 +50,8 @@ enum Orbit: unsigned int static const std::size_t NB_ORBITS = Orbit::PHI21_PHI31 + 1; +static const unsigned int EMBNULL = 0xffffffff; + inline std::string orbit_name(Orbit orbit) { switch(orbit) @@ -67,7 +69,6 @@ inline std::string orbit_name(Orbit orbit) return "UNKNOWN"; } - /** * \brief Cellular typing * diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 7b9f7011..870f439e 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -185,16 +185,6 @@ class CMap1_T : public MapBase inline void delete_dart(Dart d) { this->remove_topology_element(d.index); - - for(unsigned int orbit = 0; orbit < NB_ORBITS; ++orbit) - { - if(this->embeddings_[orbit]) - { - // get the embedding of the dart - unsigned int emb = (*this->embeddings_[orbit])[d.index]; - this->attributes_[orbit].unref_line(emb); - } - } } public: @@ -220,12 +210,12 @@ class CMap1_T : public MapBase { foreach_incident_vertex(f, [this] (Cell c) { - init_orbit_embedding(c, this->template add_attribute_element()); + this->template set_orbit_embedding(c, this->template add_attribute_element()); }); } if (this->template is_orbit_embedded()) - init_orbit_embedding(f, this->template add_attribute_element()); + this->template set_orbit_embedding(f, this->template add_attribute_element()); return f; } @@ -463,24 +453,6 @@ class CMap1_T : public MapBase f(Edge(phi1(e.dart))); f(Edge(phi_1(e.dart))); } - -protected: - - /******************************************************************************* - * Embedding management - *******************************************************************************/ - - template - inline void init_orbit_embedding(Cell c, unsigned int emb) - { - foreach_dart_of_orbit(c, [this, emb] (Dart d) { this->template init_embedding(d, emb); }); - } - - template - inline void set_orbit_embedding(Cell c, unsigned int emb) - { - foreach_dart_of_orbit(c, [this, emb] (Dart d) { this->template set_embedding(d, emb); }); - } }; template diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 6f530012..b7b16024 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -180,26 +180,26 @@ class CMap2_T : public CMap1_T { foreach_dart_of_orbit(new_face, [this] (Dart fd) { - init_orbit_embedding(fd, this->template add_attribute_element()); + this->template set_orbit_embedding(fd, this->template add_attribute_element()); }); } if (this->template is_orbit_embedded()) { foreach_dart_of_orbit(new_face, [this] (Dart fd) { - this->template init_embedding(fd, this->template get_embedding(this->phi1(phi2(fd)))); + this->template set_embedding(fd, this->template get_embedding(this->phi1(phi2(fd)))); }); } if (this->template is_orbit_embedded()) { foreach_dart_of_orbit(new_face, [this] (Dart fd) { - this->template init_embedding(fd, this->template get_embedding(phi2(fd))); + this->template set_embedding(fd, this->template get_embedding(phi2(fd))); }); } if (this->template is_orbit_embedded()) { - init_orbit_embedding(new_face, this->template add_attribute_element()); + this->template set_orbit_embedding(new_face, this->template add_attribute_element()); } } } @@ -231,7 +231,7 @@ class CMap2_T : public CMap1_T { foreach_dart_of_orbit(f, [this] (Dart fd) { - init_orbit_embedding(fd, this->template add_attribute_element()); + this->template set_orbit_embedding(fd, this->template add_attribute_element()); }); } @@ -239,7 +239,7 @@ class CMap2_T : public CMap1_T { foreach_incident_vertex(f, [this] (Cell c) { - init_orbit_embedding(c, this->template add_attribute_element()); + this->template set_orbit_embedding(c, this->template add_attribute_element()); }); } @@ -247,15 +247,15 @@ class CMap2_T : public CMap1_T { foreach_incident_edge(f, [this] (Cell c) { - init_orbit_embedding(c, this->template add_attribute_element()); + this->template set_orbit_embedding(c, this->template add_attribute_element()); }); } if (this->template is_orbit_embedded()) - init_orbit_embedding(f, this->template add_attribute_element()); + this->template set_orbit_embedding(f, this->template add_attribute_element()); if (this->template is_orbit_embedded()) - init_orbit_embedding(d, this->template add_attribute_element()); + this->template set_orbit_embedding(d, this->template add_attribute_element()); return f; } @@ -617,24 +617,6 @@ class CMap2_T : public CMap1_T static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); foreach_dart_of_orbit(f, [this, &func] (Dart d) { func(Face(this->phi2(d))); }); } - -protected: - - /******************************************************************************* - * Embedding management - *******************************************************************************/ - - template - inline void init_orbit_embedding(Cell c, unsigned int emb) - { - foreach_dart_of_orbit(c, [this, emb] (Dart d) { this->template init_embedding(d, emb); }); - } - - template - inline void set_orbit_embedding(Cell c, unsigned int emb) - { - foreach_dart_of_orbit(c, [this, emb] (Dart d) { this->template set_embedding(d, emb); }); - } }; template diff --git a/cgogn/core/cmap/cmap2_builder.h b/cgogn/core/cmap/cmap2_builder.h index 08676611..c863c5c9 100644 --- a/cgogn/core/cmap/cmap2_builder.h +++ b/cgogn/core/cmap/cmap2_builder.h @@ -63,9 +63,9 @@ class CMap2Builder_T } template - inline void init_embedding(Dart d, unsigned int emb) + inline void set_embedding(Dart d, unsigned int emb) { - map_.template init_embedding(d, emb); + map_.template set_embedding(d, emb); } inline void phi2_sew(Dart d, Dart e) diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 95ede0b9..85396a76 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -839,24 +839,6 @@ class CMap3_T : public CMap2_T }); }); } - -protected: - - /******************************************************************************* - * Embedding management - *******************************************************************************/ - - template - inline void init_orbit_embedding(Cell c, unsigned int emb) - { - foreach_dart_of_orbit(c, [this, emb] (Dart d) { this->template init_embedding(d, emb); }); - } - - template - inline void set_orbit_embedding(Cell c, unsigned int emb) - { - foreach_dart_of_orbit(c, [this, emb] (Dart d) { this->template set_embedding(d, emb); }); - } }; template diff --git a/cgogn/core/cmap/cmap3_builder.h b/cgogn/core/cmap/cmap3_builder.h index 61c11251..8e0a9cb3 100644 --- a/cgogn/core/cmap/cmap3_builder.h +++ b/cgogn/core/cmap/cmap3_builder.h @@ -70,9 +70,9 @@ class CMap3Builder_T inline void init_parent_vertex_embedding(Dart d, unsigned int emb) { - map_.foreach_dart_of_PHI21(d,[&](Dart dit) + map_.foreach_dart_of_PHI21(d, [&] (Dart dit) { - map_.template init_embedding(dit,emb); + map_.template set_embedding(dit, emb); }); } diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index f91eaa7c..5ff870af 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -144,6 +144,11 @@ class MapBase : public MapBaseData { unsigned int idx = this->topology_.template insert_lines(); this->topology_.init_markers_of_line(idx); + for(unsigned int orbit = 0; orbit < NB_ORBITS; ++orbit) + { + if(this->embeddings_[orbit]) + (*this->embeddings_[orbit])[idx] = EMBNULL; + } return idx; } @@ -159,6 +164,15 @@ class MapBase : public MapBaseData inline void remove_topology_element(unsigned int index) { this->topology_.template remove_lines(index); + + for(unsigned int orbit = 0; orbit < NB_ORBITS; ++orbit) + { + if(this->embeddings_[orbit]) + { + unsigned int emb = (*this->embeddings_[orbit])[index]; + this->attributes_[orbit].unref_line(emb); + } + } } template @@ -309,14 +323,26 @@ class MapBase : public MapBaseData ChunkArray* ca = this->topology_.template add_attribute(oss.str()); this->embeddings_[ORBIT] = ca; + // initialize all darts indices to EMBNULL for this ORBIT + foreach_dart([this] (Dart d) + { + (*this->embeddings_[ORBIT])[d.index] = EMBNULL; + }); + // initialize the indices of the existing orbits - ConcreteMap* cmap = to_concrete(); - foreach_cell([cmap] (Cell c) + foreach_cell([this] (Cell c) { - cmap->init_orbit_embedding(c, cmap->template add_attribute_element()); + set_orbit_embedding(c, add_attribute_element()); }); } + template + inline void set_orbit_embedding(Cell c, unsigned int emb) + { + ConcreteMap* cmap = to_concrete(); + cmap->foreach_dart_of_orbit(c, [cmap, emb] (Dart d) { cmap->template set_embedding(d, emb); }); + } + public: /** diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index dbc16150..2f3e176a 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -244,33 +244,25 @@ class MapBaseData : public MapGen { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); cgogn_message_assert(is_orbit_embedded(), "Invalid parameter: orbit not embedded"); + cgogn_message_assert((*embeddings_[ORBIT])[c.dart.index] != EMBNULL, "get_embedding result is EMBNULL"); return (*embeddings_[ORBIT])[c.dart.index]; } protected: - template - inline void init_embedding(Dart d, unsigned int emb) - { - static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - cgogn_message_assert(is_orbit_embedded(), "Invalid parameter: orbit not embedded"); - - this->attributes_[ORBIT].ref_line(emb); // ref the new emb - (*this->embeddings_[ORBIT])[d.index] = emb; // affect the embedding to the dart - } - template inline void set_embedding(Dart d, unsigned int emb) { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); cgogn_message_assert(is_orbit_embedded(), "Invalid parameter: orbit not embedded"); - unsigned int old = get_embedding(d); + unsigned int old = (*embeddings_[ORBIT])[d.index]; if (old == emb) return; - this->attributes_[ORBIT].unref_line(old); // unref the old emb + if (old != EMBNULL) + this->attributes_[ORBIT].unref_line(old); // unref the old emb this->attributes_[ORBIT].ref_line(emb); // ref the new emb (*this->embeddings_[ORBIT])[d.index] = emb; // affect the embedding to the dart diff --git a/cgogn/core/container/chunk_array_container.h b/cgogn/core/container/chunk_array_container.h index 073613d1..ea5ed42a 100644 --- a/cgogn/core/container/chunk_array_container.h +++ b/cgogn/core/container/chunk_array_container.h @@ -819,6 +819,8 @@ class ChunkArrayContainer bool unref_line(unsigned int index) { // static_assert(PRIMSIZE == 1u, "unrefLine with container where PRIMSIZE!=1"); + cgogn_message_assert(refs_[index] > 1u, "Container: unref line with nb_ref == 1"); + refs_[index]--; if (refs_[index] == 1u) { diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index a1b38024..f201161f 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -197,7 +197,7 @@ class SurfaceImport for (unsigned int j = 0; j < nbe; ++j) { unsigned int vertex_index = vertices_buffer[j]; - mbuild.template init_embedding(d, vertex_index); + mbuild.template set_embedding(d, vertex_index); darts_per_vertex[vertex_index].push_back(d); d = map.phi1(d); } From b7ac622cbd38e6f4e42ac937b7491074614374dc Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Tue, 9 Feb 2016 09:57:12 +0100 Subject: [PATCH 055/402] 0xfff.. -> UINT_MAX --- cgogn/core/basic/cell.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cgogn/core/basic/cell.h b/cgogn/core/basic/cell.h index d5508e3e..fde1464d 100644 --- a/cgogn/core/basic/cell.h +++ b/cgogn/core/basic/cell.h @@ -29,6 +29,8 @@ #include #include +#include + /** * \file core/basic/cell.h * \brief Orbit and cell definitions used in cgogn. @@ -50,7 +52,7 @@ enum Orbit: unsigned int static const std::size_t NB_ORBITS = Orbit::PHI21_PHI31 + 1; -static const unsigned int EMBNULL = 0xffffffff; +static const unsigned int EMBNULL = UINT_MAX; inline std::string orbit_name(Orbit orbit) { From 806c598ad942fa1ae6d3863736d21525f3bc9645 Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Sat, 6 Feb 2016 23:27:33 +0100 Subject: [PATCH 056/402] change variable name --- cgogn/core/cmap/cmap1.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 1d9d9e6d..7b9f7011 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -343,9 +343,9 @@ class CMap1_T : public MapBase public: - inline unsigned int degree(Face d) const + inline unsigned int degree(Face f) const { - return this->nb_darts(d); + return this->nb_darts(f); } protected: From 19d4dd67a658158c260a069fa9b23318f8a3aa14 Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Tue, 9 Feb 2016 09:52:02 +0100 Subject: [PATCH 057/402] embnull is back --- cgogn/core/basic/cell.h | 3 +- cgogn/core/cmap/cmap1.h | 32 ++--------------- cgogn/core/cmap/cmap2.h | 36 +++++--------------- cgogn/core/cmap/cmap2_builder.h | 4 +-- cgogn/core/cmap/cmap3.h | 18 ---------- cgogn/core/cmap/cmap3_builder.h | 4 +-- cgogn/core/cmap/map_base.h | 32 +++++++++++++++-- cgogn/core/cmap/map_base_data.h | 16 +++------ cgogn/core/container/chunk_array_container.h | 2 ++ cgogn/io/surface_import.h | 2 +- 10 files changed, 53 insertions(+), 96 deletions(-) diff --git a/cgogn/core/basic/cell.h b/cgogn/core/basic/cell.h index 3bbbe5ef..d5508e3e 100644 --- a/cgogn/core/basic/cell.h +++ b/cgogn/core/basic/cell.h @@ -50,6 +50,8 @@ enum Orbit: unsigned int static const std::size_t NB_ORBITS = Orbit::PHI21_PHI31 + 1; +static const unsigned int EMBNULL = 0xffffffff; + inline std::string orbit_name(Orbit orbit) { switch(orbit) @@ -67,7 +69,6 @@ inline std::string orbit_name(Orbit orbit) return "UNKNOWN"; } - /** * \brief Cellular typing * diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 7b9f7011..870f439e 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -185,16 +185,6 @@ class CMap1_T : public MapBase inline void delete_dart(Dart d) { this->remove_topology_element(d.index); - - for(unsigned int orbit = 0; orbit < NB_ORBITS; ++orbit) - { - if(this->embeddings_[orbit]) - { - // get the embedding of the dart - unsigned int emb = (*this->embeddings_[orbit])[d.index]; - this->attributes_[orbit].unref_line(emb); - } - } } public: @@ -220,12 +210,12 @@ class CMap1_T : public MapBase { foreach_incident_vertex(f, [this] (Cell c) { - init_orbit_embedding(c, this->template add_attribute_element()); + this->template set_orbit_embedding(c, this->template add_attribute_element()); }); } if (this->template is_orbit_embedded()) - init_orbit_embedding(f, this->template add_attribute_element()); + this->template set_orbit_embedding(f, this->template add_attribute_element()); return f; } @@ -463,24 +453,6 @@ class CMap1_T : public MapBase f(Edge(phi1(e.dart))); f(Edge(phi_1(e.dart))); } - -protected: - - /******************************************************************************* - * Embedding management - *******************************************************************************/ - - template - inline void init_orbit_embedding(Cell c, unsigned int emb) - { - foreach_dart_of_orbit(c, [this, emb] (Dart d) { this->template init_embedding(d, emb); }); - } - - template - inline void set_orbit_embedding(Cell c, unsigned int emb) - { - foreach_dart_of_orbit(c, [this, emb] (Dart d) { this->template set_embedding(d, emb); }); - } }; template diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 6f530012..b7b16024 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -180,26 +180,26 @@ class CMap2_T : public CMap1_T { foreach_dart_of_orbit(new_face, [this] (Dart fd) { - init_orbit_embedding(fd, this->template add_attribute_element()); + this->template set_orbit_embedding(fd, this->template add_attribute_element()); }); } if (this->template is_orbit_embedded()) { foreach_dart_of_orbit(new_face, [this] (Dart fd) { - this->template init_embedding(fd, this->template get_embedding(this->phi1(phi2(fd)))); + this->template set_embedding(fd, this->template get_embedding(this->phi1(phi2(fd)))); }); } if (this->template is_orbit_embedded()) { foreach_dart_of_orbit(new_face, [this] (Dart fd) { - this->template init_embedding(fd, this->template get_embedding(phi2(fd))); + this->template set_embedding(fd, this->template get_embedding(phi2(fd))); }); } if (this->template is_orbit_embedded()) { - init_orbit_embedding(new_face, this->template add_attribute_element()); + this->template set_orbit_embedding(new_face, this->template add_attribute_element()); } } } @@ -231,7 +231,7 @@ class CMap2_T : public CMap1_T { foreach_dart_of_orbit(f, [this] (Dart fd) { - init_orbit_embedding(fd, this->template add_attribute_element()); + this->template set_orbit_embedding(fd, this->template add_attribute_element()); }); } @@ -239,7 +239,7 @@ class CMap2_T : public CMap1_T { foreach_incident_vertex(f, [this] (Cell c) { - init_orbit_embedding(c, this->template add_attribute_element()); + this->template set_orbit_embedding(c, this->template add_attribute_element()); }); } @@ -247,15 +247,15 @@ class CMap2_T : public CMap1_T { foreach_incident_edge(f, [this] (Cell c) { - init_orbit_embedding(c, this->template add_attribute_element()); + this->template set_orbit_embedding(c, this->template add_attribute_element()); }); } if (this->template is_orbit_embedded()) - init_orbit_embedding(f, this->template add_attribute_element()); + this->template set_orbit_embedding(f, this->template add_attribute_element()); if (this->template is_orbit_embedded()) - init_orbit_embedding(d, this->template add_attribute_element()); + this->template set_orbit_embedding(d, this->template add_attribute_element()); return f; } @@ -617,24 +617,6 @@ class CMap2_T : public CMap1_T static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); foreach_dart_of_orbit(f, [this, &func] (Dart d) { func(Face(this->phi2(d))); }); } - -protected: - - /******************************************************************************* - * Embedding management - *******************************************************************************/ - - template - inline void init_orbit_embedding(Cell c, unsigned int emb) - { - foreach_dart_of_orbit(c, [this, emb] (Dart d) { this->template init_embedding(d, emb); }); - } - - template - inline void set_orbit_embedding(Cell c, unsigned int emb) - { - foreach_dart_of_orbit(c, [this, emb] (Dart d) { this->template set_embedding(d, emb); }); - } }; template diff --git a/cgogn/core/cmap/cmap2_builder.h b/cgogn/core/cmap/cmap2_builder.h index 08676611..c863c5c9 100644 --- a/cgogn/core/cmap/cmap2_builder.h +++ b/cgogn/core/cmap/cmap2_builder.h @@ -63,9 +63,9 @@ class CMap2Builder_T } template - inline void init_embedding(Dart d, unsigned int emb) + inline void set_embedding(Dart d, unsigned int emb) { - map_.template init_embedding(d, emb); + map_.template set_embedding(d, emb); } inline void phi2_sew(Dart d, Dart e) diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 95ede0b9..85396a76 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -839,24 +839,6 @@ class CMap3_T : public CMap2_T }); }); } - -protected: - - /******************************************************************************* - * Embedding management - *******************************************************************************/ - - template - inline void init_orbit_embedding(Cell c, unsigned int emb) - { - foreach_dart_of_orbit(c, [this, emb] (Dart d) { this->template init_embedding(d, emb); }); - } - - template - inline void set_orbit_embedding(Cell c, unsigned int emb) - { - foreach_dart_of_orbit(c, [this, emb] (Dart d) { this->template set_embedding(d, emb); }); - } }; template diff --git a/cgogn/core/cmap/cmap3_builder.h b/cgogn/core/cmap/cmap3_builder.h index 61c11251..8e0a9cb3 100644 --- a/cgogn/core/cmap/cmap3_builder.h +++ b/cgogn/core/cmap/cmap3_builder.h @@ -70,9 +70,9 @@ class CMap3Builder_T inline void init_parent_vertex_embedding(Dart d, unsigned int emb) { - map_.foreach_dart_of_PHI21(d,[&](Dart dit) + map_.foreach_dart_of_PHI21(d, [&] (Dart dit) { - map_.template init_embedding(dit,emb); + map_.template set_embedding(dit, emb); }); } diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index f91eaa7c..5ff870af 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -144,6 +144,11 @@ class MapBase : public MapBaseData { unsigned int idx = this->topology_.template insert_lines(); this->topology_.init_markers_of_line(idx); + for(unsigned int orbit = 0; orbit < NB_ORBITS; ++orbit) + { + if(this->embeddings_[orbit]) + (*this->embeddings_[orbit])[idx] = EMBNULL; + } return idx; } @@ -159,6 +164,15 @@ class MapBase : public MapBaseData inline void remove_topology_element(unsigned int index) { this->topology_.template remove_lines(index); + + for(unsigned int orbit = 0; orbit < NB_ORBITS; ++orbit) + { + if(this->embeddings_[orbit]) + { + unsigned int emb = (*this->embeddings_[orbit])[index]; + this->attributes_[orbit].unref_line(emb); + } + } } template @@ -309,14 +323,26 @@ class MapBase : public MapBaseData ChunkArray* ca = this->topology_.template add_attribute(oss.str()); this->embeddings_[ORBIT] = ca; + // initialize all darts indices to EMBNULL for this ORBIT + foreach_dart([this] (Dart d) + { + (*this->embeddings_[ORBIT])[d.index] = EMBNULL; + }); + // initialize the indices of the existing orbits - ConcreteMap* cmap = to_concrete(); - foreach_cell([cmap] (Cell c) + foreach_cell([this] (Cell c) { - cmap->init_orbit_embedding(c, cmap->template add_attribute_element()); + set_orbit_embedding(c, add_attribute_element()); }); } + template + inline void set_orbit_embedding(Cell c, unsigned int emb) + { + ConcreteMap* cmap = to_concrete(); + cmap->foreach_dart_of_orbit(c, [cmap, emb] (Dart d) { cmap->template set_embedding(d, emb); }); + } + public: /** diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index dbc16150..2f3e176a 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -244,33 +244,25 @@ class MapBaseData : public MapGen { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); cgogn_message_assert(is_orbit_embedded(), "Invalid parameter: orbit not embedded"); + cgogn_message_assert((*embeddings_[ORBIT])[c.dart.index] != EMBNULL, "get_embedding result is EMBNULL"); return (*embeddings_[ORBIT])[c.dart.index]; } protected: - template - inline void init_embedding(Dart d, unsigned int emb) - { - static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - cgogn_message_assert(is_orbit_embedded(), "Invalid parameter: orbit not embedded"); - - this->attributes_[ORBIT].ref_line(emb); // ref the new emb - (*this->embeddings_[ORBIT])[d.index] = emb; // affect the embedding to the dart - } - template inline void set_embedding(Dart d, unsigned int emb) { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); cgogn_message_assert(is_orbit_embedded(), "Invalid parameter: orbit not embedded"); - unsigned int old = get_embedding(d); + unsigned int old = (*embeddings_[ORBIT])[d.index]; if (old == emb) return; - this->attributes_[ORBIT].unref_line(old); // unref the old emb + if (old != EMBNULL) + this->attributes_[ORBIT].unref_line(old); // unref the old emb this->attributes_[ORBIT].ref_line(emb); // ref the new emb (*this->embeddings_[ORBIT])[d.index] = emb; // affect the embedding to the dart diff --git a/cgogn/core/container/chunk_array_container.h b/cgogn/core/container/chunk_array_container.h index 073613d1..ea5ed42a 100644 --- a/cgogn/core/container/chunk_array_container.h +++ b/cgogn/core/container/chunk_array_container.h @@ -819,6 +819,8 @@ class ChunkArrayContainer bool unref_line(unsigned int index) { // static_assert(PRIMSIZE == 1u, "unrefLine with container where PRIMSIZE!=1"); + cgogn_message_assert(refs_[index] > 1u, "Container: unref line with nb_ref == 1"); + refs_[index]--; if (refs_[index] == 1u) { diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index a1b38024..f201161f 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -197,7 +197,7 @@ class SurfaceImport for (unsigned int j = 0; j < nbe; ++j) { unsigned int vertex_index = vertices_buffer[j]; - mbuild.template init_embedding(d, vertex_index); + mbuild.template set_embedding(d, vertex_index); darts_per_vertex[vertex_index].push_back(d); d = map.phi1(d); } From 4d7fe42a6f470919726bda0bb50bf9e031d0f1ec Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Tue, 9 Feb 2016 09:57:12 +0100 Subject: [PATCH 058/402] 0xfff.. -> UINT_MAX --- cgogn/core/basic/cell.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cgogn/core/basic/cell.h b/cgogn/core/basic/cell.h index d5508e3e..fde1464d 100644 --- a/cgogn/core/basic/cell.h +++ b/cgogn/core/basic/cell.h @@ -29,6 +29,8 @@ #include #include +#include + /** * \file core/basic/cell.h * \brief Orbit and cell definitions used in cgogn. @@ -50,7 +52,7 @@ enum Orbit: unsigned int static const std::size_t NB_ORBITS = Orbit::PHI21_PHI31 + 1; -static const unsigned int EMBNULL = 0xffffffff; +static const unsigned int EMBNULL = UINT_MAX; inline std::string orbit_name(Orbit orbit) { From eef5c06e50c4e533b9122f38b1215a44f3f35696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 9 Feb 2016 15:09:22 +0100 Subject: [PATCH 059/402] fixed a bug in VolumeImport::create_map MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/volume_import.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/cgogn/io/volume_import.h b/cgogn/io/volume_import.h index 88c0c10d..c5bb3e89 100644 --- a/cgogn/io/volume_import.h +++ b/cgogn/io/volume_import.h @@ -155,9 +155,6 @@ class VolumeImport typename Map::DartMarkerStore m(map); - unsigned int vemb = std::numeric_limits::max(); - //auto fsetemb = [&] (Dart d) { map.template initDartEmbedding(d, vemb); }; - //for each volume of table for(unsigned int i = 0u; i < this->nb_volumes_; ++i) { @@ -243,7 +240,7 @@ class VolumeImport for (Dart dv : vertices_of_prism) { const unsigned int emb = edgesBuffer[buffer_id++]; - mbuild.init_parent_vertex_embedding(dv,vemb); + mbuild.init_parent_vertex_embedding(dv,emb); Dart dd = dv; do From b5cb8b3daddd94d12f620c8090d7856b77d76998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 9 Feb 2016 15:09:57 +0100 Subject: [PATCH 060/402] checking if emb is EMBNULL in set_embedding. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/map_base_data.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index 2f3e176a..ebf5ad31 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -256,14 +256,13 @@ class MapBaseData : public MapGen { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); cgogn_message_assert(is_orbit_embedded(), "Invalid parameter: orbit not embedded"); + cgogn_message_assert(emb != EMBNULL,"cannot set an embedding to EMBNULL."); - unsigned int old = (*embeddings_[ORBIT])[d.index]; - - if (old == emb) return; + const unsigned int old = (*embeddings_[ORBIT])[d.index]; + this->attributes_[ORBIT].ref_line(emb); // ref the new emb if (old != EMBNULL) this->attributes_[ORBIT].unref_line(old); // unref the old emb - this->attributes_[ORBIT].ref_line(emb); // ref the new emb (*this->embeddings_[ORBIT])[d.index] = emb; // affect the embedding to the dart } From a111a7740f4b4d9a99a3fa6bb4ea8735ae16d2a2 Mon Sep 17 00:00:00 2001 From: lionel untereiner Date: Tue, 9 Feb 2016 15:16:21 +0100 Subject: [PATCH 061/402] changing implicit hierarchy (david's idea) --- cgogn/multiresolution/CMakeLists.txt | 7 +- .../cph/{ihcmap_base.h => cph2.h} | 96 ++---------- cgogn/multiresolution/cph/cph_base.h | 141 ++++++++++++++++++ cgogn/multiresolution/cph/ihcmap2.h | 6 +- cgogn/multiresolution/dll.h | 40 +++++ 5 files changed, 201 insertions(+), 89 deletions(-) rename cgogn/multiresolution/cph/{ihcmap_base.h => cph2.h} (57%) create mode 100644 cgogn/multiresolution/cph/cph_base.h create mode 100644 cgogn/multiresolution/dll.h diff --git a/cgogn/multiresolution/CMakeLists.txt b/cgogn/multiresolution/CMakeLists.txt index 4dae2b3f..6af83b1f 100644 --- a/cgogn/multiresolution/CMakeLists.txt +++ b/cgogn/multiresolution/CMakeLists.txt @@ -3,8 +3,13 @@ project(cgogn_multiresolution ) set(HEADER_FILES + dll.h + cph/attribute_handler_cph.h - cph/ihcmap_base.h + + cph/cph_base.h + cph/cph2.h + cph/ihcmap2.h cph/ihcmap2_adaptive.h cph/ihcmap2_regular.h diff --git a/cgogn/multiresolution/cph/ihcmap_base.h b/cgogn/multiresolution/cph/cph2.h similarity index 57% rename from cgogn/multiresolution/cph/ihcmap_base.h rename to cgogn/multiresolution/cph/cph2.h index d53fa63e..a1be2ca3 100644 --- a/cgogn/multiresolution/cph/ihcmap_base.h +++ b/cgogn/multiresolution/cph/cph2.h @@ -21,55 +21,37 @@ * * *******************************************************************************/ -#ifndef MULTIRESOLUTION_CPH_IHCMAP_BASE_H_ -#define MULTIRESOLUTION_CPH_IHCMAP_BASE_H_ +#ifndef MULTIRESOLUTION_CPH_CPH2_BASE_H_ +#define MULTIRESOLUTION_CPH_CPH2_BASE_H_ -#include -#include +#include namespace cgogn { template -class IHCMapBase +class CPH2 : CPHBase { - typedef IHCMapBase Self; - - template - using ChunkArray = cgogn::ChunkArray; - template - using ChunkArrayContainer = cgogn::ChunkArrayContainer; + typedef CPH2 Self; + typedef CPHBase Inherit; protected: - unsigned int current_level_; - unsigned int maximum_level_; - - // DartAttributeHandler dart_level_ ; - // DartAttributeHandler edge_id_ ; - ChunkArray* dart_level_; ChunkArray* edge_id_; - std::vector nb_darts_per_level; - - ChunkArrayContainer& topo_; public: - IHCMapBase(ChunkArrayContainer& topology): - topo_(topology), - current_level_(0), - maximum_level_(0) + CPH2(ChunkArrayContainer& topology): Inherit(topology) { init(); } - ~IHCMapBase() + ~CPH2() { - topo_.remove_attribute(dart_level_); topo_.remove_attribute(edge_id_); } - IHCMapBase(Self const&) = delete; - IHCMapBase(Self &&) = delete; + CPH2(Self const&) = delete; + CPH2(Self &&) = delete; Self& operator=(Self const&) = delete; Self& operator=(Self &&) = delete; @@ -77,54 +59,9 @@ class IHCMapBase void init() { - dart_level_ = topo_.template add_attribute("dartLevel") ; edge_id_ = topo_.template add_attribute("edgeId"); } - /*************************************************** - * LEVELS MANAGEMENT * - ***************************************************/ - - inline unsigned int get_current_level() const - { - return current_level_ ; - } - - inline void set_current_level(unsigned int l) - { - current_level_ = l ; - } - - inline unsigned int get_maximum_level() const - { - return maximum_level_ ; - } - - inline void set_maximum_level(unsigned int l) - { - maximum_level_ = l; - } - - inline unsigned int get_dart_level(Dart d) const - { - return (*dart_level_)[d.index] ; - } - - inline void set_dart_level(Dart d, unsigned int l) - { - (*dart_level_)[d.index] = l ; - } - - inline void inc_current_level() - { - set_current_level(get_current_level() + 1); - } - - inline void dec_current_level() - { - set_current_level(get_current_level() - 1); - } - /*************************************************** * EDGE ID MANAGEMENT * ***************************************************/ @@ -173,20 +110,9 @@ class IHCMapBase return 0u; } - inline void inc_nb_darts(unsigned int level) - { - cgogn_message_assert(level < get_maximum_level(), "inc_nb_darts : already at maximum resolution level"); - nb_darts_per_level[level]++; - } - - inline void new_level_darts() - { - nb_darts_per_level.push_back(0); - } - }; } // namespace cgogn -#endif // MULTIRESOLUTION_CPH_IHCMAP_BASE_H_ +#endif // MULTIRESOLUTION_CPH_CPH2_BASE_H_ diff --git a/cgogn/multiresolution/cph/cph_base.h b/cgogn/multiresolution/cph/cph_base.h new file mode 100644 index 00000000..72e96de3 --- /dev/null +++ b/cgogn/multiresolution/cph/cph_base.h @@ -0,0 +1,141 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef MULTIRESOLUTION_CPH_CPH_BASE_H_ +#define MULTIRESOLUTION_CPH_CPH_BASE_H_ + +#include +#include + +namespace cgogn +{ + +template +class CPHBase +{ + + typedef CPHBase Self; + + template + using ChunkArray = cgogn::ChunkArray; + template + using ChunkArrayContainer = cgogn::ChunkArrayContainer; + +protected: + unsigned int current_level_; + unsigned int maximum_level_; + + ChunkArray* dart_level_; + + std::vector nb_darts_per_level; + + ChunkArrayContainer& topo_; + +public: + CPHBase(ChunkArrayContainer& topology): + topo_(topology), + current_level_(0) + { + init(); + } + + ~CPHBase() + { + topo_.remove_attribute(dart_level_); + } + + CPHBase(Self const&) = delete; + CPHBase(Self &&) = delete; + Self& operator=(Self const&) = delete; + Self& operator=(Self &&) = delete; + +public: + + void init() + { + dart_level_ = topo_.template add_attribute("dartLevel") ; + } + + /*************************************************** + * LEVELS MANAGEMENT * + ***************************************************/ + + inline unsigned int get_current_level() const + { + return current_level_ ; + } + + inline void set_current_level(unsigned int l) + { + current_level_ = l ; + } + + inline unsigned int get_maximum_level() const + { + return maximum_level_ ; + } + + inline void set_maximum_level(unsigned int l) + { + maximum_level_ = l; + } + + inline unsigned int get_dart_level(Dart d) const + { + return (*dart_level_)[d.index] ; + } + + inline void set_dart_level(Dart d, unsigned int l) + { + (*dart_level_)[d.index] = l ; + } + + inline void inc_current_level() + { + set_current_level(get_current_level() + 1); + } + + inline void dec_current_level() + { + set_current_level(get_current_level() - 1); + } + + inline void inc_nb_darts(unsigned int level) + { + cgogn_message_assert(level < get_maximum_level(), "inc_nb_darts : already at maximum resolution level"); + nb_darts_per_level[level]++; + } + + /*************************************************** + * NB DARTS PER LEVEL * + ***************************************************/ + + inline void new_level_darts() + { + nb_darts_per_level.push_back(0); + } +}; + +} + +#endif // MULTIRESOLUTION_CPH_CPH_BASE_H_ diff --git a/cgogn/multiresolution/cph/ihcmap2.h b/cgogn/multiresolution/cph/ihcmap2.h index 4a3c2722..96005da6 100644 --- a/cgogn/multiresolution/cph/ihcmap2.h +++ b/cgogn/multiresolution/cph/ihcmap2.h @@ -25,7 +25,7 @@ #define MULTIRESOLUTION_CPH_IHCMAP2_H_ #include -#include +#include //#include namespace cgogn @@ -54,12 +54,12 @@ class ContainerCPHBrowser : public ContainerBrowser }; template -class IHCMap2_T : public CMap2_T, public IHCMapBase +class IHCMap2_T : public CMap2_T, public CPH2 { public: typedef CMap2_T Inherit_CMAP; - typedef IHCMapBase Inherit_CPH; + typedef CPH2 Inherit_CPH; typedef IHCMap2_T Self; friend typename Self::Inherit_CMAP; diff --git a/cgogn/multiresolution/dll.h b/cgogn/multiresolution/dll.h new file mode 100644 index 00000000..dec04f49 --- /dev/null +++ b/cgogn/multiresolution/dll.h @@ -0,0 +1,40 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef MULTIRESOLUTION_DLL_H_ +#define MULTIRESOLUTION_DLL_H_ + +/** +* \brief Linkage declaration for CGOGN symbols. +*/ +#ifdef WIN32 +#if defined CGOGN_MULTIRESOLUTION_DLL_EXPORT +#define CGOGN_MULTIRESOLUTION_API __declspec(dllexport) +#else +#define CGOGN_MULTIRESOLUTION_API __declspec(dllimport) +#endif +#else +#define CGOGN_MULTIRESOLUTION_API +#endif + +#endif // MULTIRESOLUTION_DLL_H_ From a3373bbbad79469e02d75aa1ab9abee4a890f9f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 9 Feb 2016 15:28:46 +0100 Subject: [PATCH 062/402] removed unused allocators. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/utils/allocator.cpp | 7 --- cgogn/core/utils/allocator.h | 82 ---------------------------------- 2 files changed, 89 deletions(-) delete mode 100644 cgogn/core/utils/allocator.cpp delete mode 100644 cgogn/core/utils/allocator.h diff --git a/cgogn/core/utils/allocator.cpp b/cgogn/core/utils/allocator.cpp deleted file mode 100644 index 408c6ddc..00000000 --- a/cgogn/core/utils/allocator.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "allocator.h" - -namespace cgogn -{ - - -} diff --git a/cgogn/core/utils/allocator.h b/cgogn/core/utils/allocator.h deleted file mode 100644 index bfbedd24..00000000 --- a/cgogn/core/utils/allocator.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef UTILS_ALLOCATOR_H -#define UTILS_ALLOCATOR_H -#include -#include -namespace cgogn { - -struct Chunk -{ - typedef unsigned char uchar; - void init(std::size_t blockSize, uchar blocks) - { - assert(blocks > 0); - // Overflow check - const ::std::size_t allocSize = blockSize * blocks; - assert( allocSize / blockSize == blocks); - _pData = new uchar[blockSize * blocks]; - _firstAvailableBlock = 0; - _blocksAvailable = blocks; - uchar i{0}; - uchar* p = _pData; - for(; i != blocks ; p+=blockSize) - { - *p = ++i; - } - } - - inline bool isFilled() const - { - return _blocksAvailable == uchar(0); - } - - inline bool hasAvailable( unsigned char numBlocks ) const - { - return ( _blocksAvailable == numBlocks ); - } - - void* allocate(std::size_t blockSize) - { - if (isFilled()) - return nullptr; - - uchar* result = _pData + (_firstAvailableBlock * blockSize); - //update firstavailableblock to point to the next block - _firstAvailableBlock = *result; - --_blocksAvailable; - return result; - } - - void deallocate(void* p, std::size_t blockSize) - { - assert( p >= _pData ); - uchar* toRelease = static_cast(p); - // Alignment check - assert((toRelease - _pData) % blockSize == 0); - const unsigned char index = static_cast< unsigned char >(( toRelease - _pData ) / blockSize); -#if defined(DEBUG) || defined(_DEBUG) - // Check if block was already deleted. Attempting to delete the same - // block more than once causes Chunk's linked-list of stealth indexes to - // become corrupt. And causes count of blocksAvailable_ to be wrong. - if ( 0 < _blocksAvailable ) - assert( _firstAvailableBlock != index ); -#endif - *toRelease = _firstAvailableBlock; - _firstAvailableBlock = static_cast( index ); - ++_blocksAvailable; - } - - void release() - { - assert( _pData != nullptr); - delete[] _pData; - - } - - unsigned char* _pData; - unsigned char _firstAvailableBlock; - unsigned char _blocksAvailable; -}; -} - -#endif // UTILS_ALLOCATOR_H - From 9ec20409b0ddc7800c2efed0b1ff9542ae177af5 Mon Sep 17 00:00:00 2001 From: lionel untereiner Date: Tue, 9 Feb 2016 15:55:00 +0100 Subject: [PATCH 063/402] adding cph3 management and ihcmap3 --- cgogn/multiresolution/CMakeLists.txt | 4 +- cgogn/multiresolution/cph/cph2.h | 21 +- cgogn/multiresolution/cph/cph3.h | 92 +++++ cgogn/multiresolution/cph/cph_base.h | 179 ++++----- cgogn/multiresolution/cph/ihcmap2_regular.h | 30 +- ihcmap3.h | 407 ++++++++++++++++++++ 6 files changed, 620 insertions(+), 113 deletions(-) create mode 100644 cgogn/multiresolution/cph/cph3.h create mode 100644 ihcmap3.h diff --git a/cgogn/multiresolution/CMakeLists.txt b/cgogn/multiresolution/CMakeLists.txt index 6af83b1f..2708c924 100644 --- a/cgogn/multiresolution/CMakeLists.txt +++ b/cgogn/multiresolution/CMakeLists.txt @@ -6,13 +6,13 @@ set(HEADER_FILES dll.h cph/attribute_handler_cph.h - cph/cph_base.h cph/cph2.h - + cph/cph3.h cph/ihcmap2.h cph/ihcmap2_adaptive.h cph/ihcmap2_regular.h + cph/ihcmap3.h mrcmap/mrcmap2.h diff --git a/cgogn/multiresolution/cph/cph2.h b/cgogn/multiresolution/cph/cph2.h index a1be2ca3..81c4bce1 100644 --- a/cgogn/multiresolution/cph/cph2.h +++ b/cgogn/multiresolution/cph/cph2.h @@ -30,24 +30,30 @@ namespace cgogn { template -class CPH2 : CPHBase +class CPH2 : public CPHBase { + +public: typedef CPH2 Self; typedef CPHBase Inherit; + template + using ChunkArray = typename Inherit::template ChunkArray; + template + using ChunkArrayContainer = typename Inherit::template ChunkArrayContainer; + protected: ChunkArray* edge_id_; - public: CPH2(ChunkArrayContainer& topology): Inherit(topology) { init(); } - ~CPH2() + ~CPH2() override { - topo_.remove_attribute(edge_id_); + this->topo_.remove_attribute(edge_id_); } CPH2(Self const&) = delete; @@ -55,13 +61,14 @@ class CPH2 : CPHBase Self& operator=(Self const&) = delete; Self& operator=(Self &&) = delete; -public: - void init() +protected: + inline void init() { - edge_id_ = topo_.template add_attribute("edgeId"); + edge_id_ = this->topo_.template add_attribute("edgeId"); } +public: /*************************************************** * EDGE ID MANAGEMENT * ***************************************************/ diff --git a/cgogn/multiresolution/cph/cph3.h b/cgogn/multiresolution/cph/cph3.h new file mode 100644 index 00000000..b179260f --- /dev/null +++ b/cgogn/multiresolution/cph/cph3.h @@ -0,0 +1,92 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef MULTIRESOLUTION_CPH_CPH3_BASE_H_ +#define MULTIRESOLUTION_CPH_CPH3_BASE_H_ + +#include + +namespace cgogn +{ + +template +class CPH3 : CPH2 +{ + +public: + typedef CPH3 Self; + typedef CPH2 Inherit; + +protected: + ChunkArray* face_id_; + +public: + CPH3(ChunkArrayContainer& topology): Inherit(topology) + { + init(); + } + + ~CPH3() override + { + this->topo_.remove_attribute(face_id_); + } + + CPH3(Self const&) = delete; + CPH3(Self &&) = delete; + Self& operator=(Self const&) = delete; + Self& operator=(Self &&) = delete; + +protected: + void init() + { + face_id_ = this->topo_.template add_attribute("faceId"); + } + +public: + /*************************************************** + * FACE ID MANAGEMENT * + ***************************************************/ + inline unsigned int get_face_id(Dart d) const + { + return (*face_id_)[d.index] ; + } + + inline void set_face_id(Dart d, unsigned int i) + { + (*face_id_)[d.index] = i ; + } + + inline unsigned int get_tri_refinement_face_id(Dart d, Dart e) const + { + + } + + inline unsigned int get_quad_refinement_face_id(Dart d) const + { + + } +}; + +} // namespace cgogn + +#endif // MULTIRESOLUTION_CPH_CPH3_BASE_H_ diff --git a/cgogn/multiresolution/cph/cph_base.h b/cgogn/multiresolution/cph/cph_base.h index 72e96de3..b204fb30 100644 --- a/cgogn/multiresolution/cph/cph_base.h +++ b/cgogn/multiresolution/cph/cph_base.h @@ -34,106 +34,107 @@ template class CPHBase { - typedef CPHBase Self; +public: + typedef CPHBase Self; - template - using ChunkArray = cgogn::ChunkArray; - template - using ChunkArrayContainer = cgogn::ChunkArrayContainer; + template + using ChunkArray = cgogn::ChunkArray; + template + using ChunkArrayContainer = cgogn::ChunkArrayContainer; protected: - unsigned int current_level_; - unsigned int maximum_level_; + unsigned int current_level_; + unsigned int maximum_level_; - ChunkArray* dart_level_; + ChunkArray* dart_level_; - std::vector nb_darts_per_level; + std::vector nb_darts_per_level; - ChunkArrayContainer& topo_; + ChunkArrayContainer& topo_; public: - CPHBase(ChunkArrayContainer& topology): - topo_(topology), - current_level_(0) - { - init(); - } - - ~CPHBase() - { - topo_.remove_attribute(dart_level_); - } - - CPHBase(Self const&) = delete; - CPHBase(Self &&) = delete; - Self& operator=(Self const&) = delete; - Self& operator=(Self &&) = delete; + CPHBase(ChunkArrayContainer& topology): + topo_(topology), + current_level_(0) + { + init(); + } + + virtual ~CPHBase() + { + topo_.remove_attribute(dart_level_); + } + + CPHBase(Self const&) = delete; + CPHBase(Self &&) = delete; + Self& operator=(Self const&) = delete; + Self& operator=(Self &&) = delete; public: - void init() - { - dart_level_ = topo_.template add_attribute("dartLevel") ; - } - - /*************************************************** - * LEVELS MANAGEMENT * - ***************************************************/ - - inline unsigned int get_current_level() const - { - return current_level_ ; - } - - inline void set_current_level(unsigned int l) - { - current_level_ = l ; - } - - inline unsigned int get_maximum_level() const - { - return maximum_level_ ; - } - - inline void set_maximum_level(unsigned int l) - { - maximum_level_ = l; - } - - inline unsigned int get_dart_level(Dart d) const - { - return (*dart_level_)[d.index] ; - } - - inline void set_dart_level(Dart d, unsigned int l) - { - (*dart_level_)[d.index] = l ; - } - - inline void inc_current_level() - { - set_current_level(get_current_level() + 1); - } - - inline void dec_current_level() - { - set_current_level(get_current_level() - 1); - } - - inline void inc_nb_darts(unsigned int level) - { - cgogn_message_assert(level < get_maximum_level(), "inc_nb_darts : already at maximum resolution level"); - nb_darts_per_level[level]++; - } - - /*************************************************** - * NB DARTS PER LEVEL * - ***************************************************/ - - inline void new_level_darts() - { - nb_darts_per_level.push_back(0); - } + void init() + { + dart_level_ = topo_.template add_attribute("dartLevel") ; + } + + /*************************************************** + * LEVELS MANAGEMENT * + ***************************************************/ + + inline unsigned int get_current_level() const + { + return current_level_ ; + } + + inline void set_current_level(unsigned int l) + { + current_level_ = l ; + } + + inline unsigned int get_maximum_level() const + { + return maximum_level_ ; + } + + inline void set_maximum_level(unsigned int l) + { + maximum_level_ = l; + } + + inline unsigned int get_dart_level(Dart d) const + { + return (*dart_level_)[d.index] ; + } + + inline void set_dart_level(Dart d, unsigned int l) + { + (*dart_level_)[d.index] = l ; + } + + inline void inc_current_level() + { + set_current_level(get_current_level() + 1); + } + + inline void dec_current_level() + { + set_current_level(get_current_level() - 1); + } + + inline void inc_nb_darts(unsigned int level) + { + cgogn_message_assert(level < get_maximum_level(), "inc_nb_darts : already at maximum resolution level"); + nb_darts_per_level[level]++; + } + + /*************************************************** + * NB DARTS PER LEVEL * + ***************************************************/ + + inline void new_level_darts() + { + nb_darts_per_level.push_back(0); + } }; } diff --git a/cgogn/multiresolution/cph/ihcmap2_regular.h b/cgogn/multiresolution/cph/ihcmap2_regular.h index bedef434..1cf83c02 100644 --- a/cgogn/multiresolution/cph/ihcmap2_regular.h +++ b/cgogn/multiresolution/cph/ihcmap2_regular.h @@ -59,7 +59,7 @@ class IHCMap2Regular : public IHCMap2 Inherit::template foreach_cell([&] (typename Inherit::Edge e) { Dart dd = Inherit::phi2(e); - Inherit::cut_edge(e); +// Inherit::cut_edge(e); unsigned int eid = Inherit::get_edge_id(e); Inherit::set_edge_id(Inherit::phi1(e), eid); @@ -77,7 +77,7 @@ class IHCMap2Regular : public IHCMap2 Dart dd = Inherit::phi1(old) ; Dart e = Inherit::phi1(Inherit::phi1(dd)) ; // insert a new edge - Inherit::split_face(dd, e) ; +// Inherit::split_face(dd, e) ; unsigned int id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id) ; // set the edge id of the inserted @@ -85,14 +85,14 @@ class IHCMap2Regular : public IHCMap2 dd = e ; e = Inherit::phi1(Inherit::phi1(dd)) ; - Inherit::split_face(dd, e) ; +// Inherit::split_face(dd, e) ; id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id) ; Inherit::set_edge_id(Inherit::phi_1(e), id) ; dd = e ; e = Inherit::phi1(Inherit::phi1(dd)) ; - Inherit::split_face(dd, e) ; +// Inherit::split_face(dd, e) ; id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id) ; Inherit::set_edge_id(Inherit::phi_1(e), id) ; @@ -111,7 +111,7 @@ class IHCMap2Regular : public IHCMap2 Inherit::template foreach_cell([&] (typename Inherit::Edge e) { Dart dd = Inherit::phi2(e); - Inherit::cut_edge(e); +// Inherit::cut_edge(e); unsigned int eid = Inherit::get_edge_id(e); Inherit::set_edge_id(Inherit::phi1(e), eid); @@ -128,11 +128,11 @@ class IHCMap2Regular : public IHCMap2 Dart dd = Inherit::phi1(old) ; Dart next = Inherit::phi1(Inherit::phi1(dd)) ; - Inherit::split_face(dd, next) ; // insert a first edge +// Inherit::split_face(dd, next) ; // insert a first edge Dart ne = Inherit::phi2(Inherit::phi_1(dd)) ; Dart ne2 = Inherit::phi2(ne) ; - Inherit::cut_edge(ne) ; // cut the new edge to insert the central vertex +// Inherit::cut_edge(ne) ; // cut the new edge to insert the central vertex unsigned int id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(ne))); Inherit::set_edge_id(ne, id) ; @@ -146,7 +146,7 @@ class IHCMap2Regular : public IHCMap2 while(dd != ne) // turn around the face and insert new edges { // linked to the central vertex Dart tmp = Inherit::phi1(ne) ; - Inherit::split_face(tmp, dd) ; +// Inherit::split_face(tmp, dd) ; Dart nne = Inherit::phi2(Inherit::phi_1(dd)) ; @@ -170,7 +170,7 @@ class IHCMap2Regular : public IHCMap2 Inherit::template foreach_cell([&] (typename Inherit::Edge e) { Dart dd = Inherit::phi2(e); - Inherit::cut_edge(e); +// Inherit::cut_edge(e); unsigned int eid = Inherit::get_edge_id(e); Inherit::set_edge_id(Inherit::phi1(e), eid); @@ -195,7 +195,7 @@ class IHCMap2Regular : public IHCMap2 Dart dd = Inherit::phi1(old) ; Dart e = Inherit::phi1(Inherit::phi1(dd)) ; // insert a new edge - Inherit::split_face(dd, e) ; +// Inherit::split_face(dd, e) ; unsigned int id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id) ; // set the edge id of the inserted @@ -203,14 +203,14 @@ class IHCMap2Regular : public IHCMap2 dd = e ; e = Inherit::phi1(Inherit::phi1(dd)) ; - Inherit::split_face(dd, e) ; +// Inherit::split_face(dd, e) ; id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id) ; Inherit::set_edge_id(Inherit::phi_1(e), id) ; dd = e ; e = Inherit::phi1(Inherit::phi1(dd)) ; - Inherit::split_face(dd, e) ; +// Inherit::split_face(dd, e) ; id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id) ; Inherit::set_edge_id(Inherit::phi_1(e), id) ; @@ -219,11 +219,11 @@ class IHCMap2Regular : public IHCMap2 { Dart dd = Inherit::phi1(old) ; Dart next = Inherit::phi1(Inherit::phi1(dd)) ; - Inherit::split_face(dd, next) ; // insert a first edge +// Inherit::split_face(dd, next) ; // insert a first edge Dart ne = Inherit::phi2(Inherit::phi_1(dd)) ; Dart ne2 = Inherit::phi2(ne) ; - Inherit::cut_edge(ne) ; // cut the new edge to insert the central vertex +// Inherit::cut_edge(ne) ; // cut the new edge to insert the central vertex unsigned int id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(ne))); Inherit::set_edge_id(ne, id) ; @@ -237,7 +237,7 @@ class IHCMap2Regular : public IHCMap2 while(dd != ne) // turn around the face and insert new edges { // linked to the central vertex Dart tmp = Inherit::phi1(ne) ; - Inherit::split_face(tmp, dd) ; +// Inherit::split_face(tmp, dd) ; Dart nne = Inherit::phi2(Inherit::phi_1(dd)) ; diff --git a/ihcmap3.h b/ihcmap3.h new file mode 100644 index 00000000..8f4e2c0c --- /dev/null +++ b/ihcmap3.h @@ -0,0 +1,407 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef MULTIRESOLUTION_CPH_IHCMAP3_H_ +#define MULTIRESOLUTION_CPH_IHCMAP3_H_ + +#include +#include + +namespace cgogn +{ + + + +template +class IHCMap3_T : public CMap3_T, public CPH3 +{ +public: + + typedef CMap3_T Inherit_CMAP; + typedef CPH3 Inherit_CPH; + typedef IHCMap3_T Self; + + friend typename Self::Inherit_CMAP; + // friend typename Inherit::Inherit; + + friend class DartMarker_T; + + static const Orbit DART = Orbit::DART; + static const Orbit VERTEX = Orbit::PHI21; + static const Orbit EDGE = Orbit::PHI2; + static const Orbit FACE = Orbit::PHI1; + static const Orbit VOLUME = Orbit::PHI1_PHI2; + + typedef Cell Vertex; + typedef Cell Edge; + typedef Cell Face; + typedef Cell Volume; + + template + using ChunkArray = typename Inherit_CMAP::template ChunkArray; + template + using ChunkArrayContainer = typename Inherit_CMAP::template ChunkArrayContainer; + + template + using AttributeHandler = typename Inherit_CMAP::template AttributeHandler; + template + using DartAttributeHandler = AttributeHandler; + template + using VertexAttributeHandler = AttributeHandler; + template + using EdgeAttributeHandler = AttributeHandler; + template + using FaceAttributeHandler = AttributeHandler; + template + using VolumeAttributeHandler = AttributeHandler; + using DartMarker = typename cgogn::DartMarker; + using DartMarkerStore = typename cgogn::DartMarkerStore; + + ChunkArray* next_level_cell[NB_ORBITS]; + + template + class ContainerCPHBrowser : public ContainerBrowser + { + const CONTAINER& cac_; + const MAP* map_; + + public: + ContainerCPHBrowser(const CONTAINER& cac, const MAP* map) : cac_(cac), map_(map) {} + virtual unsigned int begin() const { return cac_.real_begin(); } + virtual unsigned int end() const { return cac_.real_end(); } + virtual void next(unsigned int &it) const + { + cac_.real_next(it); + if(map_->get_dart_level(Dart(it)) > map_->get_current_level()) + it = cac_.real_end(); + } + virtual void next_primitive(unsigned int &it, unsigned int primSz) const { cac_.real_next_primitive(it,primSz); } + virtual void enable() {} + virtual void disable() {} + virtual ~ContainerCPHBrowser() {} + }; + +protected: + ContainerCPHBrowser, Self>* cph_browser; + + inline void init() + { + cph_browser = new ContainerCPHBrowser, Self>(this->topology_, this); + this->topology_.set_current_browser(cph_browser); + + // Inherit_CPH::new_level_darts(); + } + +public: + IHCMap3_T() : Inherit_CMAP(), Inherit_CPH(this->topology_) + { + init(); + } + + ~IHCMap3_T() override + {} + + IHCMap3_T(Self const&) = delete; + IHCMap3_T(Self &&) = delete; + Self& operator=(Self const&) = delete; + Self& operator=(Self &&) = delete; + +public: + /******************************************************************************* + * Basic topological operations + *******************************************************************************/ + + inline Dart phi1(Dart d) const + { + cgogn_message_assert(Inherit_CPH::get_dart_level(d) <= Inherit_CPH::get_current_level(), "Access to a dart introduced after current level") ; + + bool finished = false ; + unsigned int edge_id = Inherit_CPH::get_edge_id(d) ; + Dart it = d ; + do + { + it = Inherit_CMAP::phi1(it) ; + if(Inherit_CPH::get_dart_level(it) <= Inherit_CPH::get_current_level()) + finished = true ; + else + { + while(Inherit_CPH::get_edge_id(it) != edge_id) + it = Inherit_CMAP::phi1(phi2bis(it)) ; + } + } while(!finished) ; + return it ; + } + + inline Dart phi_1(Dart d) const + { + cgogn_message_assert(Inherit_CPH::get_dart_level(d) <= Inherit_CPH::get_current_level(), "Access to a dart introduced after current level") ; + + bool finished = false ; + Dart it = Inherit_CMAP::phi_1(d) ; + unsigned int edge_id = Inherit_CPH::get_edge_id(d) ; + do + { + if(Inherit_CPH::get_dart_level(it) <= Inherit_CPH::get_current_level()) + finished = true ; + else + { + it = Inherit_CMAP::phi_1(it) ; + while(Inherit_CPH::get_edge_id(it) != edge_id) + it = Inherit_CMAP::phi_1(phi2bis(it)) ; + } + } while(!finished) ; + return it ; + } + + /** + * \brief phi2 + * @param d + * @return phi2(d) + */ + inline Dart phi2(Dart d) const + { + cgogn_message_assert(Inherit_CPH::get_dart_level(d) <= Inherit_CPH::get_current_level(), "Access to a dart introduced after current level") ; + + return Inherit_CMAP::phi2(Inherit_CMAP::phi_1(phi1(d))); + } + + inline Dart phi3(Dart d) const + { + cgogn_message_assert(Inherit_CPH::get_dart_level(d) <= Inherit_CPH::get_current_level(), "Access to a dart introduced after current level") ; + + if(Inherit_CMAP::phi3(d) == d); + return d; + + return Inherit_CMAP::phi3(Inherit_CMAP::phi_1(phi1(d))); + } + + /** + * \brief add a Dart in the map + * @return the new Dart + */ + inline Dart add_dart() + { + Dart d = Inherit_CMAP::add_dart(); + + Inherit_CPH::set_edge_id(d, 0); + Inherit_CPH::set_face_id(d, 0); + Inherit_CPH::set_dart_level(d, Inherit_CPH::get_current_level()); + + // update max level if needed + if(Inherit_CPH::get_current_level() > Inherit_CPH::get_maximum_level()) + { + Inherit_CPH::set_maximum_level(Inherit_CPH::get_current_level()); + // Inherit_CPH::new_level_darts(); + } + + // Inherit_CPH::inc_nb_darts(get_current_level()); + + return d ; + } + +protected: + + inline Dart phi2bis(Dart d) const + { + unsigned int face_id = Inherit_CPH::get_face_id(d); + Dart it = d; + + it = Inherit_CMAP::phi2(it); + + if(Inherit_CPH::get_face_id(it) == face_id) + return it; + else + { + do + { + it = Inherit_CMAP::phi2(Inherit_CMAP::phi3(it)); + } + while(Inherit_CPH::get_face_id(it) != face_id); + + return it; + } + } + + /******************************************************************************* + * Orbits traversal + *******************************************************************************/ + + template + inline void foreach_dart_of_DART(Dart d, const FUNC& f) const + { + f(d); + } + + template + inline void foreach_dart_of_PHI1(Dart d, const FUNC& f) const + { + Dart it = d; + do + { + f(it); + it = phi1(it); + } while (it != d); + } + + template + inline void foreach_dart_of_PHI2(Dart d, const FUNC& f) const + { + f(d); + Dart d2 = phi2(d); + if (d2 != d) + f(d2); + } + + template + inline void foreach_dart_of_PHI21(Dart d, const FUNC& f) const + { + Dart it = d; + do + { + f(it); + it = Inherit_CMAP::phi2(Inherit_CMAP::phi_1(it)); + } while (it != d); + } + + template + void foreach_dart_of_PHI1_PHI2(Dart d, const FUNC& f) const + { + DartMarkerStore marker(*this); + + std::vector* visited_faces = cgogn::get_dart_buffers()->get_buffer(); + visited_faces->push_back(d); // Start with the face of d + + // For every face added to the list + for(unsigned int i = 0; i < visited_faces->size(); ++i) + { + if (!marker.is_marked((*visited_faces)[i])) // Face has not been visited yet + { + // mark visited darts (current face) + // and add non visited adjacent faces to the list of face + Dart e = (*visited_faces)[i] ; + do + { + f(e); // apply the function to the darts of the face + marker.mark(e); // Mark + Dart adj = phi2(e); // Get adjacent face + if (!marker.is_marked(adj)) + visited_faces->push_back(adj); // Add it + e = phi1(e); + } while (e != (*visited_faces)[i]); + } + } + + cgogn::get_dart_buffers()->release_buffer(visited_faces); + } + + template + inline void foreach_dart_of_PHI21_PHI31(Dart d, const FUNC& f) const + { + DartMarkerStore marker(*this); + const std::vector* marked_darts = marker.get_marked_darts(); + + marker.mark(d); + for(unsigned int i = 0; i < marked_darts->size(); ++i) + { + f((*marked_darts)[i]); + + Dart d2 = phi2((*marked_darts)[i]); + Dart d21 = phi1(d2); // turn in volume + Dart d23 = phi3(d2); // change volume + if(!marker.is_marked(d21)) + marker.mark(d21); + if(!marker.is_marked(d23)) + marker.mark(d23); + } + } + + template + inline void foreach_dart_of_PHI2_PHI3(Dart d, const FUNC& f) const + { + Dart it = d; + do + { + f(it); + it = phi2(it); + f(it); + it = phi3(it); + } while (it != d); + } + + template + inline void foreach_dart_of_PHI23(Dart d, const FUNC& f) const + { + Dart it = d; + do + { + f(it); + it = phi3(phi2(it)); + } while (it != d); + } + + template + inline void foreach_dart_of_PHI1_PHI3(Dart d, const FUNC& f) const + { + foreach_dart_of_PHI1(d, [&] (Dart fd) + { + f(fd); + f(phi3(fd)); + }); + } + +public: + template + inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const + { + static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || + ORBIT == Orbit::PHI2 || ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21, + "Orbit not supported in a CMap2"); + switch (ORBIT) + { + case Orbit::DART: foreach_dart_of_DART(c, f); break; + case Orbit::PHI1: foreach_dart_of_PHI1(c, f); break; + case Orbit::PHI2: foreach_dart_of_PHI2(c, f); break; + case Orbit::PHI1_PHI2: foreach_dart_of_PHI1_PHI2(c, f); break; + case Orbit::PHI1_PHI3: foreach_dart_of_PHI1_PHI3(c, f); break; + case Orbit::PHI2_PHI3: foreach_dart_of_PHI2_PHI3(c, f); break; + case Orbit::PHI21: foreach_dart_of_PHI21(c, f); break; + case Orbit::PHI21_PHI31: foreach_dart_of_PHI21_PHI31(c, f); break; + default: cgogn_assert_not_reached("Cells of this dimension are not handled"); break; + } + } + +}; + +template +struct IHCMap3Type +{ + typedef IHCMap3_T> TYPE; +}; + +template +using IHCMap3 = IHCMap3_T>; + +} // namespace cgogn + + +#endif // MULTIRESOLUTION_CPH_IHCMAP3_H_ From 32fa6730670777f1f30fb54401abc807350312ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 9 Feb 2016 15:56:56 +0100 Subject: [PATCH 064/402] added macro CGOGN_CHECK_CONCRETE_TYPE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/cmap1.h | 1 + cgogn/core/cmap/cmap2.h | 1 + cgogn/core/cmap/cmap3.h | 1 + 3 files changed, 3 insertions(+) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 870f439e..62041662 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -172,6 +172,7 @@ class CMap1_T : public MapBase */ inline Dart add_dart() { + CGOGN_CHECK_CONCRETE_TYPE; unsigned int di = this->add_topology_element(); Dart d(di); diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index b7b16024..6afcf43a 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -160,6 +160,7 @@ class CMap2_T : public CMap1_T */ inline Dart add_dart() { + CGOGN_CHECK_CONCRETE_TYPE; Dart d = Inherit::add_dart(); (*phi2_)[d.index] = d; return d; diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 85396a76..de09edce 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -323,6 +323,7 @@ class CMap3_T : public CMap2_T */ inline Dart add_dart() { + CGOGN_CHECK_CONCRETE_TYPE; Dart d = Inherit::add_dart(); (*phi3_)[d.index] = d; return d; From 938150c7c977cfcf97d2b00b07ffee2cb5d2ede1 Mon Sep 17 00:00:00 2001 From: lionel untereiner Date: Tue, 9 Feb 2016 15:57:06 +0100 Subject: [PATCH 065/402] shitty qt creator --- ihcmap3.h => cgogn/multiresolution/cph/ihcmap3.h | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename ihcmap3.h => cgogn/multiresolution/cph/ihcmap3.h (100%) diff --git a/ihcmap3.h b/cgogn/multiresolution/cph/ihcmap3.h similarity index 100% rename from ihcmap3.h rename to cgogn/multiresolution/cph/ihcmap3.h From 4181c5ffd9bbed9e1dbc20efba1370ba8905dd32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 9 Feb 2016 16:04:51 +0100 Subject: [PATCH 066/402] added the demangle function and the CGOGN_CHECK_CONCRETE_TYPE macro. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/CMakeLists.txt | 1 + cgogn/core/cmap/map_base_data.h | 17 +++++---- cgogn/core/utils/name_types.cpp | 61 +++++++++++++++++++++++++++++++++ cgogn/core/utils/name_types.h | 14 ++------ 4 files changed, 76 insertions(+), 17 deletions(-) create mode 100644 cgogn/core/utils/name_types.cpp diff --git a/cgogn/core/CMakeLists.txt b/cgogn/core/CMakeLists.txt index e7481d2a..f16daf12 100644 --- a/cgogn/core/CMakeLists.txt +++ b/cgogn/core/CMakeLists.txt @@ -59,6 +59,7 @@ set(SOURCE_FILES container/chunk_array_factory.cpp utils/assert.cpp + utils/name_types.cpp utils/thread.cpp utils/thread_pool.cpp utils/serialization.cpp diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index ebf5ad31..9961d5fa 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -24,19 +24,24 @@ #ifndef CORE_CMAP_MAP_BASE_DATA_H_ #define CORE_CMAP_MAP_BASE_DATA_H_ +#include +#include +#include +#include +#include +#include + #include #include #include +#include #include #include #include -#include -#include -#include -#include -#include -#include + +#define CGOGN_CHECK_CONCRETE_TYPE cgogn_message_assert(typeid(*this).hash_code() == typeid(Self).hash_code(),\ + std::string("dynamic type of current object : ") + cgogn::internal::demangle(std::string(typeid(*this).name())) + std::string(",\nwhereas Self = ") + cgogn::name_of_type(Self())) namespace cgogn { diff --git a/cgogn/core/utils/name_types.cpp b/cgogn/core/utils/name_types.cpp new file mode 100644 index 00000000..c9382419 --- /dev/null +++ b/cgogn/core/utils/name_types.cpp @@ -0,0 +1,61 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#define CGOGN_UTILS_DLL_EXPORT + +#include + +#ifdef __GNUG__ +#include +#include +#endif // __GNUG__ + + +namespace cgogn +{ + +namespace internal +{ + +/** + * @brief demangle, trying demangling a typename using the cxxabi + * @param str, a type name + * @return the demangled type name is succeded, otherwise a copy of str + */ +CGOGN_UTILS_API std::string demangle(const std::string& str) +{ +#ifndef __GNUG__ + return str; +#else + int status = std::numeric_limits::max(); + std::unique_ptr res{ abi::__cxa_demangle(str.c_str(), NULL, NULL, &status), std::free }; + if (status == 0) + return std::string(res.get()); + else + std::cerr << "__cxa_demangle exited with error code " << status << std::endl; + return str; +#endif // __GNUG__ +} + +} // namespace internal +} // namespace cgogn diff --git a/cgogn/core/utils/name_types.h b/cgogn/core/utils/name_types.h index 8a9ad97c..08b8b5f5 100644 --- a/cgogn/core/utils/name_types.h +++ b/cgogn/core/utils/name_types.h @@ -36,8 +36,6 @@ #ifdef __GNUG__ #include -#include -#include #include #include #include @@ -95,6 +93,8 @@ inline std::string name_of_type_impl(const std::basic_string&); template inline std::string name_of_type_impl(const std::array&); +CGOGN_UTILS_API std::string demangle(const std::string& str); + // definitions template @@ -113,7 +113,6 @@ template inline std::string name_of_type_impl(const std::array&) { return std::string("std::array<") + name_of_type(T()) + std::string(",") + std::to_string(N) + std::string(">"); } - template inline auto name_of_type_impl(const T&)->typename std::enable_if::value == true, std::string>::type { @@ -123,15 +122,8 @@ inline auto name_of_type_impl(const T&)->typename std::enable_if inline auto name_of_type_impl(const T&)->typename std::enable_if::value == false, std::string>::type { - std::string type_name = typeid(T).name(); + std::string type_name = demangle(std::string(typeid(T).name())); #ifdef __GNUG__ - int status = std::numeric_limits::max(); - std::unique_ptr res{ abi::__cxa_demangle(type_name.c_str(), NULL, NULL, &status), std::free }; - if (status == 0) - type_name = std::string(res.get()); - else - std::cerr << "__cxa_demangle exited with error code " << status << std::endl; - // integer postfixes { std::regex regex("([0-9]+)(ul|l)", std::regex_constants::ECMAScript | std::regex_constants::icase); From bf153c906b2d23e4d250e73d7e16cc1de2cc1416 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Tue, 9 Feb 2016 16:13:06 +0100 Subject: [PATCH 067/402] fix crash & compil pb on Windows --- benchmarks/multithreading/bench_multithreading.cpp | 2 +- cgogn/core/basic/cell.h | 4 ++-- cgogn/core/cmap/cmap1.h | 4 ++-- cgogn/core/cmap/cmap2.h | 6 +++--- cgogn/core/cmap/map_base.h | 8 ++++---- cgogn/core/cmap/map_base_data.h | 4 ++-- cgogn/core/container/chunk_array_factory.h | 14 +++++++------- cgogn/core/utils/definitions.h | 3 ++- 8 files changed, 23 insertions(+), 22 deletions(-) diff --git a/benchmarks/multithreading/bench_multithreading.cpp b/benchmarks/multithreading/bench_multithreading.cpp index 7bb055c5..29649da3 100644 --- a/benchmarks/multithreading/bench_multithreading.cpp +++ b/benchmarks/multithreading/bench_multithreading.cpp @@ -77,7 +77,7 @@ static void BENCH_Dart_count_multi_threaded(benchmark::State& state) for (unsigned int n : nb_darts_per_thread) nb_darts_2 += n; - cgogn_assert(nb_darts_2 = map.nb_darts()); + cgogn_assert(nb_darts_2 == map.nb_darts()); } } diff --git a/cgogn/core/basic/cell.h b/cgogn/core/basic/cell.h index fde1464d..cce25ae7 100644 --- a/cgogn/core/basic/cell.h +++ b/cgogn/core/basic/cell.h @@ -66,9 +66,9 @@ inline std::string orbit_name(Orbit orbit) case Orbit::PHI2_PHI3: return "cgogn::Orbit::PHI2_PHI3"; break; case Orbit::PHI21: return "cgogn::Orbit::PHI21"; break; case Orbit::PHI21_PHI31: return "cgogn::Orbit::PHI21_PHI31"; break; - default: cgogn_assert_not_reached("This orbit does not exist"); break; + default: cgogn_assert_not_reached("This orbit does not exist"); return "UNKNOWN"; break; } - return "UNKNOWN"; +// return "UNKNOWN"; } /** diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 870f439e..39e3a661 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -210,12 +210,12 @@ class CMap1_T : public MapBase { foreach_incident_vertex(f, [this] (Cell c) { - this->template set_orbit_embedding(c, this->template add_attribute_element()); + this->set_orbit_embedding(c, this->template add_attribute_element()); }); } if (this->template is_orbit_embedded()) - this->template set_orbit_embedding(f, this->template add_attribute_element()); + this->set_orbit_embedding(f, this->template add_attribute_element()); return f; } diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index b7b16024..362a4e20 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -239,7 +239,7 @@ class CMap2_T : public CMap1_T { foreach_incident_vertex(f, [this] (Cell c) { - this->template set_orbit_embedding(c, this->template add_attribute_element()); + this->set_orbit_embedding(c, this->template add_attribute_element()); }); } @@ -247,12 +247,12 @@ class CMap2_T : public CMap1_T { foreach_incident_edge(f, [this] (Cell c) { - this->template set_orbit_embedding(c, this->template add_attribute_element()); + this->set_orbit_embedding(c, this->template add_attribute_element()); }); } if (this->template is_orbit_embedded()) - this->template set_orbit_embedding(f, this->template add_attribute_element()); + this->set_orbit_embedding(f, this->template add_attribute_element()); if (this->template is_orbit_embedded()) this->template set_orbit_embedding(d, this->template add_attribute_element()); diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 5ff870af..6e17c6ce 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -586,7 +586,7 @@ class MapBase : public MapBaseData using VecDarts = std::vector; ThreadPool* thread_pool = cgogn::get_thread_pool(); - const unsigned int nb_threads_pool = thread_pool->get_nb_threads(); + const std::size_t nb_threads_pool = thread_pool->get_nb_threads(); std::array, 2> dart_buffers; std::array, 2> futures; @@ -783,7 +783,7 @@ class MapBase : public MapBaseData using Future = std::future< typename std::result_of, unsigned int)>::type >; ThreadPool* thread_pool = cgogn::get_thread_pool(); - const unsigned int nb_threads_pool = thread_pool->get_nb_threads(); + const std::size_t nb_threads_pool = thread_pool->get_nb_threads(); std::array, 2> cells_buffers; std::array, 2> futures; @@ -866,7 +866,7 @@ class MapBase : public MapBaseData using Future = std::future< typename std::result_of, unsigned int)>::type >; ThreadPool* thread_pool = cgogn::get_thread_pool(); - const unsigned int nb_threads_pool = thread_pool->get_nb_threads(); + const std::size_t nb_threads_pool = thread_pool->get_nb_threads(); std::array, 2> cells_buffers; std::array, 2> futures; @@ -944,7 +944,7 @@ class MapBase : public MapBaseData using Future = std::future< typename std::result_of, unsigned int)>::type >; ThreadPool* thread_pool = cgogn::get_thread_pool(); - const unsigned int nb_threads_pool = thread_pool->get_nb_threads(); + const std::size_t nb_threads_pool = thread_pool->get_nb_threads(); std::array, 2> cells_buffers; std::array, 2> futures; diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index 2f3e176a..f15b40c1 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -290,7 +290,7 @@ class MapBaseData : public MapGen std::advance(end, NB_UNKNOWN_THREADS); auto res_it = std::find(thread_ids_.begin(), end, thread_id); if (res_it != end) - return std::distance(thread_ids_.begin(), res_it); + return (unsigned int)(std::distance(thread_ids_.begin(), res_it)); return add_unknown_thread(); } @@ -304,7 +304,7 @@ class MapBaseData : public MapGen const auto end = thread_ids_.end(); auto it_lower_bound = std::lower_bound(real_begin, end, std::this_thread::get_id()); if (it_lower_bound != end) - return std::distance(thread_ids_.begin(),it_lower_bound); + return (unsigned int)(std::distance(thread_ids_.begin(),it_lower_bound)); return get_unknown_thread_index(std::this_thread::get_id()); } diff --git a/cgogn/core/container/chunk_array_factory.h b/cgogn/core/container/chunk_array_factory.h index 98b3136e..be830593 100644 --- a/cgogn/core/container/chunk_array_factory.h +++ b/cgogn/core/container/chunk_array_factory.h @@ -46,7 +46,7 @@ class ChunkArrayFactory typedef std::unique_ptr< ChunkArrayGen > ChunkArrayGenPtr; typedef std::map NamePtrMap; - static NamePtrMap map_CA_; + static NamePtrMap* map_CA_; /** * @brief register a type @@ -57,8 +57,8 @@ class ChunkArrayFactory static void register_CA() { std::string&& keyType(name_of_type(T())); - if(map_CA_.find(keyType) == map_CA_.end()) - map_CA_[std::move(keyType)] = make_unique>(); + if(map_CA_->find(keyType) == map_CA_->end()) + (*map_CA_)[std::move(keyType)] = make_unique>(); } static void register_known_types() @@ -98,9 +98,9 @@ class ChunkArrayFactory static ChunkArrayGen* create(const std::string& keyType) { ChunkArrayGen* tmp = nullptr; - typename NamePtrMap::const_iterator it = map_CA_.find(keyType); + typename NamePtrMap::const_iterator it = map_CA_->find(keyType); - if(it != map_CA_.end()) + if(it != map_CA_->end()) { tmp = (it->second)->clone(); } @@ -112,12 +112,12 @@ class ChunkArrayFactory static void reset() { - ChunkArrayFactory::map_CA_ = NamePtrMap(); + ChunkArrayFactory::map_CA_ = new NamePtrMap(); } }; template -typename ChunkArrayFactory::NamePtrMap ChunkArrayFactory::map_CA_= typename ChunkArrayFactory::NamePtrMap(); +typename ChunkArrayFactory::NamePtrMap* ChunkArrayFactory::map_CA_ = nullptr;//typename ChunkArrayFactory::NamePtrMap(); #if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_CONTAINER_CHUNK_ARRAY_FACTORY_CPP_)) diff --git a/cgogn/core/utils/definitions.h b/cgogn/core/utils/definitions.h index c76e3058..00aff708 100644 --- a/cgogn/core/utils/definitions.h +++ b/cgogn/core/utils/definitions.h @@ -37,7 +37,8 @@ /* * Thread local storage. In VS <1900 it works only with POD types. */ -#if defined(_MSC_VER) && _MSC_VER < 1900 +//#if defined(_MSC_VER) && _MSC_VER < 1900 +#if defined(_MSC_VER) #define CGOGN_TLS __declspec( thread ) #else #define CGOGN_TLS __thread From e9af7ce63bf791a2ccd3f77b3072edf201ae4750 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 9 Feb 2016 16:23:53 +0100 Subject: [PATCH 068/402] Revert "Merge branch 'develop-cgogn' into develop-schmitte" This reverts commit e512046837effd51ee60792cb5e9c2b41aa2a350, reversing changes made to 4181c5ffd9bbed9e1dbc20efba1370ba8905dd32. --- cgogn/core/cmap/map_base_data.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index 0707ca3a..9961d5fa 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -256,16 +256,6 @@ class MapBaseData : public MapGen protected: - template - inline void init_embedding(Dart d, unsigned int emb) - { - static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - cgogn_message_assert(is_orbit_embedded(), "Invalid parameter: orbit not embedded"); - - this->attributes_[ORBIT].ref_line(emb); // ref the new emb - (*this->embeddings_[ORBIT])[d.index] = emb; // affect the embedding to the dart - } - template inline void set_embedding(Dart d, unsigned int emb) { From 59ec58b1c17f1c4492b135c50b5c0137d3dc8be0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 9 Feb 2016 16:26:09 +0100 Subject: [PATCH 069/402] removed init_orbit embedding in cmap0 and cmap3_builder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/cmap0.h | 18 ------------------ cgogn/core/cmap/cmap3_builder.h | 6 ------ 2 files changed, 24 deletions(-) diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index 6802f84d..6cfb681c 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -120,24 +120,6 @@ class CMap0_T : public MapBase default: cgogn_assert_not_reached("Cells of this dimension are not handled"); break; } } - -protected: - - /******************************************************************************* - * Embedding management - *******************************************************************************/ - - template - inline void init_orbit_embedding(Cell c, unsigned int emb) - { - foreach_dart_of_orbit(c, [this, emb] (Dart d) { this->template init_embedding(d, emb); }); - } - - template - inline void set_orbit_embedding(Cell c, unsigned int emb) - { - foreach_dart_of_orbit(c, [this, emb] (Dart d) { this->template set_embedding(d, emb); }); - } }; template diff --git a/cgogn/core/cmap/cmap3_builder.h b/cgogn/core/cmap/cmap3_builder.h index 8e0a9cb3..f321872b 100644 --- a/cgogn/core/cmap/cmap3_builder.h +++ b/cgogn/core/cmap/cmap3_builder.h @@ -62,12 +62,6 @@ class CMap3Builder_T map_.attributes_[ORBIT].swap(cac); } - template - inline void init_embedding(Dart d, unsigned int emb) - { - map_.template init_embedding(d, emb); - } - inline void init_parent_vertex_embedding(Dart d, unsigned int emb) { map_.foreach_dart_of_PHI21(d, [&] (Dart dit) From 7b407d9ec90d78c322e2840f4e07a81b30376243 Mon Sep 17 00:00:00 2001 From: lionel untereiner Date: Tue, 9 Feb 2016 16:48:17 +0100 Subject: [PATCH 070/402] improvement of mr analysis --- cgogn/multiresolution/CMakeLists.txt | 3 +- cgogn/multiresolution/examples/cph/cph2.cpp | 2 +- cgogn/multiresolution/mra/lerp_triquad_mra.h | 118 ++++++++++++++++++ cgogn/multiresolution/mra/mr_analysis.h | 80 ++++++++++++ .../mranalysis/lerp_triquad_mra.h | 109 ---------------- 5 files changed, 201 insertions(+), 111 deletions(-) create mode 100644 cgogn/multiresolution/mra/lerp_triquad_mra.h create mode 100644 cgogn/multiresolution/mra/mr_analysis.h delete mode 100644 cgogn/multiresolution/mranalysis/lerp_triquad_mra.h diff --git a/cgogn/multiresolution/CMakeLists.txt b/cgogn/multiresolution/CMakeLists.txt index 2708c924..f7647a58 100644 --- a/cgogn/multiresolution/CMakeLists.txt +++ b/cgogn/multiresolution/CMakeLists.txt @@ -16,7 +16,8 @@ set(HEADER_FILES mrcmap/mrcmap2.h - mranalysis/lerp_triquad_mra.h + mra/mr_analysis.h + mra/lerp_triquad_mra.h ) set(SOURCE_FILES diff --git a/cgogn/multiresolution/examples/cph/cph2.cpp b/cgogn/multiresolution/examples/cph/cph2.cpp index c2eb9ace..83195d93 100644 --- a/cgogn/multiresolution/examples/cph/cph2.cpp +++ b/cgogn/multiresolution/examples/cph/cph2.cpp @@ -1,7 +1,7 @@ #include -#include +#include #include diff --git a/cgogn/multiresolution/mra/lerp_triquad_mra.h b/cgogn/multiresolution/mra/lerp_triquad_mra.h new file mode 100644 index 00000000..c461896f --- /dev/null +++ b/cgogn/multiresolution/mra/lerp_triquad_mra.h @@ -0,0 +1,118 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef MULTIRESOLUTION_MRA_LERP_TRI_QUAD_MRANALYSIS_H_ +#define MULTIRESOLUTION_MRA_LERP_TRI_QUAD_MRANALYSIS_H_ + +#include +#include + +namespace cgogn { + +template +class LerpTriQuadMRAnalysis : public MRAnalysis +{ + +public: + typedef LerpTriQuadMRAnalysis Self; + typedef MRAnalysis Inherit; + + using VertexAttributeHandler = typename MRMAP::template VertexAttributeHandler; + +protected: + VertexAttributeHandler& va_; + +public: + LerpTriQuadMRAnalysis(MRMAP& map, VertexAttributeHandler& v): + Inherit(map), + va_(v) + { + this->synthesis_filters_.push_back(lerp_tri_quad_odd_synthesis_); + } + + LerpTriQuadMRAnalysis(Self const& ) = delete; + LerpTriQuadMRAnalysis(Self&& ) = delete; + LerpTriQuadMRAnalysis& operator=(Self const& ) = delete; + LerpTriQuadMRAnalysis& operator=(Self&& ) = delete; + + ~LerpTriQuadMRAnalysis() override + {} + +protected: + + std::function lerp_tri_quad_odd_synthesis_ = [this] () + { + this->map_.template foreach_cell([&] (typename MRMAP::Face f) + { + if(this->map_.degree(f) != 3) + { + VEC3 vf(0.0); + VEC3 ef(0.0); + + unsigned int count = 0; + + this->map_.template foreach_incident_edge(f, [&] (typename MRMAP::Edge e) + { + vf += va_[e.dart]; + this->map_.inc_current_level(); + ef += va_[this->map_.phi1(e.dart)]; + this->map_.dec_current_level(); + ++count; + }); + + ef /= count; + ef *= 2.0; + + vf /= count; + + this->map_.inc_current_level() ; + Dart midF = this->map_.phi1(this->map_.phi1(f.dart)); + va_[midF] += vf + ef ; + this->map_.dec_current_level() ; + } + }); + + this->map_.template foreach_cell([&] (typename MRMAP::Edge e) + { + VEC3 ve = (va_[e.dart] + va_[this->map_.phi1(e)]) * 0.5; + + this->map_.inc_current_level() ; + Dart midV = this->map_.phi1(e) ; + va_[midV] += ve ; + this->map_.dec_current_level() ; + }); + }; + +public: + + void add_level() override + { + this->map_.add_mixed_level(); + } + +}; + +} //namespace cgogn + +#endif // MULTIRESOLUTION_MRA_LERP_TRI_QUAD_MRANALYSIS_H_ + diff --git a/cgogn/multiresolution/mra/mr_analysis.h b/cgogn/multiresolution/mra/mr_analysis.h new file mode 100644 index 00000000..5699f04d --- /dev/null +++ b/cgogn/multiresolution/mra/mr_analysis.h @@ -0,0 +1,80 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef MULTIRESOLUTION_MRA_MR_ANALYSIS_H_ +#define MULTIRESOLUTION_MRA_MR_ANALYSIS_H_ + +namespace cgogn { + +template +class MRAnalysis +{ +public: + typedef MRAnalysis Self; + + +protected: + MRMAP& map_; + + std::vector> synthesis_filters_; + std::vector> analysis_filters_; + +public: + MRAnalysis(MRMAP& map): + map_(map) + {} + + MRAnalysis(Self const& ) = delete; + MRAnalysis(Self&& ) = delete; + MRAnalysis& operator=(Self const& ) = delete; + MRAnalysis& operator=(Self&& ) = delete; + + virtual ~MRAnalysis() + {} + + void analysis() + { + cgogn_message_assert(map_.get_current_level() > 0, "analysis : called on level 0") ; + + map_.dec_current_level() ; + + for(unsigned int i = 0; i < analysis_filters_.size(); ++i) + analysis_filters_[i](); + } + + void synthesis() + { + cgogn_message_assert(map_.get_current_level() < map_.get_maximum_level(), "synthesis : called on max level") ; + + for(unsigned int i = 0; i < synthesis_filters_.size(); ++i) + synthesis_filters_[i](); + + map_.inc_current_level(); + } + + virtual void add_level() = 0; +}; + +} //namespace cgogn + +#endif // MULTIRESOLUTION_MRA_MR_ANALYSIS_H_ diff --git a/cgogn/multiresolution/mranalysis/lerp_triquad_mra.h b/cgogn/multiresolution/mranalysis/lerp_triquad_mra.h deleted file mode 100644 index 7a9f2de8..00000000 --- a/cgogn/multiresolution/mranalysis/lerp_triquad_mra.h +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef MULTIRESOLUTION_MRANALYSIS_LERP_TRI_QUAD_MRANALYSIS_H_ -#define MULTIRESOLUTION_MRANALYSIS_LERP_TRI_QUAD_MRANALYSIS_H_ - -#include - -namespace cgogn { - -template -class LerpTriQuadMRAnalysis -{ - -public: - using Self = LerpTriQuadMRAnalysis; - - using VertexAttributeHandler = typename MRMAP::template VertexAttributeHandler; - -protected: - std::vector> synthesis_filters_; - std::vector> analysis_filters_; - - MRMAP& map_; - VertexAttributeHandler& va_; - -public: - LerpTriQuadMRAnalysis(MRMAP& map, VertexAttributeHandler& v): - map_(map), - va_(v) - { - synthesis_filters_.emplace_back(lerp_tri_quad_odd_synthesis_); - } - -protected: - - std::function lerp_tri_quad_odd_synthesis_ = [this] () - { - map_.template foreach_cell([&] (typename MRMAP::Face f) - { - if(map_.degree(f) != 3) - { - VEC3 vf(0.0); - VEC3 ef(0.0); - - unsigned int count = 0; - - map_.template foreach_incident_edge(f, [&] (typename MRMAP::Edge e) - { - vf += va_[e.dart]; - map_.inc_current_level(); - ef += va_[map_.phi1(e.dart)]; - map_.dec_current_level(); - ++count; - }); - - ef /= count; - ef *= 2.0; - - vf /= count; - - map_.inc_current_level() ; - Dart midF = map_.phi1(map_.phi1(f.dart)); - va_[midF] += vf + ef ; - map_.dec_current_level() ; - } - }); - - map_.template foreach_cell([&] (typename MRMAP::Edge e) - { - VEC3 ve = (va_[e.dart] + va_[map_.phi1(e)]) * 0.5; - - map_.inc_current_level() ; - Dart midV = map_.phi1(e) ; - va_[midV] += ve ; - map_.dec_current_level() ; - }); - }; - -public: - - void analysis() - { - cgogn_message_assert(map_.get_current_level() > 0, "analysis : called on level 0") ; - - map_.dec_current_level() ; - - for(unsigned int i = 0; i < analysis_filters_.size(); ++i) - analysis_filters_[i](); - } - - void synthesis() - { - cgogn_message_assert(map_.get_current_level() < map_.get_maximum_level(), "synthesis : called on max level") ; - - for(unsigned int i = 0; i < synthesis_filters_.size(); ++i) - synthesis_filters_[i](); - - map_.inc_current_level(); - } - - void add_level() - { - map_.add_mixed_level(); - } - -}; - -} //namespace cgogn - -#endif // MULTIRESOLUTION_MRANALYSIS_LERP_TRI_QUAD_MRANALYSIS_H_ - From 1fb94e8a060bf650952e5b53c8a678ac22af60b0 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Tue, 9 Feb 2016 16:13:06 +0100 Subject: [PATCH 071/402] fix crash & compil pb on Windows --- benchmarks/multithreading/bench_multithreading.cpp | 2 +- cgogn/core/basic/cell.h | 4 ++-- cgogn/core/cmap/cmap1.h | 4 ++-- cgogn/core/cmap/cmap2.h | 6 +++--- cgogn/core/cmap/map_base.h | 8 ++++---- cgogn/core/cmap/map_base_data.h | 4 ++-- cgogn/core/container/chunk_array_factory.h | 14 +++++++------- cgogn/core/utils/definitions.h | 3 ++- 8 files changed, 23 insertions(+), 22 deletions(-) diff --git a/benchmarks/multithreading/bench_multithreading.cpp b/benchmarks/multithreading/bench_multithreading.cpp index 7bb055c5..29649da3 100644 --- a/benchmarks/multithreading/bench_multithreading.cpp +++ b/benchmarks/multithreading/bench_multithreading.cpp @@ -77,7 +77,7 @@ static void BENCH_Dart_count_multi_threaded(benchmark::State& state) for (unsigned int n : nb_darts_per_thread) nb_darts_2 += n; - cgogn_assert(nb_darts_2 = map.nb_darts()); + cgogn_assert(nb_darts_2 == map.nb_darts()); } } diff --git a/cgogn/core/basic/cell.h b/cgogn/core/basic/cell.h index fde1464d..cce25ae7 100644 --- a/cgogn/core/basic/cell.h +++ b/cgogn/core/basic/cell.h @@ -66,9 +66,9 @@ inline std::string orbit_name(Orbit orbit) case Orbit::PHI2_PHI3: return "cgogn::Orbit::PHI2_PHI3"; break; case Orbit::PHI21: return "cgogn::Orbit::PHI21"; break; case Orbit::PHI21_PHI31: return "cgogn::Orbit::PHI21_PHI31"; break; - default: cgogn_assert_not_reached("This orbit does not exist"); break; + default: cgogn_assert_not_reached("This orbit does not exist"); return "UNKNOWN"; break; } - return "UNKNOWN"; +// return "UNKNOWN"; } /** diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 62041662..18afee1d 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -211,12 +211,12 @@ class CMap1_T : public MapBase { foreach_incident_vertex(f, [this] (Cell c) { - this->template set_orbit_embedding(c, this->template add_attribute_element()); + this->set_orbit_embedding(c, this->template add_attribute_element()); }); } if (this->template is_orbit_embedded()) - this->template set_orbit_embedding(f, this->template add_attribute_element()); + this->set_orbit_embedding(f, this->template add_attribute_element()); return f; } diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 6afcf43a..e552411d 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -240,7 +240,7 @@ class CMap2_T : public CMap1_T { foreach_incident_vertex(f, [this] (Cell c) { - this->template set_orbit_embedding(c, this->template add_attribute_element()); + this->set_orbit_embedding(c, this->template add_attribute_element()); }); } @@ -248,12 +248,12 @@ class CMap2_T : public CMap1_T { foreach_incident_edge(f, [this] (Cell c) { - this->template set_orbit_embedding(c, this->template add_attribute_element()); + this->set_orbit_embedding(c, this->template add_attribute_element()); }); } if (this->template is_orbit_embedded()) - this->template set_orbit_embedding(f, this->template add_attribute_element()); + this->set_orbit_embedding(f, this->template add_attribute_element()); if (this->template is_orbit_embedded()) this->template set_orbit_embedding(d, this->template add_attribute_element()); diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 5ff870af..6e17c6ce 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -586,7 +586,7 @@ class MapBase : public MapBaseData using VecDarts = std::vector; ThreadPool* thread_pool = cgogn::get_thread_pool(); - const unsigned int nb_threads_pool = thread_pool->get_nb_threads(); + const std::size_t nb_threads_pool = thread_pool->get_nb_threads(); std::array, 2> dart_buffers; std::array, 2> futures; @@ -783,7 +783,7 @@ class MapBase : public MapBaseData using Future = std::future< typename std::result_of, unsigned int)>::type >; ThreadPool* thread_pool = cgogn::get_thread_pool(); - const unsigned int nb_threads_pool = thread_pool->get_nb_threads(); + const std::size_t nb_threads_pool = thread_pool->get_nb_threads(); std::array, 2> cells_buffers; std::array, 2> futures; @@ -866,7 +866,7 @@ class MapBase : public MapBaseData using Future = std::future< typename std::result_of, unsigned int)>::type >; ThreadPool* thread_pool = cgogn::get_thread_pool(); - const unsigned int nb_threads_pool = thread_pool->get_nb_threads(); + const std::size_t nb_threads_pool = thread_pool->get_nb_threads(); std::array, 2> cells_buffers; std::array, 2> futures; @@ -944,7 +944,7 @@ class MapBase : public MapBaseData using Future = std::future< typename std::result_of, unsigned int)>::type >; ThreadPool* thread_pool = cgogn::get_thread_pool(); - const unsigned int nb_threads_pool = thread_pool->get_nb_threads(); + const std::size_t nb_threads_pool = thread_pool->get_nb_threads(); std::array, 2> cells_buffers; std::array, 2> futures; diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index 9961d5fa..c05ae3a3 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -294,7 +294,7 @@ class MapBaseData : public MapGen std::advance(end, NB_UNKNOWN_THREADS); auto res_it = std::find(thread_ids_.begin(), end, thread_id); if (res_it != end) - return std::distance(thread_ids_.begin(), res_it); + return (unsigned int)(std::distance(thread_ids_.begin(), res_it)); return add_unknown_thread(); } @@ -308,7 +308,7 @@ class MapBaseData : public MapGen const auto end = thread_ids_.end(); auto it_lower_bound = std::lower_bound(real_begin, end, std::this_thread::get_id()); if (it_lower_bound != end) - return std::distance(thread_ids_.begin(),it_lower_bound); + return (unsigned int)(std::distance(thread_ids_.begin(),it_lower_bound)); return get_unknown_thread_index(std::this_thread::get_id()); } diff --git a/cgogn/core/container/chunk_array_factory.h b/cgogn/core/container/chunk_array_factory.h index 98b3136e..be830593 100644 --- a/cgogn/core/container/chunk_array_factory.h +++ b/cgogn/core/container/chunk_array_factory.h @@ -46,7 +46,7 @@ class ChunkArrayFactory typedef std::unique_ptr< ChunkArrayGen > ChunkArrayGenPtr; typedef std::map NamePtrMap; - static NamePtrMap map_CA_; + static NamePtrMap* map_CA_; /** * @brief register a type @@ -57,8 +57,8 @@ class ChunkArrayFactory static void register_CA() { std::string&& keyType(name_of_type(T())); - if(map_CA_.find(keyType) == map_CA_.end()) - map_CA_[std::move(keyType)] = make_unique>(); + if(map_CA_->find(keyType) == map_CA_->end()) + (*map_CA_)[std::move(keyType)] = make_unique>(); } static void register_known_types() @@ -98,9 +98,9 @@ class ChunkArrayFactory static ChunkArrayGen* create(const std::string& keyType) { ChunkArrayGen* tmp = nullptr; - typename NamePtrMap::const_iterator it = map_CA_.find(keyType); + typename NamePtrMap::const_iterator it = map_CA_->find(keyType); - if(it != map_CA_.end()) + if(it != map_CA_->end()) { tmp = (it->second)->clone(); } @@ -112,12 +112,12 @@ class ChunkArrayFactory static void reset() { - ChunkArrayFactory::map_CA_ = NamePtrMap(); + ChunkArrayFactory::map_CA_ = new NamePtrMap(); } }; template -typename ChunkArrayFactory::NamePtrMap ChunkArrayFactory::map_CA_= typename ChunkArrayFactory::NamePtrMap(); +typename ChunkArrayFactory::NamePtrMap* ChunkArrayFactory::map_CA_ = nullptr;//typename ChunkArrayFactory::NamePtrMap(); #if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_CONTAINER_CHUNK_ARRAY_FACTORY_CPP_)) diff --git a/cgogn/core/utils/definitions.h b/cgogn/core/utils/definitions.h index c76e3058..00aff708 100644 --- a/cgogn/core/utils/definitions.h +++ b/cgogn/core/utils/definitions.h @@ -37,7 +37,8 @@ /* * Thread local storage. In VS <1900 it works only with POD types. */ -#if defined(_MSC_VER) && _MSC_VER < 1900 +//#if defined(_MSC_VER) && _MSC_VER < 1900 +#if defined(_MSC_VER) #define CGOGN_TLS __declspec( thread ) #else #define CGOGN_TLS __thread From 7c0ea58c8397e0aab93655c860c23fe5dd30c4df Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Tue, 9 Feb 2016 17:22:22 +0100 Subject: [PATCH 072/402] remove memory leak of staticc ptr by using std::unique_ptr --- cgogn/core/cmap/map_base_data.h | 12 ++++++------ cgogn/core/container/chunk_array_factory.h | 11 ++++++++--- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index c05ae3a3..f857dcf7 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -206,7 +206,7 @@ class MapBaseData : public MapGen */ inline ChunkArray* get_topology_mark_attribute() { - unsigned int thread = this->get_current_thread_index(); + std::size_t thread = this->get_current_thread_index(); if (!this->mark_attributes_topology_[thread].empty()) { ChunkArray* ca = this->mark_attributes_topology_[thread].back(); @@ -227,7 +227,7 @@ class MapBaseData : public MapGen */ inline void release_topology_mark_attribute(ChunkArray* ca) { - unsigned int thread = this->get_current_thread_index(); + std::size_t thread = this->get_current_thread_index(); this->mark_attributes_topology_[thread].push_back(ca); } @@ -288,18 +288,18 @@ class MapBaseData : public MapGen return old_index; } - inline unsigned int get_unknown_thread_index(std::thread::id thread_id) const + inline std::size_t get_unknown_thread_index(std::thread::id thread_id) const { auto end = thread_ids_.begin(); std::advance(end, NB_UNKNOWN_THREADS); auto res_it = std::find(thread_ids_.begin(), end, thread_id); if (res_it != end) - return (unsigned int)(std::distance(thread_ids_.begin(), res_it)); + return std::distance(thread_ids_.begin(), res_it); return add_unknown_thread(); } - inline unsigned int get_current_thread_index() const + inline std::size_t get_current_thread_index() const { // avoid the unknown threads stored at the beginning of the vector auto real_begin =thread_ids_.begin(); @@ -308,7 +308,7 @@ class MapBaseData : public MapGen const auto end = thread_ids_.end(); auto it_lower_bound = std::lower_bound(real_begin, end, std::this_thread::get_id()); if (it_lower_bound != end) - return (unsigned int)(std::distance(thread_ids_.begin(),it_lower_bound)); + return std::distance(thread_ids_.begin(),it_lower_bound); return get_unknown_thread_index(std::this_thread::get_id()); } diff --git a/cgogn/core/container/chunk_array_factory.h b/cgogn/core/container/chunk_array_factory.h index be830593..765c087d 100644 --- a/cgogn/core/container/chunk_array_factory.h +++ b/cgogn/core/container/chunk_array_factory.h @@ -45,8 +45,9 @@ class ChunkArrayFactory public: typedef std::unique_ptr< ChunkArrayGen > ChunkArrayGenPtr; typedef std::map NamePtrMap; + typedef std::unique_ptr UniqueNamePtrMap; - static NamePtrMap* map_CA_; + static UniqueNamePtrMap map_CA_; /** * @brief register a type @@ -56,6 +57,10 @@ class ChunkArrayFactory template static void register_CA() { + // could be moved in register_known_types (dangerous) ?? + if (!map_CA_) + reset(); + std::string&& keyType(name_of_type(T())); if(map_CA_->find(keyType) == map_CA_->end()) (*map_CA_)[std::move(keyType)] = make_unique>(); @@ -112,12 +117,12 @@ class ChunkArrayFactory static void reset() { - ChunkArrayFactory::map_CA_ = new NamePtrMap(); + ChunkArrayFactory::map_CA_ = make_unique(); } }; template -typename ChunkArrayFactory::NamePtrMap* ChunkArrayFactory::map_CA_ = nullptr;//typename ChunkArrayFactory::NamePtrMap(); +typename ChunkArrayFactory::UniqueNamePtrMap ChunkArrayFactory::map_CA_ = nullptr; #if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_CONTAINER_CHUNK_ARRAY_FACTORY_CPP_)) From 11c4ea23a3f9e3f68ee0c869544a3339a2465468 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Tue, 9 Feb 2016 17:22:22 +0100 Subject: [PATCH 073/402] remove memory leak of staticc ptr by using std::unique_ptr --- cgogn/core/cmap/map_base_data.h | 12 ++++++------ cgogn/core/container/chunk_array_factory.h | 11 ++++++++--- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index f15b40c1..e8a22545 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -201,7 +201,7 @@ class MapBaseData : public MapGen */ inline ChunkArray* get_topology_mark_attribute() { - unsigned int thread = this->get_current_thread_index(); + std::size_t thread = this->get_current_thread_index(); if (!this->mark_attributes_topology_[thread].empty()) { ChunkArray* ca = this->mark_attributes_topology_[thread].back(); @@ -222,7 +222,7 @@ class MapBaseData : public MapGen */ inline void release_topology_mark_attribute(ChunkArray* ca) { - unsigned int thread = this->get_current_thread_index(); + std::size_t thread = this->get_current_thread_index(); this->mark_attributes_topology_[thread].push_back(ca); } @@ -284,18 +284,18 @@ class MapBaseData : public MapGen return old_index; } - inline unsigned int get_unknown_thread_index(std::thread::id thread_id) const + inline std::size_t get_unknown_thread_index(std::thread::id thread_id) const { auto end = thread_ids_.begin(); std::advance(end, NB_UNKNOWN_THREADS); auto res_it = std::find(thread_ids_.begin(), end, thread_id); if (res_it != end) - return (unsigned int)(std::distance(thread_ids_.begin(), res_it)); + return std::distance(thread_ids_.begin(), res_it); return add_unknown_thread(); } - inline unsigned int get_current_thread_index() const + inline std::size_t get_current_thread_index() const { // avoid the unknown threads stored at the beginning of the vector auto real_begin =thread_ids_.begin(); @@ -304,7 +304,7 @@ class MapBaseData : public MapGen const auto end = thread_ids_.end(); auto it_lower_bound = std::lower_bound(real_begin, end, std::this_thread::get_id()); if (it_lower_bound != end) - return (unsigned int)(std::distance(thread_ids_.begin(),it_lower_bound)); + return std::distance(thread_ids_.begin(),it_lower_bound); return get_unknown_thread_index(std::this_thread::get_id()); } diff --git a/cgogn/core/container/chunk_array_factory.h b/cgogn/core/container/chunk_array_factory.h index be830593..765c087d 100644 --- a/cgogn/core/container/chunk_array_factory.h +++ b/cgogn/core/container/chunk_array_factory.h @@ -45,8 +45,9 @@ class ChunkArrayFactory public: typedef std::unique_ptr< ChunkArrayGen > ChunkArrayGenPtr; typedef std::map NamePtrMap; + typedef std::unique_ptr UniqueNamePtrMap; - static NamePtrMap* map_CA_; + static UniqueNamePtrMap map_CA_; /** * @brief register a type @@ -56,6 +57,10 @@ class ChunkArrayFactory template static void register_CA() { + // could be moved in register_known_types (dangerous) ?? + if (!map_CA_) + reset(); + std::string&& keyType(name_of_type(T())); if(map_CA_->find(keyType) == map_CA_->end()) (*map_CA_)[std::move(keyType)] = make_unique>(); @@ -112,12 +117,12 @@ class ChunkArrayFactory static void reset() { - ChunkArrayFactory::map_CA_ = new NamePtrMap(); + ChunkArrayFactory::map_CA_ = make_unique(); } }; template -typename ChunkArrayFactory::NamePtrMap* ChunkArrayFactory::map_CA_ = nullptr;//typename ChunkArrayFactory::NamePtrMap(); +typename ChunkArrayFactory::UniqueNamePtrMap ChunkArrayFactory::map_CA_ = nullptr; #if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_CONTAINER_CHUNK_ARRAY_FACTORY_CPP_)) From 4523cb0133c26645af4258298ee52588c5499ee9 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Tue, 9 Feb 2016 17:47:01 +0100 Subject: [PATCH 074/402] =?UTF-8?q?Utilation=20du=20nouveau=20set=5Fembedd?= =?UTF-8?q?ing=20pour=20les=20op=C3=A9rateurs=20plong=C3=A9s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cgogn/core/cmap/cmap0.h | 13 +++--- cgogn/core/cmap/cmap1.h | 70 ++++++++++++++++---------------- cgogn/core/cmap/cmap2.h | 71 ++++++++++++++++++--------------- cgogn/core/cmap/map_base_data.h | 9 ++--- cgogn/core/tests/main.cpp | 47 +++++++++++++++++++++- 5 files changed, 129 insertions(+), 81 deletions(-) diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index 6802f84d..01e9d913 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -81,21 +81,22 @@ class CMap0_T : public MapBase protected: inline Dart add_dart() { + cgogn_assert(typeid(*this).hash_code() == typeid(Self).hash_code()); unsigned int di = this->add_topology_element(); - Dart d(di); - return d; + return Dart(di); } public: Vertex add_vertex() { Dart d = this->to_concrete()->add_dart(); - Vertex v(d); - if (this->template is_orbit_embedded()) - init_orbit_embedding(d, this->template add_attribute_element()); + if (this->template is_orbit_embedded()) { + unsigned int idx = this->template add_attribute_element(); + this->template set_embedding(d, idx); + } - return v; + return Vertex(d); } protected: diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index ae010302..45cc9a05 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -172,13 +172,11 @@ class CMap1_T : public MapBase */ inline Dart add_dart() { + cgogn_assert(typeid(*this).hash_code() == typeid(Self).hash_code()); unsigned int di = this->add_topology_element(); - Dart d(di); - (*phi1_)[di] = d; (*phi_1_)[di] = d; - return d; } @@ -187,39 +185,10 @@ class CMap1_T : public MapBase this->remove_topology_element(d.index); } -public: - /******************************************************************************* * High-level topological operations *******************************************************************************/ - /** - * \brief add_face - * @param nb_edges - * @return - */ - Face add_face(unsigned int nb_edges) - { - cgogn_message_assert(nb_edges > 0, "Cannot create a face with no edge"); - - Dart d = add_face_topo(nb_edges); - - Face f(d); - - if (this->template is_orbit_embedded()) - { - foreach_incident_vertex(f, [this] (Cell c) - { - this->template set_orbit_embedding(c, this->template add_attribute_element()); - }); - } - - if (this->template is_orbit_embedded()) - this->template set_orbit_embedding(f, this->template add_attribute_element()); - - return f; - } - protected: inline Dart add_face_topo(unsigned int nb_edges) @@ -253,8 +222,8 @@ class CMap1_T : public MapBase */ inline Dart cut_edge_topo(Dart d) { - Dart e = this->to_concrete()->add_dart(); // Create a new dart - phi1_sew(d, e); // Insert dart e between d and phi1(d) + Dart e = this->to_concrete()->add_dart(); // Create a new dart e + phi1_sew(d, e); // Insert e between d and phi1(d) return e; } @@ -293,7 +262,7 @@ class CMap1_T : public MapBase Dart nd = cut_edge_topo(phi_1(d)); // cut the edge before d (insert a new dart before d) Dart ne = cut_edge_topo(phi_1(e)); // cut the edge before e (insert a new dart before e) - + phi1_sew(nd, ne); // subdivide phi1 cycle at the inserted darts } @@ -306,7 +275,7 @@ class CMap1_T : public MapBase if (e == d) return; // Only two edges: nothing to do - if (phi1(e) == d) return; + if (phi1(e) == d) return; // Detach e from the face of d phi1_unsew(d); @@ -328,6 +297,35 @@ class CMap1_T : public MapBase public: + /** + * \brief add_face + * @param nb_edges + * @return + */ + Face add_face(unsigned int nb_edges) + { + cgogn_message_assert(nb_edges > 0, "Cannot create a face with no edge"); + + Dart d = add_face_topo(nb_edges); + Face f(d); + + if (this->template is_orbit_embedded()) + { + foreach_dart_of_PHI1(d, [this] (Dart e) + { + unsigned int idx = this->template add_attribute_element(); + this->template set_embedding(e, idx); + }); + } + + if (this->template is_orbit_embedded()) { + unsigned int idx = this->template add_attribute_element(); + this->template set_orbit_embedding(f, idx); + } + + return f; + } + inline unsigned int degree(Face f) const { return this->nb_darts(f); diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 90d33c69..d077c997 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -51,6 +51,7 @@ class CMap2_T : public CMap1_T friend class CMap2Builder_T; friend class DartMarker_T; + static const Orbit DART = Orbit::DART; static const Orbit VERTEX = Orbit::PHI21; static const Orbit EDGE = Orbit::PHI2; static const Orbit FACE = Orbit::PHI1; @@ -160,6 +161,7 @@ class CMap2_T : public CMap1_T */ inline Dart add_dart() { + cgogn_assert(typeid(*this).hash_code() == typeid(Self).hash_code()); Dart d = Inherit::add_dart(); (*phi2_)[d.index] = d; return d; @@ -176,30 +178,37 @@ class CMap2_T : public CMap1_T { close_hole_topo(d); Dart new_face = phi2(d); - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) { foreach_dart_of_orbit(new_face, [this] (Dart fd) { - this->template set_orbit_embedding(fd, this->template add_attribute_element()); + this->template set_orbit_embedding(fd, this->template add_attribute_element()); }); } - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) { foreach_dart_of_orbit(new_face, [this] (Dart fd) { - this->template set_embedding(fd, this->template get_embedding(this->phi1(phi2(fd)))); + this->template set_embedding(fd, this->template get_embedding(this->phi1(phi2(fd)))); }); } - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) { foreach_dart_of_orbit(new_face, [this] (Dart fd) { - this->template set_embedding(fd, this->template get_embedding(phi2(fd))); + this->template set_embedding(fd, this->template get_embedding(phi2(fd))); }); } - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) { - this->template set_orbit_embedding(new_face, this->template add_attribute_element()); + this->template set_orbit_embedding(new_face, this->template add_attribute_element()); + } + if (this->template is_orbit_embedded()) + { + foreach_dart_of_orbit(new_face, [this,new_face] (Dart fd) + { + this->template set_embedding(fd, this->template get_embedding(new_face)); + }); } } } @@ -229,9 +238,9 @@ class CMap2_T : public CMap1_T if (this->template is_orbit_embedded()) { - foreach_dart_of_orbit(f, [this] (Dart fd) + this->foreach_dart_of_orbit(f, [this] (Cell df) { - this->template set_orbit_embedding(fd, this->template add_attribute_element()); + this->template set_orbit_embedding(df, this->template add_attribute_element()); }); } @@ -255,7 +264,7 @@ class CMap2_T : public CMap1_T this->template set_orbit_embedding(f, this->template add_attribute_element()); if (this->template is_orbit_embedded()) - this->template set_orbit_embedding(d, this->template add_attribute_element()); + this->template set_orbit_embedding(Volume(d), this->template add_attribute_element()); return f; } @@ -270,33 +279,31 @@ class CMap2_T : public CMap1_T if(this->template is_orbit_embedded()) { - this->template init_embedding(nd, this->template add_attribute_element()); - this->template init_embedding(ne, this->template add_attribute_element()); + this->template set_embedding(nd, this->template add_attribute_element()); + this->template set_embedding(ne, this->template add_attribute_element()); } if (this->template is_orbit_embedded()) { - init_orbit_embedding(v, this->template add_attribute_element()); + this->template set_orbit_embedding(v, this->template add_attribute_element()); } if (this->template is_orbit_embedded()) { - this->template init_embedding(ne, this->template get_embedding(d.dart)); - // pour que le unref du set_orbit suivant fonctionne - this->template init_embedding(nd, this->template get_embedding(e)); - set_orbit_embedding(nd, this->template add_attribute_element()); + this->template set_embedding(ne, this->template get_embedding(d.dart)); + this->template set_orbit_embedding(Edge(nd), this->template add_attribute_element()); } if (this->template is_orbit_embedded()) { - this->template init_embedding(nd, this->template get_embedding(d.dart)); - this->template init_embedding(ne, this->template get_embedding(e)); + this->template set_embedding(nd, this->template get_embedding(d.dart)); + this->template set_embedding(ne, this->template get_embedding(e)); } if (this->template is_orbit_embedded()) { - this->template init_embedding(nd, this->template get_embedding(d.dart)); - this->template init_embedding(ne, this->template get_embedding(e)); + this->template set_embedding(nd, this->template get_embedding(d.dart)); + this->template set_embedding(ne, this->template get_embedding(e)); } return v; @@ -310,33 +317,31 @@ class CMap2_T : public CMap1_T if(this->template is_orbit_embedded()) { - this->template init_embedding(nd, this->template add_attribute_element()); - this->template init_embedding(ne, this->template add_attribute_element()); + this->template set_embedding(nd, this->template add_attribute_element()); + this->template set_embedding(ne, this->template add_attribute_element()); } if (this->template is_orbit_embedded()) { - this->template init_embedding(nd, this->template get_embedding(d)); - this->template init_embedding(ne, this->template get_embedding(e)); + this->template set_embedding(nd, this->template get_embedding(d)); + this->template set_embedding(ne, this->template get_embedding(e)); } if (this->template is_orbit_embedded()) { - init_orbit_embedding(nd, this->template add_attribute_element()); + this->template set_orbit_embedding(nd, this->template add_attribute_element()); } if (this->template is_orbit_embedded()) { - this->template init_embedding(ne, this->template get_embedding(d)); - // pour que le unref du set_orbit suivant fonctionne - this->template init_embedding(nd, this->template get_embedding(e)); - init_orbit_embedding(e, this->template add_attribute_element()); + this->template set_embedding(ne, this->template get_embedding(d)); + this->template set_orbit_embedding(e, this->template add_attribute_element()); } if (this->template is_orbit_embedded()) { - init_orbit_embedding(nd, this->template get_embedding(d)); - init_orbit_embedding(ne, this->template get_embedding(d)); + this->template set_orbit_embedding(nd, this->template get_embedding(d)); + this->template set_orbit_embedding(ne, this->template get_embedding(d)); } } diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index 2f3e176a..3219178e 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -259,13 +259,12 @@ class MapBaseData : public MapGen unsigned int old = (*embeddings_[ORBIT])[d.index]; - if (old == emb) return; - + // ref_line() is done before unref_line() to avoid deleting the indexed line if old == emb + this->attributes_[ORBIT].ref_line(emb); // ref the new emb if (old != EMBNULL) - this->attributes_[ORBIT].unref_line(old); // unref the old emb - this->attributes_[ORBIT].ref_line(emb); // ref the new emb + this->attributes_[ORBIT].unref_line(old); // unref the old emb - (*this->embeddings_[ORBIT])[d.index] = emb; // affect the embedding to the dart + (*this->embeddings_[ORBIT])[d.index] = emb; // affect the embedding to the dart } /******************************************************************************* diff --git a/cgogn/core/tests/main.cpp b/cgogn/core/tests/main.cpp index 4f2383f9..e8143d56 100644 --- a/cgogn/core/tests/main.cpp +++ b/cgogn/core/tests/main.cpp @@ -28,12 +28,57 @@ // using ::testing::AtLeast; + +class Carte { +public: + void begin() { + std::cout << "Carte() " << val << std::endl; + } + Carte(int v) { + val = v; + std::cout << "constructor Carte() " << val << std::endl; + } + Carte(const Carte& c) { + val = c.val; + std::cout << "constructor Carte() " << val << std::endl; + } + +protected: + int val; +}; + +class Browser1 : Carte { +public: + void begin() { + Carte::begin(); + std::cout << "Browser1()" << val << std::endl; + } + Browser1(const Carte& c) : Carte(c) { + } +}; + +class Browser2 : Carte { +public: + void begin() { + Carte::begin(); + std::cout << "Browser2()" << val << std::endl; + } + Browser2(const Carte& c) : Carte(c) { + } +}; + int main(int argc, char **argv) { + Carte carte(3); + + carte.begin(); + static_cast(carte).begin(); + static_cast(carte).begin(); + testing::InitGoogleTest(&argc, argv); // testing::InitGoogleMock(&argc, argv); // Set LC_CTYPE according to the environnement variable. setlocale(LC_CTYPE, ""); - return RUN_ALL_TESTS(); + return 0; //RUN_ALL_TESTS(); } From e868dbb249c6595ac6a45d9044587bc290850592 Mon Sep 17 00:00:00 2001 From: lionel untereiner Date: Wed, 10 Feb 2016 09:19:26 +0100 Subject: [PATCH 075/402] changing explicit mr representation --- cgogn/multiresolution/CMakeLists.txt | 1 + cgogn/multiresolution/mrcmap/mr_base.h | 170 +++++++++++++++++++++++++ cgogn/multiresolution/mrcmap/mrcmap2.h | 127 ++---------------- 3 files changed, 181 insertions(+), 117 deletions(-) create mode 100644 cgogn/multiresolution/mrcmap/mr_base.h diff --git a/cgogn/multiresolution/CMakeLists.txt b/cgogn/multiresolution/CMakeLists.txt index f7647a58..398742b7 100644 --- a/cgogn/multiresolution/CMakeLists.txt +++ b/cgogn/multiresolution/CMakeLists.txt @@ -14,6 +14,7 @@ set(HEADER_FILES cph/ihcmap2_regular.h cph/ihcmap3.h + mrcmap/mr_base.h mrcmap/mrcmap2.h mra/mr_analysis.h diff --git a/cgogn/multiresolution/mrcmap/mr_base.h b/cgogn/multiresolution/mrcmap/mr_base.h new file mode 100644 index 00000000..132f8449 --- /dev/null +++ b/cgogn/multiresolution/mrcmap/mr_base.h @@ -0,0 +1,170 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef MULTIRESOLUTION_MRCMAP_MRCMAP2_H_ +#define MULTIRESOLUTION_MRCMAP_MRCMAP2_H_ + + +#include +#include + + +namespace cgogn +{ + +template +class MRBase +{ +public: + typedef MRBase Self; + + template + using ChunkArray = typename CMap2::template ChunkArray; + +protected: + /** + * pointers to maps (one for each level) + */ + std::deque maps_; + + /** + * pointers to attributs that stores next level + * correspondance indices for each dart + */ + std::deque*> next_level_indices_; + + /** + * pointers to attributs that stores previous level + * correspondance indices for each dart + */ + std::deque*> previous_level_indices_; + + /** + * stack for current level temporary storage + */ + std::stack> levels_stack_ ; + + /** + * current level in multiresolution map + */ + unsigned int current_level_; + + //TODO le niveau courant doit etre par thread + //appele sur la carte et non plus un champs de + //la classe carte + +public: + + MRBase() + {} + + ~MRBase() + {} + + MRBase(Self const&) = delete; + MRBase(Self &&) = delete; + Self& operator=(Self const&) = delete; + Self& operator=(Self &&) = delete; + + inline void add_level_back() + { + //ajouter une carte par copie dans maps_ + //ajouter un chunkarray dans next_ + CMap2* last = maps_.back(); + maps_.emplace_back(last); + } + + inline void remove_level_back() + { + maps_.pop_back(); + } + + inline void add_level_front() + { + CMap2* first = maps_.front(); + maps.emplace_front(first); + } + + inline void remove_level_front() + { + maps_.pop_front(); + } + + //1 thread par niveau = 1 thread par carte + //n thread par niveau = n thread par carte + + inline unsigned int get_maximum_level() const + { + return static_cast(maps_.size()); + } + + inline unsigned int get_current_level() const + { + return current_level_; + } + + inline void set_current_level(unsigned int l) + { + current_level_ = l; + } + + inline void inc_current_level() + { + cgogn_debug_assert(get_current_level() < maps_.size() - 1, "incCurrentLevel : already at maximum resolution level"); + ++current_level_; + } + + inline void dec_current_level() + { + cgogn_debug_assert(get_current_level() > 0, "decCurrentLevel : already at minimum resolution level"); + --current_level_; + } + + /** + * store current resolution level on a stack + */ + inline void push_level() + { + levels_stack_.push_back(get_current_level()) ; + } + + /** + * set as current the resolution level of the top of the stack + */ + inline void pop_level() + { + set_current_level(levels_stack_.back()) ; + levels_stack_.pop_back() ; + } + + inline const MAP* current() const + { + return maps_[get_current_level()]; + } + +}; + + +} + +#endif // MULTIRESOLUTION_MRCMAP_MRCMAP2_H_ diff --git a/cgogn/multiresolution/mrcmap/mrcmap2.h b/cgogn/multiresolution/mrcmap/mrcmap2.h index 88580f60..5a347c5b 100644 --- a/cgogn/multiresolution/mrcmap/mrcmap2.h +++ b/cgogn/multiresolution/mrcmap/mrcmap2.h @@ -21,12 +21,11 @@ * * *******************************************************************************/ -#ifndef CORE_MRCMAP_MRCMAP2_H_ -#define CORE_MRCMAP_MRCMAP2_H_ +#ifndef MULTIRESOLUTION_MRCMAP_MRCMAP2_H_ +#define MULTIRESOLUTION_MRCMAP_MRCMAP2_H_ -#include -#include -#include +#include +#include namespace cgogn { @@ -42,65 +41,11 @@ class MRCMap2_T template using ChunkArray = typename CMap2::template ChunkArray; - protected: - /** - * pointers to maps (one for each level) - */ - std::deque maps_; - - /** - * pointers to attributs that stores next level - * correspondance indices for each dart - */ - std::deque*> next_level_indices_; - - /** - * pointers to attributs that stores previous level - * correspondance indices for each dart - */ - std::deque*> previous_level_indices_; - - /** - * stack for current level temporary storage - */ - std::stack> levels_stack_ ; - - /** - * current level in multiresolution map - */ - unsigned int current_level_; - - //TODO le niveau courant doit etre par thread - //appele sur la carte et non plus un champs de - //la classe carte + MRBase mrmap2; - inline void add_level_back() - { - //ajouter une carte par copie dans maps_ - //ajouter un chunkarray dans next_ - CMap2* last = maps_.back(); - maps_.emplace_back(last); - } - - inline void remove_level_back() - { - maps_.pop_back(); - } - - inline void add_level_front() - { - CMap2* first = maps_.front(); - maps.emplace_front(first); - } - - inline void remove_level_front() - { - maps_.pop_front(); - } - public: MRCMap2_T() @@ -115,60 +60,7 @@ class MRCMap2_T Self& operator=(Self &&) = delete; - //1 thread par niveau = 1 thread par carte - //n thread par niveau = n thread par carte - - inline unsigned int get_maximum_level() const - { - return static_cast(maps_.size()); - } - - inline unsigned int get_current_level() const - { - return current_level_; - } - - inline void set_current_level(unsigned int l) - { - current_level_ = l; - } - - inline void inc_current_level() - { - cgogn_debug_assert(get_current_level() < maps_.size() - 1, "incCurrentLevel : already at maximum resolution level"); - ++current_level_; - } - - inline void dec_current_level() - { - cgogn_debug_assert(get_current_level() > 0, "decCurrentLevel : already at minimum resolution level"); - --current_level_; - } - - /** - * store current resolution level on a stack - */ - inline void push_level() - { - levels_stack_.push_back(get_current_level()) ; - } - - /** - * set as current the resolution level of the top of the stack - */ - inline void pop_level() - { - set_current_level(levels_stack_.back()) ; - levels_stack_.pop_back() ; - } - - inline const CMap2* current() const - { - return maps_[get_current_level()]; - } - protected: - /******************************************************************************* * Orbits traversal *******************************************************************************/ @@ -176,21 +68,22 @@ class MRCMap2_T template inline void foreach_dart_of_vertex(Dart d, const FUNC& f) const { - current()->foreach_dart_of_vertex(d, f); + mrmap2.current()->foreach_dart_of_vertex(d, f); } template inline void foreach_dart_of_face(Dart d, const FUNC& f) const { - current()->foreach_dart_of_face(d, f); + mrmap2.current()->foreach_dart_of_face(d, f); } template void foreach_dart_of_volume(Dart d, const FUNC& f) const { - current()->foreach_dart_of_volume(d, f); + mrmap2.current()->foreach_dart_of_volume(d, f); } +public: template inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const { @@ -211,4 +104,4 @@ class MRCMap2_T } // namespace cgogn -#endif // CORE_MRCMAP_MRCMAP2_H_ +#endif // MULTIRESOLUTION_MRCMAP_MRCMAP2_H_ From ca89195a32ffb3694863d1278ba35d5f20308593 Mon Sep 17 00:00:00 2001 From: lionel untereiner Date: Wed, 10 Feb 2016 09:22:01 +0100 Subject: [PATCH 076/402] type correction --- cgogn/multiresolution/mrcmap/mr_base.h | 247 ++++++++++++------------- 1 file changed, 123 insertions(+), 124 deletions(-) diff --git a/cgogn/multiresolution/mrcmap/mr_base.h b/cgogn/multiresolution/mrcmap/mr_base.h index 132f8449..4b149400 100644 --- a/cgogn/multiresolution/mrcmap/mr_base.h +++ b/cgogn/multiresolution/mrcmap/mr_base.h @@ -21,13 +21,12 @@ * * *******************************************************************************/ -#ifndef MULTIRESOLUTION_MRCMAP_MRCMAP2_H_ -#define MULTIRESOLUTION_MRCMAP_MRCMAP2_H_ - +#ifndef MULTIRESOLUTION_MRCMAP_MR_BASE_H_ +#define MULTIRESOLUTION_MRCMAP_MR_BASE_H_ #include #include - +#include namespace cgogn { @@ -36,135 +35,135 @@ template class MRBase { public: - typedef MRBase Self; + typedef MRBase Self; - template - using ChunkArray = typename CMap2::template ChunkArray; + template + using ChunkArray = typename MAP::template ChunkArray; protected: - /** - * pointers to maps (one for each level) - */ - std::deque maps_; - - /** - * pointers to attributs that stores next level - * correspondance indices for each dart - */ - std::deque*> next_level_indices_; - - /** - * pointers to attributs that stores previous level - * correspondance indices for each dart - */ - std::deque*> previous_level_indices_; - - /** - * stack for current level temporary storage - */ - std::stack> levels_stack_ ; - - /** - * current level in multiresolution map - */ - unsigned int current_level_; - - //TODO le niveau courant doit etre par thread - //appele sur la carte et non plus un champs de - //la classe carte + /** + * pointers to maps (one for each level) + */ + std::deque maps_; + + /** + * pointers to attributs that stores next level + * correspondance indices for each dart + */ + std::deque*> next_level_indices_; + + /** + * pointers to attributs that stores previous level + * correspondance indices for each dart + */ + std::deque*> previous_level_indices_; + + /** + * stack for current level temporary storage + */ + std::stack> levels_stack_ ; + + /** + * current level in multiresolution map + */ + unsigned int current_level_; + + //TODO le niveau courant doit etre par thread + //appele sur la carte et non plus un champs de + //la classe carte public: - MRBase() - {} - - ~MRBase() - {} - - MRBase(Self const&) = delete; - MRBase(Self &&) = delete; - Self& operator=(Self const&) = delete; - Self& operator=(Self &&) = delete; - - inline void add_level_back() - { - //ajouter une carte par copie dans maps_ - //ajouter un chunkarray dans next_ - CMap2* last = maps_.back(); - maps_.emplace_back(last); - } - - inline void remove_level_back() - { - maps_.pop_back(); - } - - inline void add_level_front() - { - CMap2* first = maps_.front(); - maps.emplace_front(first); - } - - inline void remove_level_front() - { - maps_.pop_front(); - } - - //1 thread par niveau = 1 thread par carte - //n thread par niveau = n thread par carte - - inline unsigned int get_maximum_level() const - { - return static_cast(maps_.size()); - } - - inline unsigned int get_current_level() const - { - return current_level_; - } - - inline void set_current_level(unsigned int l) - { - current_level_ = l; - } - - inline void inc_current_level() - { - cgogn_debug_assert(get_current_level() < maps_.size() - 1, "incCurrentLevel : already at maximum resolution level"); - ++current_level_; - } - - inline void dec_current_level() - { - cgogn_debug_assert(get_current_level() > 0, "decCurrentLevel : already at minimum resolution level"); - --current_level_; - } - - /** - * store current resolution level on a stack - */ - inline void push_level() - { - levels_stack_.push_back(get_current_level()) ; - } - - /** - * set as current the resolution level of the top of the stack - */ - inline void pop_level() - { - set_current_level(levels_stack_.back()) ; - levels_stack_.pop_back() ; - } - - inline const MAP* current() const - { - return maps_[get_current_level()]; - } + MRBase() + {} + + ~MRBase() + {} + + MRBase(Self const&) = delete; + MRBase(Self &&) = delete; + Self& operator=(Self const&) = delete; + Self& operator=(Self &&) = delete; + + inline void add_level_back() + { + //ajouter une carte par copie dans maps_ + //ajouter un chunkarray dans next_ + MAP* last = maps_.back(); + maps_.push_back(last); + } + + inline void remove_level_back() + { + maps_.pop_back(); + } + + inline void add_level_front() + { + MAP* first = maps_.front(); + maps.push_front(first); + } + + inline void remove_level_front() + { + maps_.pop_front(); + } + + //1 thread par niveau = 1 thread par carte + //n thread par niveau = n thread par carte + + inline unsigned int get_maximum_level() const + { + return static_cast(maps_.size()); + } + + inline unsigned int get_current_level() const + { + return current_level_; + } + + inline void set_current_level(unsigned int l) + { + current_level_ = l; + } + + inline void inc_current_level() + { + cgogn_debug_assert(get_current_level() < maps_.size() - 1, "incCurrentLevel : already at maximum resolution level"); + ++current_level_; + } + + inline void dec_current_level() + { + cgogn_debug_assert(get_current_level() > 0, "decCurrentLevel : already at minimum resolution level"); + --current_level_; + } + + /** + * store current resolution level on a stack + */ + inline void push_level() + { + levels_stack_.push_back(get_current_level()) ; + } + + /** + * set as current the resolution level of the top of the stack + */ + inline void pop_level() + { + set_current_level(levels_stack_.back()) ; + levels_stack_.pop_back() ; + } + + inline const MAP* current() const + { + return maps_[get_current_level()]; + } }; } -#endif // MULTIRESOLUTION_MRCMAP_MRCMAP2_H_ +#endif // MULTIRESOLUTION_MRCMAP_MR_BASE_H_ From b2f103c0356b0fad596f2ae6cd9273ff6b0db456 Mon Sep 17 00:00:00 2001 From: lionel untereiner Date: Wed, 10 Feb 2016 10:40:36 +0100 Subject: [PATCH 077/402] adding mrcmap2 regular subdivision interface --- cgogn/multiresolution/cph/ihcmap2.h | 18 +- cgogn/multiresolution/cph/ihcmap2_regular.h | 32 +-- cgogn/multiresolution/mrcmap/mr_base.h | 238 +++++++++--------- cgogn/multiresolution/mrcmap/mrcmap2.h | 46 +++- .../multiresolution/mrcmap/mrcmap2_regular.h | 156 ++++++++++++ 5 files changed, 339 insertions(+), 151 deletions(-) create mode 100644 cgogn/multiresolution/mrcmap/mrcmap2_regular.h diff --git a/cgogn/multiresolution/cph/ihcmap2.h b/cgogn/multiresolution/cph/ihcmap2.h index 96005da6..dd88cedb 100644 --- a/cgogn/multiresolution/cph/ihcmap2.h +++ b/cgogn/multiresolution/cph/ihcmap2.h @@ -68,15 +68,15 @@ class IHCMap2_T : public CMap2_T, public CPH2; static const Orbit DART = Orbit::DART; - static const Orbit VERTEX = Orbit::PHI21; - static const Orbit EDGE = Orbit::PHI2; - static const Orbit FACE = Orbit::PHI1; - static const Orbit VOLUME = Orbit::PHI1_PHI2; - - typedef Cell Vertex; - typedef Cell Edge; - typedef Cell Face; - typedef Cell Volume; + static const Orbit VERTEX = Inherit_CMAP::VERTEX; + static const Orbit EDGE = Inherit_CMAP::EDGE; + static const Orbit FACE = Inherit_CMAP::FACE; + static const Orbit VOLUME = Inherit_CMAP::VOLUME; + + typedef Inherit_CMAP::Vertex Vertex; + typedef Inherit_CMAP::Edge Edge; + typedef Inherit_CMAP::Face Face; + typedef Inherit_CMAP::Volume Volume; template using ChunkArray = typename Inherit_CMAP::template ChunkArray; diff --git a/cgogn/multiresolution/cph/ihcmap2_regular.h b/cgogn/multiresolution/cph/ihcmap2_regular.h index 1cf83c02..290589d0 100644 --- a/cgogn/multiresolution/cph/ihcmap2_regular.h +++ b/cgogn/multiresolution/cph/ihcmap2_regular.h @@ -59,7 +59,7 @@ class IHCMap2Regular : public IHCMap2 Inherit::template foreach_cell([&] (typename Inherit::Edge e) { Dart dd = Inherit::phi2(e); -// Inherit::cut_edge(e); + // Inherit::cut_edge(e); unsigned int eid = Inherit::get_edge_id(e); Inherit::set_edge_id(Inherit::phi1(e), eid); @@ -77,7 +77,7 @@ class IHCMap2Regular : public IHCMap2 Dart dd = Inherit::phi1(old) ; Dart e = Inherit::phi1(Inherit::phi1(dd)) ; // insert a new edge -// Inherit::split_face(dd, e) ; + // Inherit::split_face(dd, e) ; unsigned int id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id) ; // set the edge id of the inserted @@ -85,14 +85,14 @@ class IHCMap2Regular : public IHCMap2 dd = e ; e = Inherit::phi1(Inherit::phi1(dd)) ; -// Inherit::split_face(dd, e) ; + // Inherit::split_face(dd, e) ; id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id) ; Inherit::set_edge_id(Inherit::phi_1(e), id) ; dd = e ; e = Inherit::phi1(Inherit::phi1(dd)) ; -// Inherit::split_face(dd, e) ; + // Inherit::split_face(dd, e) ; id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id) ; Inherit::set_edge_id(Inherit::phi_1(e), id) ; @@ -111,7 +111,7 @@ class IHCMap2Regular : public IHCMap2 Inherit::template foreach_cell([&] (typename Inherit::Edge e) { Dart dd = Inherit::phi2(e); -// Inherit::cut_edge(e); + // Inherit::cut_edge(e); unsigned int eid = Inherit::get_edge_id(e); Inherit::set_edge_id(Inherit::phi1(e), eid); @@ -128,11 +128,11 @@ class IHCMap2Regular : public IHCMap2 Dart dd = Inherit::phi1(old) ; Dart next = Inherit::phi1(Inherit::phi1(dd)) ; -// Inherit::split_face(dd, next) ; // insert a first edge + // Inherit::split_face(dd, next) ; // insert a first edge Dart ne = Inherit::phi2(Inherit::phi_1(dd)) ; Dart ne2 = Inherit::phi2(ne) ; -// Inherit::cut_edge(ne) ; // cut the new edge to insert the central vertex + // Inherit::cut_edge(ne) ; // cut the new edge to insert the central vertex unsigned int id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(ne))); Inherit::set_edge_id(ne, id) ; @@ -146,7 +146,7 @@ class IHCMap2Regular : public IHCMap2 while(dd != ne) // turn around the face and insert new edges { // linked to the central vertex Dart tmp = Inherit::phi1(ne) ; -// Inherit::split_face(tmp, dd) ; + // Inherit::split_face(tmp, dd) ; Dart nne = Inherit::phi2(Inherit::phi_1(dd)) ; @@ -170,7 +170,7 @@ class IHCMap2Regular : public IHCMap2 Inherit::template foreach_cell([&] (typename Inherit::Edge e) { Dart dd = Inherit::phi2(e); -// Inherit::cut_edge(e); + // Inherit::cut_edge(e); unsigned int eid = Inherit::get_edge_id(e); Inherit::set_edge_id(Inherit::phi1(e), eid); @@ -195,7 +195,7 @@ class IHCMap2Regular : public IHCMap2 Dart dd = Inherit::phi1(old) ; Dart e = Inherit::phi1(Inherit::phi1(dd)) ; // insert a new edge -// Inherit::split_face(dd, e) ; + // Inherit::split_face(dd, e) ; unsigned int id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id) ; // set the edge id of the inserted @@ -203,14 +203,14 @@ class IHCMap2Regular : public IHCMap2 dd = e ; e = Inherit::phi1(Inherit::phi1(dd)) ; -// Inherit::split_face(dd, e) ; + // Inherit::split_face(dd, e) ; id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id) ; Inherit::set_edge_id(Inherit::phi_1(e), id) ; dd = e ; e = Inherit::phi1(Inherit::phi1(dd)) ; -// Inherit::split_face(dd, e) ; + // Inherit::split_face(dd, e) ; id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id) ; Inherit::set_edge_id(Inherit::phi_1(e), id) ; @@ -219,11 +219,11 @@ class IHCMap2Regular : public IHCMap2 { Dart dd = Inherit::phi1(old) ; Dart next = Inherit::phi1(Inherit::phi1(dd)) ; -// Inherit::split_face(dd, next) ; // insert a first edge + // Inherit::split_face(dd, next) ; // insert a first edge Dart ne = Inherit::phi2(Inherit::phi_1(dd)) ; Dart ne2 = Inherit::phi2(ne) ; -// Inherit::cut_edge(ne) ; // cut the new edge to insert the central vertex + // Inherit::cut_edge(ne) ; // cut the new edge to insert the central vertex unsigned int id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(ne))); Inherit::set_edge_id(ne, id) ; @@ -237,7 +237,7 @@ class IHCMap2Regular : public IHCMap2 while(dd != ne) // turn around the face and insert new edges { // linked to the central vertex Dart tmp = Inherit::phi1(ne) ; -// Inherit::split_face(tmp, dd) ; + // Inherit::split_face(tmp, dd) ; Dart nne = Inherit::phi2(Inherit::phi_1(dd)) ; @@ -249,7 +249,7 @@ class IHCMap2Regular : public IHCMap2 } }); - Inherit::set_current_level(cur) ; + Inherit::set_current_level(cur) ; } }; diff --git a/cgogn/multiresolution/mrcmap/mr_base.h b/cgogn/multiresolution/mrcmap/mr_base.h index 4b149400..1f536400 100644 --- a/cgogn/multiresolution/mrcmap/mr_base.h +++ b/cgogn/multiresolution/mrcmap/mr_base.h @@ -41,125 +41,131 @@ class MRBase using ChunkArray = typename MAP::template ChunkArray; protected: - /** - * pointers to maps (one for each level) - */ - std::deque maps_; - - /** - * pointers to attributs that stores next level - * correspondance indices for each dart - */ - std::deque*> next_level_indices_; - - /** - * pointers to attributs that stores previous level - * correspondance indices for each dart - */ - std::deque*> previous_level_indices_; - - /** - * stack for current level temporary storage - */ - std::stack> levels_stack_ ; - - /** - * current level in multiresolution map - */ - unsigned int current_level_; - - //TODO le niveau courant doit etre par thread - //appele sur la carte et non plus un champs de - //la classe carte + /** + * pointers to maps (one for each level) + */ + std::deque maps_; + + /** + * pointers to attributs that stores next level + * correspondance indices for each dart + */ + std::deque*> next_level_indices_; + + /** + * pointers to attributs that stores previous level + * correspondance indices for each dart + */ + std::deque*> previous_level_indices_; + + /** + * stack for current level temporary storage + */ + std::stack> levels_stack_ ; + + /** + * current level in multiresolution map + */ + unsigned int current_level_; + + //TODO le niveau courant doit etre par thread + //appele sur la carte et non plus un champs de + //la classe carte public: - MRBase() - {} - - ~MRBase() - {} - - MRBase(Self const&) = delete; - MRBase(Self &&) = delete; - Self& operator=(Self const&) = delete; - Self& operator=(Self &&) = delete; - - inline void add_level_back() - { - //ajouter une carte par copie dans maps_ - //ajouter un chunkarray dans next_ - MAP* last = maps_.back(); - maps_.push_back(last); - } - - inline void remove_level_back() - { - maps_.pop_back(); - } - - inline void add_level_front() - { - MAP* first = maps_.front(); - maps.push_front(first); - } - - inline void remove_level_front() - { - maps_.pop_front(); - } - - //1 thread par niveau = 1 thread par carte - //n thread par niveau = n thread par carte - - inline unsigned int get_maximum_level() const - { - return static_cast(maps_.size()); - } - - inline unsigned int get_current_level() const - { - return current_level_; - } - - inline void set_current_level(unsigned int l) - { - current_level_ = l; - } - - inline void inc_current_level() - { - cgogn_debug_assert(get_current_level() < maps_.size() - 1, "incCurrentLevel : already at maximum resolution level"); - ++current_level_; - } - - inline void dec_current_level() - { - cgogn_debug_assert(get_current_level() > 0, "decCurrentLevel : already at minimum resolution level"); - --current_level_; - } - - /** - * store current resolution level on a stack - */ - inline void push_level() - { - levels_stack_.push_back(get_current_level()) ; - } - - /** - * set as current the resolution level of the top of the stack - */ - inline void pop_level() - { - set_current_level(levels_stack_.back()) ; - levels_stack_.pop_back() ; - } - - inline const MAP* current() const - { - return maps_[get_current_level()]; - } + MRBase() + {} + + ~MRBase() + {} + + MRBase(Self const&) = delete; + MRBase(Self &&) = delete; + Self& operator=(Self const&) = delete; + Self& operator=(Self &&) = delete; + + inline void add_level_back() + { + //ajouter une carte par copie dans maps_ + //ajouter un chunkarray dans next_ + MAP* last = maps_.back(); + maps_.push_back(last); + } + + inline void remove_level_back() + { + maps_.pop_back(); + } + + inline void add_level_front() + { + MAP* first = maps_.front(); + maps.push_front(first); + } + + inline void remove_level_front() + { + maps_.pop_front(); + } + + //1 thread par niveau = 1 thread par carte + //n thread par niveau = n thread par carte + + inline unsigned int get_maximum_level() const + { + return static_cast(maps_.size()); + } + + inline unsigned int get_current_level() const + { + return current_level_; + } + + inline void set_current_level(unsigned int l) + { + current_level_ = l; + } + + inline void inc_current_level() + { + cgogn_debug_assert(get_current_level() < maps_.size() - 1, "incCurrentLevel : already at maximum resolution level"); + ++current_level_; + } + + inline void dec_current_level() + { + cgogn_debug_assert(get_current_level() > 0, "decCurrentLevel : already at minimum resolution level"); + --current_level_; + } + + //TODO + inline unsigned int get_dart_level(Dart d) + { + return 0; + } + + /** + * store current resolution level on a stack + */ + inline void push_level() + { + levels_stack_.push_back(get_current_level()) ; + } + + /** + * set as current the resolution level of the top of the stack + */ + inline void pop_level() + { + set_current_level(levels_stack_.back()) ; + levels_stack_.pop_back() ; + } + + inline const MAP* current() const + { + return maps_[get_current_level()]; + } }; diff --git a/cgogn/multiresolution/mrcmap/mrcmap2.h b/cgogn/multiresolution/mrcmap/mrcmap2.h index 5a347c5b..feeb5cea 100644 --- a/cgogn/multiresolution/mrcmap/mrcmap2.h +++ b/cgogn/multiresolution/mrcmap/mrcmap2.h @@ -31,20 +31,22 @@ namespace cgogn { template -class MRCMap2_T +class MRCMap2_T : public MRBase> { public: typedef MRCMap2_T Self; typedef CMap2_T CMap2; - template - using ChunkArray = typename CMap2::template ChunkArray; - -protected: - - MRBase mrmap2; + static const Orbit VERTEX = CMap2::VERTEX; + static const Orbit EDGE = CMap2::EDGE; + static const Orbit FACE = CMap2::FACE; + static const Orbit VOLUME = CMap2::VOLUME; + typedef CMap2::Vertex Vertex; + typedef CMap2::Edge Edge; + typedef CMap2::Face Face; + typedef CMap2::Volume Volume; public: @@ -65,22 +67,37 @@ class MRCMap2_T * Orbits traversal *******************************************************************************/ + inline Dart phi1(Dart d) + { + return this->current()->phi1(d); + } + + inline Dart phi_1(Dart d) + { + return this->current()->phi_1(d); + } + + inline Dart phi2(Dart d) + { + return this->current()->phi2(d); + } + template inline void foreach_dart_of_vertex(Dart d, const FUNC& f) const { - mrmap2.current()->foreach_dart_of_vertex(d, f); + this->current()->foreach_dart_of_vertex(d, f); } template inline void foreach_dart_of_face(Dart d, const FUNC& f) const { - mrmap2.current()->foreach_dart_of_face(d, f); + this->current()->foreach_dart_of_face(d, f); } template void foreach_dart_of_volume(Dart d, const FUNC& f) const { - mrmap2.current()->foreach_dart_of_volume(d, f); + this->current()->foreach_dart_of_volume(d, f); } public: @@ -102,6 +119,15 @@ class MRCMap2_T } }; +template +struct MRCMap2Type +{ + typedef MRCMap2_T> TYPE; +}; + +template +using MRCMap2 = MRCMap2_T>; + } // namespace cgogn #endif // MULTIRESOLUTION_MRCMAP_MRCMAP2_H_ diff --git a/cgogn/multiresolution/mrcmap/mrcmap2_regular.h b/cgogn/multiresolution/mrcmap/mrcmap2_regular.h new file mode 100644 index 00000000..42b0534e --- /dev/null +++ b/cgogn/multiresolution/mrcmap/mrcmap2_regular.h @@ -0,0 +1,156 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef MULTIRESOLUTION_MRCMAP_MRCMAP2_REGULAR_H_ +#define MULTIRESOLUTION_MRCMAP_MRCMAP2_REGULAR_H_ + + +#include + +namespace cgogn +{ + +template +class MRCMap2Regular : public MRCMap2_T +{ +public: + + typedef MRCMap2 Inherit; + typedef MRCMap2Regular Self; + + + MRCMap2Regular() : Inherit() + {} + + MRCMap2Regular(const Self&) = delete; + MRCMap2Regular(Self&&) = delete; + Self& operator=(const Self&) = delete; + Self& operator=(Self&&) = delete; + inline ~MRCMap2Regular() = default; + +protected: + inline Vertex cut_edge(Edge e) + { + Inherit::current()->cut_edge(e); + } + + inline void split_face(Vertex d, Vertex e) + { + Inherit::current()->split_face(d, e); + } + +public: + + inline void add_triangular_level() + { + Inherit::push_level(); + + Inherit::add_level_back(); + + Inherit::set_current_level(Inherit::get_maximum_level()); + + Inherit::template foreach_cell([&] (typename Inherit::Edge e) + { + cut_edge(e); + + //skip the new edges + }); + + //cut faces + Inherit::template foreach_cell([&] (typename Inherit::Face d) + { + Dart old = d ; + + if(Inherit::get_dart_level(old) == Inherit::get_maximum_level()) + old = Inherit::phi1(old) ; + + Dart dd = Inherit::phi1(old) ; + Dart e = Inherit::phi1(Inherit::phi1(dd)) ; + // insert a new edge + split_face(dd, e) ; + + dd = e ; + e = Inherit::phi1(Inherit::phi1(dd)) ; + split_face(dd, e) ; + + dd = e ; + e = Inherit::phi1(Inherit::phi1(dd)) ; + split_face(dd, e) ; + + //skip the new faces + }); + + Inherit::pop_level(); + } + + inline void add_quadrangular_level() + { + Inherit::push_level(); + + Inherit::add_level_back(); + + Inherit::set_current_level(Inherit::get_maximum_level()); + + Inherit::template foreach_cell([&] (typename Inherit::Edge e) + { + cut_edge(e); + + //skip the new edges + }); + + //cut faces + Inherit::template foreach_cell([&] (typename Inherit::Face d) + { + Dart old = d ; + + if(Inherit::get_dart_level(old) == Inherit::get_maximum_level()) + old = Inherit::phi1(old) ; + + Dart dd = Inherit::phi1(old) ; + Dart next = Inherit::phi1(Inherit::phi1(dd)) ; + split_face(dd, next) ; // insert a first edge + + Dart ne = Inherit::phi2(Inherit::phi_1(dd)) ; + cut_edge(ne) ; // cut the new edge to insert the central vertex + + dd = Inherit::phi1(Inherit::phi1(next)) ; + while(dd != ne) // turn around the face and insert new edges + { // linked to the central vertex + Dart tmp = Inherit::phi1(ne) ; + split_face(tmp, dd) ; + dd = Inherit::phi1(Inherit::phi1(dd)) ; + } + }); + + Inherit::pop_level(); + } + + inline void add_mixed_level() + { + + } +}; + +} + +#endif // MULTIRESOLUTION_MRCMAP_MRCMAP2_REGULAR_H_ From 542daa164f7c813bef66ae2844272d0be1131d49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 10 Feb 2016 11:52:28 +0100 Subject: [PATCH 078/402] PHIXX -> ORBIT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/cmap2.h | 155 ++++++++++++++++++++-------------------- 1 file changed, 78 insertions(+), 77 deletions(-) diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 255cdd0d..0b84ab2b 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -177,7 +177,8 @@ class CMap2_T : public CMap1_T if (phi2(d) == d) { close_hole_topo(d); - Dart new_face = phi2(d); + const Dart new_face = phi2(d); + if (this->template is_orbit_embedded()) { foreach_dart_of_orbit(new_face, [this] (Dart fd) @@ -205,9 +206,10 @@ class CMap2_T : public CMap1_T } if (this->template is_orbit_embedded()) { - foreach_dart_of_orbit(new_face, [this,new_face] (Dart fd) + const unsigned int idx = this->template get_embedding(d); + foreach_dart_of_orbit(new_face, [this, idx] (Dart fd) { - this->template set_embedding(fd, this->template get_embedding(new_face)); + this->template set_embedding(fd, idx); }); } } @@ -236,116 +238,115 @@ class CMap2_T : public CMap1_T Face f(d); - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) { - this->foreach_dart_of_orbit(f, [this] (Cell df) + this->foreach_dart_of_orbit(f, [this] (Dart df) { - this->template set_orbit_embedding(df, this->template add_attribute_element()); + this->template set_embedding(df, this->template add_attribute_element()); }); } - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) { - foreach_incident_vertex(f, [this] (Cell c) + foreach_incident_vertex(f, [this] (Vertex v) { - this->set_orbit_embedding(c, this->template add_attribute_element()); + this->set_orbit_embedding(v, this->template add_attribute_element()); }); } - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) { - foreach_incident_edge(f, [this] (Cell c) + foreach_incident_edge(f, [this] (Edge e) { - this->set_orbit_embedding(c, this->template add_attribute_element()); + this->set_orbit_embedding(e, this->template add_attribute_element()); }); } - if (this->template is_orbit_embedded()) - this->set_orbit_embedding(f, this->template add_attribute_element()); + if (this->template is_orbit_embedded()) + this->set_orbit_embedding(f, this->template add_attribute_element()); - if (this->template is_orbit_embedded()) - this->template set_orbit_embedding(Volume(d), this->template add_attribute_element()); + if (this->template is_orbit_embedded()) + this->template set_orbit_embedding(Volume(d), this->template add_attribute_element()); return f; } inline Vertex cut_edge(Edge d) + { + const Dart e = phi2(d); + const Dart nd = cut_edge_topo(d); + const Dart ne = phi2(d); + const Vertex v(nd); + + if(this->template is_orbit_embedded()) { - Dart e = phi2(d); - Dart nd = cut_edge_topo(d); - Dart ne = phi2(nd); + this->template set_embedding(nd, this->template add_attribute_element()); + this->template set_embedding(ne, this->template add_attribute_element()); + } - Vertex v(nd); + if (this->template is_orbit_embedded()) + { + this->template set_orbit_embedding(v, this->template add_attribute_element()); + } - if(this->template is_orbit_embedded()) - { - this->template set_embedding(nd, this->template add_attribute_element()); - this->template set_embedding(ne, this->template add_attribute_element()); - } + if (this->template is_orbit_embedded()) + { + this->template set_embedding(ne, this->template get_embedding(d.dart)); + this->template set_orbit_embedding(Edge(nd), this->template add_attribute_element()); + } - if (this->template is_orbit_embedded()) - { - this->template set_orbit_embedding(v, this->template add_attribute_element()); - } + if (this->template is_orbit_embedded()) + { + this->template set_embedding(nd, this->template get_embedding(d.dart)); + this->template set_embedding(ne, this->template get_embedding(e)); + } - if (this->template is_orbit_embedded()) - { - this->template set_embedding(ne, this->template get_embedding(d.dart)); - this->template set_orbit_embedding(Edge(nd), this->template add_attribute_element()); - } + if (this->template is_orbit_embedded()) + { + this->template set_embedding(nd, this->template get_embedding(d.dart)); + this->template set_embedding(ne, this->template get_embedding(e)); + } - if (this->template is_orbit_embedded()) - { - this->template set_embedding(nd, this->template get_embedding(d.dart)); - this->template set_embedding(ne, this->template get_embedding(e)); - } + return v; + } - if (this->template is_orbit_embedded()) - { - this->template set_embedding(nd, this->template get_embedding(d.dart)); - this->template set_embedding(ne, this->template get_embedding(e)); - } + inline void split_face(Dart d, Dart e) + { + split_face_topo(d,e); + const Dart nd = this->phi_1(e); + const Dart ne = this->phi_1(d); - return v; + if(this->template is_orbit_embedded()) + { + this->template set_embedding(nd, this->template add_attribute_element()); + this->template set_embedding(ne, this->template add_attribute_element()); } - inline void split_face(Dart d, Dart e) + if (this->template is_orbit_embedded()) { - split_face_topo(d,e); - Dart nd = this->phi_1(e); - Dart ne = this->phi_1(d); - - if(this->template is_orbit_embedded()) - { - this->template set_embedding(nd, this->template add_attribute_element()); - this->template set_embedding(ne, this->template add_attribute_element()); - } - - if (this->template is_orbit_embedded()) - { - this->template set_embedding(nd, this->template get_embedding(d)); - this->template set_embedding(ne, this->template get_embedding(e)); - } + this->template set_embedding(nd, this->template get_embedding(d)); + this->template set_embedding(ne, this->template get_embedding(e)); + } - if (this->template is_orbit_embedded()) - { - this->template set_orbit_embedding(nd, this->template add_attribute_element()); - } + if (this->template is_orbit_embedded()) + { + this->template set_orbit_embedding(nd, this->template add_attribute_element()); + } - if (this->template is_orbit_embedded()) - { - this->template set_embedding(ne, this->template get_embedding(d)); - this->template set_orbit_embedding(e, this->template add_attribute_element()); - } + if (this->template is_orbit_embedded()) + { + this->template set_embedding(ne, this->template get_embedding(d)); + this->template set_orbit_embedding(e, this->template add_attribute_element()); + } - if (this->template is_orbit_embedded()) - { - this->template set_orbit_embedding(nd, this->template get_embedding(d)); - this->template set_orbit_embedding(ne, this->template get_embedding(d)); - } + if (this->template is_orbit_embedded()) + { + this->template set_orbit_embedding(nd, this->template get_embedding(d)); + this->template set_orbit_embedding(ne, this->template get_embedding(d)); } + } - inline unsigned int degree(Face f) const + inline unsigned int degree(Face f) const { return Inherit::degree(f); } @@ -357,7 +358,7 @@ class CMap2_T : public CMap1_T Dart e = phi2(d); // Get the adjacent 1D-edge phi2_unsew(d); // Unsew the initial 2D-edge, - // separating its two 1D-edges + // separating its two 1D-edges Dart nd = Inherit::cut_edge_topo(d); Dart ne = Inherit::cut_edge_topo(e); // Cut the two adjacent 1D-edges From c988d22c0ebc1a132e629de411e5987b1d9c52a5 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Wed, 10 Feb 2016 12:31:58 +0100 Subject: [PATCH 079/402] Cleaning ORBIT notations --- cgogn/core/cmap/cmap0.h | 20 +++- cgogn/core/cmap/cmap1.h | 13 ++- cgogn/core/cmap/cmap2.h | 205 ++++++++++++++++++++++------------------ cgogn/core/cmap/cmap3.h | 26 +++-- 4 files changed, 157 insertions(+), 107 deletions(-) diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index ed82ce0c..cb4a9fed 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -45,9 +45,16 @@ class CMap0_T : public MapBase friend typename Self::Inherit; friend class DartMarker_T; + static const Orbit DART = Orbit::DART; static const Orbit VERTEX = Orbit::DART; + static const Orbit EDGE = Orbit::DART; + static const Orbit FACE = Orbit::DART; + static const Orbit VOLUME = Orbit::DART; typedef Cell Vertex; + typedef Cell Edge; + typedef Cell Face; + typedef Cell Volume; template using ChunkArray = typename Inherit::template ChunkArray; @@ -91,9 +98,9 @@ class CMap0_T : public MapBase { Dart d = this->to_concrete()->add_dart(); - if (this->template is_orbit_embedded()) { - unsigned int idx = this->template add_attribute_element(); - this->template set_embedding(d, idx); + if (this->template is_orbit_embedded()) { + unsigned int idx = this->template add_attribute_element(); + this->template set_embedding(d, idx); } return Vertex(d); @@ -108,6 +115,11 @@ class CMap0_T : public MapBase template inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const { + static_assert(check_func_parameter_type(FUNC, Dart), + "Wrong function parameter type"); + + static_assert(ORBIT == Orbit::DART, + "Orbit not supported in a CMap1"); switch(ORBIT) { case Orbit::DART: f(c.dart); break; @@ -118,7 +130,7 @@ class CMap0_T : public MapBase case Orbit::PHI2_PHI3: case Orbit::PHI21: case Orbit::PHI21_PHI31: - default: cgogn_assert_not_reached("Cells of this dimension are not handled"); break; + default: cgogn_assert_not_reached("This orbit is not handled"); break; } } }; diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index c7fbfcac..342e5691 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -357,6 +357,9 @@ class CMap1_T : public MapBase template inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const { + static_assert(check_func_parameter_type(FUNC, Dart), + "Wrong function parameter type"); + static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1, "Orbit not supported in a CMap1"); @@ -370,7 +373,7 @@ class CMap1_T : public MapBase case Orbit::PHI2_PHI3: case Orbit::PHI21: case Orbit::PHI21_PHI31: - default: cgogn_assert_not_reached("Cells of this dimension are not handled"); break; + default: cgogn_assert_not_reached("This orbit is not handled"); break; } } @@ -389,9 +392,13 @@ class CMap1_T : public MapBase template inline void foreach_dart_of_orbit_until(Cell c, const FUNC& f) const { + static_assert(check_func_parameter_type(FUNC, Dart), + "Wrong function parameter type"); + static_assert(check_func_return_type(FUNC, bool), + "Wrong function return type"); + static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1, "Orbit not supported in a CMap1"); - static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); switch (ORBIT) { @@ -403,7 +410,7 @@ class CMap1_T : public MapBase case Orbit::PHI2_PHI3: case Orbit::PHI21: case Orbit::PHI21_PHI31: - default: cgogn_assert_not_reached("Cells of this dimension are not handled"); break; + default: cgogn_assert_not_reached("This orbit is not handled"); break; } } diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 255cdd0d..1d38622d 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -205,9 +205,10 @@ class CMap2_T : public CMap1_T } if (this->template is_orbit_embedded()) { - foreach_dart_of_orbit(new_face, [this,new_face] (Dart fd) + unsigned int idx = this->template get_embedding(new_face); + foreach_dart_of_orbit(new_face, [this,idx] (Dart fd) { - this->template set_embedding(fd, this->template get_embedding(new_face)); + this->template set_embedding(fd, idx); }); } } @@ -236,116 +237,115 @@ class CMap2_T : public CMap1_T Face f(d); - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) { - this->foreach_dart_of_orbit(f, [this] (Cell df) + foreach_dart_of_orbit(f, [this] (Dart df) { - this->template set_orbit_embedding(df, this->template add_attribute_element()); + this->template set_orbit_embedding(df, this->template add_attribute_element()); }); } - - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) { - foreach_incident_vertex(f, [this] (Cell c) + foreach_incident_vertex(f, [this] (Cell c) { - this->set_orbit_embedding(c, this->template add_attribute_element()); + this->template set_orbit_embedding(c, this->template add_attribute_element()); }); } - - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) { - foreach_incident_edge(f, [this] (Cell c) + foreach_incident_edge(f, [this] (Cell c) { - this->set_orbit_embedding(c, this->template add_attribute_element()); + this->template set_orbit_embedding(c, this->template add_attribute_element()); }); } - - if (this->template is_orbit_embedded()) - this->set_orbit_embedding(f, this->template add_attribute_element()); - - if (this->template is_orbit_embedded()) - this->template set_orbit_embedding(Volume(d), this->template add_attribute_element()); - + if (this->template is_orbit_embedded()) { + this->template set_orbit_embedding(f, this->template add_attribute_element()); + } + if (this->template is_orbit_embedded()) { + this->template set_orbit_embedding(Volume(d), this->template add_attribute_element()); + } return f; } inline Vertex cut_edge(Edge d) + { + Dart e = phi2(d); + Dart nd = cut_edge_topo(d); + Dart ne = phi2(d); + + Vertex v(nd); + + if(this->template is_orbit_embedded()) { - Dart e = phi2(d); - Dart nd = cut_edge_topo(d); - Dart ne = phi2(nd); + this->template set_embedding(nd, this->template add_attribute_element()); + this->template set_embedding(ne, this->template add_attribute_element()); + } - Vertex v(nd); + if (this->template is_orbit_embedded()) + { + this->template set_orbit_embedding(v, this->template add_attribute_element()); + } - if(this->template is_orbit_embedded()) - { - this->template set_embedding(nd, this->template add_attribute_element()); - this->template set_embedding(ne, this->template add_attribute_element()); - } + if (this->template is_orbit_embedded()) + { + this->template set_embedding(ne, this->template get_embedding(d.dart)); + this->template set_orbit_embedding(Edge(nd), this->template add_attribute_element()); + } - if (this->template is_orbit_embedded()) - { - this->template set_orbit_embedding(v, this->template add_attribute_element()); - } + if (this->template is_orbit_embedded()) + { + this->template set_embedding(nd, this->template get_embedding(d.dart)); + this->template set_embedding(ne, this->template get_embedding(e)); + } - if (this->template is_orbit_embedded()) - { - this->template set_embedding(ne, this->template get_embedding(d.dart)); - this->template set_orbit_embedding(Edge(nd), this->template add_attribute_element()); - } + if (this->template is_orbit_embedded()) + { + unsigned int idx = this->template get_embedding(d.dart); + this->template set_embedding(nd, idx); + this->template set_embedding(ne, idx); + } - if (this->template is_orbit_embedded()) - { - this->template set_embedding(nd, this->template get_embedding(d.dart)); - this->template set_embedding(ne, this->template get_embedding(e)); - } + return v; + } - if (this->template is_orbit_embedded()) - { - this->template set_embedding(nd, this->template get_embedding(d.dart)); - this->template set_embedding(ne, this->template get_embedding(e)); - } + inline void split_face(Dart d, Dart e) + { + split_face_topo(d,e); + Dart nd = this->phi_1(e); + Dart ne = this->phi_1(d); - return v; + if(this->template is_orbit_embedded()) + { + this->template set_embedding(nd, this->template add_attribute_element()); + this->template set_embedding(ne, this->template add_attribute_element()); } - inline void split_face(Dart d, Dart e) + if (this->template is_orbit_embedded()) { - split_face_topo(d,e); - Dart nd = this->phi_1(e); - Dart ne = this->phi_1(d); - - if(this->template is_orbit_embedded()) - { - this->template set_embedding(nd, this->template add_attribute_element()); - this->template set_embedding(ne, this->template add_attribute_element()); - } - - if (this->template is_orbit_embedded()) - { - this->template set_embedding(nd, this->template get_embedding(d)); - this->template set_embedding(ne, this->template get_embedding(e)); - } + this->template set_embedding(nd, this->template get_embedding(d)); + this->template set_embedding(ne, this->template get_embedding(e)); + } - if (this->template is_orbit_embedded()) - { - this->template set_orbit_embedding(nd, this->template add_attribute_element()); - } + if (this->template is_orbit_embedded()) + { + this->template set_orbit_embedding(nd, this->template add_attribute_element()); + } - if (this->template is_orbit_embedded()) - { - this->template set_embedding(ne, this->template get_embedding(d)); - this->template set_orbit_embedding(e, this->template add_attribute_element()); - } + if (this->template is_orbit_embedded()) + { + this->template set_embedding(ne, this->template get_embedding(d)); + this->template set_orbit_embedding(e, this->template add_attribute_element()); + } - if (this->template is_orbit_embedded()) - { - this->template set_orbit_embedding(nd, this->template get_embedding(d)); - this->template set_orbit_embedding(ne, this->template get_embedding(d)); - } + if (this->template is_orbit_embedded()) + { + unsigned int idx = this->template get_embedding(d); + this->template set_orbit_embedding(nd, idx); + this->template set_orbit_embedding(ne, idx); } + } - inline unsigned int degree(Face f) const + inline unsigned int degree(Face f) const { return Inherit::degree(f); } @@ -357,7 +357,7 @@ class CMap2_T : public CMap1_T Dart e = phi2(d); // Get the adjacent 1D-edge phi2_unsew(d); // Unsew the initial 2D-edge, - // separating its two 1D-edges + // separating its two 1D-edges Dart nd = Inherit::cut_edge_topo(d); Dart ne = Inherit::cut_edge_topo(e); // Cut the two adjacent 1D-edges @@ -461,21 +461,32 @@ class CMap2_T : public CMap1_T template inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const { - static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || - ORBIT == Orbit::PHI2 || ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21, - "Orbit not supported in a CMap2"); +// static_assert(check_func_parameter_type(FUNC, Dart), +// "Wrong function parameter type"); + + static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || ORBIT == Orbit::PHI2 || + ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21, + "Orbit not supported in a CMap1"); +// static_assert(ORBIT == DART || ORBIT == VERTEX || ORBIT == EDGE || +// ORBIT == FACE || ORBIT == VOLUME, +// "Orbit not supported in a CMap1"); switch (ORBIT) { +// case DART: this->foreach_dart_of_DART(c, f); break; +// case VERTEX: foreach_dart_of_PHI21(c, f); break; +// case EDGE: foreach_dart_of_PHI2(c, f); break; +// case FACE: this->foreach_dart_of_PHI1(c, f); break; +// case VOLUME: foreach_dart_of_PHI1_PHI2(c, f); break; case Orbit::DART: this->foreach_dart_of_DART(c, f); break; case Orbit::PHI1: this->foreach_dart_of_PHI1(c, f); break; case Orbit::PHI2: foreach_dart_of_PHI2(c, f); break; case Orbit::PHI1_PHI2: foreach_dart_of_PHI1_PHI2(c, f); break; case Orbit::PHI21: foreach_dart_of_PHI21(c, f); break; - case Orbit::PHI2_PHI3: case Orbit::PHI1_PHI3: + case Orbit::PHI2_PHI3: case Orbit::PHI21_PHI31: - default: cgogn_assert_not_reached("Cells of this dimension are not handled"); break; + default: cgogn_assert_not_reached("This orbit is not handled"); break; } } @@ -536,13 +547,25 @@ class CMap2_T : public CMap1_T template inline void foreach_dart_of_orbit_until(Cell c, const FUNC& f) const { - static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || - ORBIT == Orbit::PHI2 || ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21, - "Orbit not supported in a CMap2"); - static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); + // static_assert(check_func_parameter_type(FUNC, Dart), + // "Wrong function parameter type"); + static_assert(check_func_return_type(FUNC, bool), + "Wrong function return type"); + + static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || ORBIT == Orbit::PHI2 || + ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21, + "Orbit not supported in a CMap1"); +// static_assert(ORBIT == DART || ORBIT == VERTEX || ORBIT == EDGE || +// ORBIT == FACE || ORBIT == VOLUME, +// "Orbit not supported in a CMap1"); switch (ORBIT) { +// case DART: this->foreach_dart_of_DART(c, f); break; +// case VERTEX: foreach_dart_of_PHI21_until(c, f); break; +// case EDGE: foreach_dart_of_PHI2_until(c, f); break; +// case FACE: this->foreach_dart_of_PHI1_until(c, f); break; +// case VOLUME: foreach_dart_of_PHI1_PHI2_until(c, f); break; case Orbit::DART: this->foreach_dart_of_DART(c, f); break; case Orbit::PHI1: this->foreach_dart_of_PHI1_until(c, f); break; case Orbit::PHI2: foreach_dart_of_PHI2_until(c, f); break; @@ -551,7 +574,7 @@ class CMap2_T : public CMap1_T case Orbit::PHI2_PHI3: case Orbit::PHI1_PHI3: case Orbit::PHI21_PHI31: - default: cgogn_assert_not_reached("Cells of this dimension are not handled"); break; + default: cgogn_assert_not_reached("This orbit is not handled"); break; } } diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index de09edce..a35e7d74 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -404,10 +404,14 @@ class CMap3_T : public CMap2_T template inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const { - static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || - ORBIT == Orbit::PHI2 || ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21 || + static_assert(check_func_parameter_type(FUNC, Dart), + "Wrong function parameter type"); + + static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || ORBIT == Orbit::PHI2 || + ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21 || ORBIT == Orbit::PHI1_PHI3 || ORBIT == Orbit::PHI2_PHI3 || ORBIT == Orbit::PHI21_PHI31, - "Orbit not supported in a CMap3"); + "Orbit not supported in a CMap1"); + switch (ORBIT) { case Orbit::DART: this->foreach_dart_of_DART(c, f); break; @@ -418,7 +422,7 @@ class CMap3_T : public CMap2_T case Orbit::PHI2_PHI3: foreach_dart_of_PHI2_PHI3(c, f); break; case Orbit::PHI21: this->foreach_dart_of_PHI21(c, f); break; case Orbit::PHI21_PHI31: foreach_dart_of_PHI21_PHI31(c, f); break; - default: cgogn_assert_not_reached("Cells of this dimension are not handled"); break; + default: cgogn_assert_not_reached("This orbit is not handled"); break; } } @@ -485,11 +489,15 @@ class CMap3_T : public CMap2_T template inline void foreach_dart_of_orbit_until(Cell c, const FUNC& f) const { - static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || - ORBIT == Orbit::PHI2 || ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21 || + static_assert(check_func_parameter_type(FUNC, Dart), + "Wrong function parameter type"); + static_assert(check_func_return_type(FUNC, bool), + "Wrong function return type"); + + static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || ORBIT == Orbit::PHI2 || + ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21 || ORBIT == Orbit::PHI1_PHI3 || ORBIT == Orbit::PHI2_PHI3 || ORBIT == Orbit::PHI21_PHI31, - "Orbit not supported in a CMap3"); - static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); + "Orbit not supported in a CMap1"); switch (ORBIT) { @@ -501,7 +509,7 @@ class CMap3_T : public CMap2_T case Orbit::PHI2_PHI3: foreach_dart_of_PHI2_PHI3_until(c, f); break; case Orbit::PHI21: this->foreach_dart_of_PHI21_until(c, f); break; case Orbit::PHI21_PHI31: foreach_dart_of_PHI21_PHI31_until(c, f); break; - default: cgogn_assert_not_reached("Cells of this dimension are not handled"); break; + default: cgogn_assert_not_reached("This orbit is not handled"); break; } } From 7b8c1dbb5401aea440d7020a0a7c334294fa27d5 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Wed, 10 Feb 2016 12:45:25 +0100 Subject: [PATCH 080/402] Cleaning ORBIT notations in CMap1 --- cgogn/core/cmap/cmap1.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 342e5691..abdeac7a 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -46,6 +46,7 @@ class CMap1_T : public MapBase friend typename Self::Inherit; friend class DartMarker_T; + static const Orbit DART = Orbit::DART; static const Orbit VERTEX = Orbit::DART; static const Orbit EDGE = Orbit::DART; static const Orbit FACE = Orbit::PHI1; @@ -309,17 +310,17 @@ class CMap1_T : public MapBase Dart d = add_face_topo(nb_edges); Face f(d); - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) { - foreach_dart_of_PHI1(d, [this] (Dart e) + foreach_dart_of_orbit(d, [this] (Dart e) { - unsigned int idx = this->template add_attribute_element(); - this->template set_embedding(e, idx); + unsigned int idx = this->template add_attribute_element(); + this->template set_embedding(e, idx); }); } - if (this->template is_orbit_embedded()) { - unsigned int idx = this->template add_attribute_element(); + if (this->template is_orbit_embedded()) { + unsigned int idx = this->template add_attribute_element(); this->template set_orbit_embedding(f, idx); } From c13ef2f9967bf6a5457f08e99ddc07ea0c9167b5 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Wed, 10 Feb 2016 13:56:07 +0100 Subject: [PATCH 081/402] Remove unused comments --- cgogn/core/cmap/cmap2.h | 25 ++----------------------- cgogn/core/cmap/map_base.h | 4 +++- 2 files changed, 5 insertions(+), 24 deletions(-) diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 1d38622d..906b26b4 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -289,7 +289,7 @@ class CMap2_T : public CMap1_T if (this->template is_orbit_embedded()) { this->template set_embedding(ne, this->template get_embedding(d.dart)); - this->template set_orbit_embedding(Edge(nd), this->template add_attribute_element()); + this->template set_orbit_embedding(nd, this->template add_attribute_element()); } if (this->template is_orbit_embedded()) @@ -461,23 +461,12 @@ class CMap2_T : public CMap1_T template inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const { -// static_assert(check_func_parameter_type(FUNC, Dart), -// "Wrong function parameter type"); - static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || ORBIT == Orbit::PHI2 || ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21, "Orbit not supported in a CMap1"); -// static_assert(ORBIT == DART || ORBIT == VERTEX || ORBIT == EDGE || -// ORBIT == FACE || ORBIT == VOLUME, -// "Orbit not supported in a CMap1"); switch (ORBIT) { -// case DART: this->foreach_dart_of_DART(c, f); break; -// case VERTEX: foreach_dart_of_PHI21(c, f); break; -// case EDGE: foreach_dart_of_PHI2(c, f); break; -// case FACE: this->foreach_dart_of_PHI1(c, f); break; -// case VOLUME: foreach_dart_of_PHI1_PHI2(c, f); break; case Orbit::DART: this->foreach_dart_of_DART(c, f); break; case Orbit::PHI1: this->foreach_dart_of_PHI1(c, f); break; case Orbit::PHI2: foreach_dart_of_PHI2(c, f); break; @@ -547,25 +536,15 @@ class CMap2_T : public CMap1_T template inline void foreach_dart_of_orbit_until(Cell c, const FUNC& f) const { - // static_assert(check_func_parameter_type(FUNC, Dart), - // "Wrong function parameter type"); static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || ORBIT == Orbit::PHI2 || ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21, "Orbit not supported in a CMap1"); -// static_assert(ORBIT == DART || ORBIT == VERTEX || ORBIT == EDGE || -// ORBIT == FACE || ORBIT == VOLUME, -// "Orbit not supported in a CMap1"); switch (ORBIT) { -// case DART: this->foreach_dart_of_DART(c, f); break; -// case VERTEX: foreach_dart_of_PHI21_until(c, f); break; -// case EDGE: foreach_dart_of_PHI2_until(c, f); break; -// case FACE: this->foreach_dart_of_PHI1_until(c, f); break; -// case VOLUME: foreach_dart_of_PHI1_PHI2_until(c, f); break; case Orbit::DART: this->foreach_dart_of_DART(c, f); break; case Orbit::PHI1: this->foreach_dart_of_PHI1_until(c, f); break; case Orbit::PHI2: foreach_dart_of_PHI2_until(c, f); break; @@ -581,7 +560,7 @@ class CMap2_T : public CMap1_T public: /******************************************************************************* - * Incidence traversal + * Incidence traversalset_embeddind *******************************************************************************/ template diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 6e17c6ce..b8c2103f 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -340,7 +340,9 @@ class MapBase : public MapBaseData inline void set_orbit_embedding(Cell c, unsigned int emb) { ConcreteMap* cmap = to_concrete(); - cmap->foreach_dart_of_orbit(c, [cmap, emb] (Dart d) { cmap->template set_embedding(d, emb); }); + cmap->foreach_dart_of_orbit(c, [cmap, emb] (Dart d) { + cmap->template set_embedding(d, emb); + }); } public: From f8317dde612930a7876c7e1a147c3e61ed029036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 10 Feb 2016 14:35:53 +0100 Subject: [PATCH 082/402] cleaning core/tests/main.cpp and fixing some remaining typos. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/cmap0.h | 14 +++++------- cgogn/core/cmap/cmap1.h | 10 ++++----- cgogn/core/cmap/cmap2.h | 10 +++++---- cgogn/core/tests/main.cpp | 47 +-------------------------------------- 4 files changed, 18 insertions(+), 63 deletions(-) diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index ed82ce0c..12be4d3d 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -81,21 +81,19 @@ class CMap0_T : public MapBase protected: inline Dart add_dart() { - cgogn_assert(typeid(*this).hash_code() == typeid(Self).hash_code()); - unsigned int di = this->add_topology_element(); - return Dart(di); + CGOGN_CHECK_CONCRETE_TYPE; + return Dart(this->add_topology_element()); } public: Vertex add_vertex() { - Dart d = this->to_concrete()->add_dart(); + const Dart d = this->to_concrete()->add_dart(); - if (this->template is_orbit_embedded()) { - unsigned int idx = this->template add_attribute_element(); - this->template set_embedding(d, idx); + if (this->template is_orbit_embedded()) { + unsigned int idx = this->template add_attribute_element(); + this->template set_embedding(d, idx); } - return Vertex(d); } diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index c7fbfcac..3b43aad0 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -309,17 +309,17 @@ class CMap1_T : public MapBase Dart d = add_face_topo(nb_edges); Face f(d); - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) { foreach_dart_of_PHI1(d, [this] (Dart e) { - unsigned int idx = this->template add_attribute_element(); - this->template set_embedding(e, idx); + unsigned int idx = this->template add_attribute_element(); + this->template set_embedding(e, idx); }); } - if (this->template is_orbit_embedded()) { - unsigned int idx = this->template add_attribute_element(); + if (this->template is_orbit_embedded()) { + unsigned int idx = this->template add_attribute_element(); this->template set_orbit_embedding(f, idx); } diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 0b84ab2b..1015a5f9 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -303,8 +303,9 @@ class CMap2_T : public CMap1_T if (this->template is_orbit_embedded()) { - this->template set_embedding(nd, this->template get_embedding(d.dart)); - this->template set_embedding(ne, this->template get_embedding(e)); + const unsigned int idx = this->template get_embedding(d.dart); + this->template set_embedding(nd, idx); + this->template set_embedding(ne, idx); } return v; @@ -341,8 +342,9 @@ class CMap2_T : public CMap1_T if (this->template is_orbit_embedded()) { - this->template set_orbit_embedding(nd, this->template get_embedding(d)); - this->template set_orbit_embedding(ne, this->template get_embedding(d)); + const unsigned int idx = this->template get_embedding(d); + this->template set_orbit_embedding(nd, idx); + this->template set_orbit_embedding(ne, idx); } } diff --git a/cgogn/core/tests/main.cpp b/cgogn/core/tests/main.cpp index e8143d56..4f2383f9 100644 --- a/cgogn/core/tests/main.cpp +++ b/cgogn/core/tests/main.cpp @@ -28,57 +28,12 @@ // using ::testing::AtLeast; - -class Carte { -public: - void begin() { - std::cout << "Carte() " << val << std::endl; - } - Carte(int v) { - val = v; - std::cout << "constructor Carte() " << val << std::endl; - } - Carte(const Carte& c) { - val = c.val; - std::cout << "constructor Carte() " << val << std::endl; - } - -protected: - int val; -}; - -class Browser1 : Carte { -public: - void begin() { - Carte::begin(); - std::cout << "Browser1()" << val << std::endl; - } - Browser1(const Carte& c) : Carte(c) { - } -}; - -class Browser2 : Carte { -public: - void begin() { - Carte::begin(); - std::cout << "Browser2()" << val << std::endl; - } - Browser2(const Carte& c) : Carte(c) { - } -}; - int main(int argc, char **argv) { - Carte carte(3); - - carte.begin(); - static_cast(carte).begin(); - static_cast(carte).begin(); - testing::InitGoogleTest(&argc, argv); // testing::InitGoogleMock(&argc, argv); // Set LC_CTYPE according to the environnement variable. setlocale(LC_CTYPE, ""); - return 0; //RUN_ALL_TESTS(); + return RUN_ALL_TESTS(); } From 05caa21f467c1762803e2459b37a3d7a5bcad46f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 10 Feb 2016 14:52:15 +0100 Subject: [PATCH 083/402] better style. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/cmap0.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index 0e9cd050..56b4369a 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -95,13 +95,12 @@ class CMap0_T : public MapBase public: Vertex add_vertex() { - const Dart d = this->to_concrete()->add_dart(); + const Vertex v(this->to_concrete()->add_dart()); - if (this->template is_orbit_embedded()) { - unsigned int idx = this->template add_attribute_element(); - this->template set_embedding(d, idx); - } - return Vertex(d); + if (this->template is_orbit_embedded()) + this->template set_embedding(v.dart, this->template add_attribute_element()); + + return v; } protected: From 06eafe3653e592c3ad4707613a0fc06568ecb474 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Wed, 10 Feb 2016 14:12:33 +0100 Subject: [PATCH 084/402] fixing compilation with MSVC. Signed-off-by: Etienne Schmitt --- cgogn/core/cmap/cmap1.h | 14 +++++--------- cgogn/core/cmap/cmap2.h | 6 +++--- cgogn/multiresolution/cph/ihcmap2_regular.h | 4 ++++ cgogn/multiresolution/examples/cph/cph2.cpp | 6 +++--- cgogn/multiresolution/mra/lerp_triquad_mra.h | 6 +++--- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index a5a379ab..44730aa5 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -307,22 +307,18 @@ class CMap1_T : public MapBase { cgogn_message_assert(nb_edges > 0, "Cannot create a face with no edge"); - Dart d = add_face_topo(nb_edges); - Face f(d); + const Face f(this->add_face_topo(nb_edges)); if (this->template is_orbit_embedded()) { - foreach_dart_of_orbit(d, [this] (Dart e) + foreach_dart_of_orbit(f, [this](Dart d) { - unsigned int idx = this->template add_attribute_element(); - this->template set_embedding(e, idx); + this->template set_orbit_embedding(d, this->template add_attribute_element()); }); } - if (this->template is_orbit_embedded()) { - unsigned int idx = this->template add_attribute_element(); - this->template set_orbit_embedding(f, idx); - } + if (this->template is_orbit_embedded()) + this->set_orbit_embedding(f, this->template add_attribute_element()); return f; } diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index fd9adf11..dfdca391 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -266,7 +266,7 @@ class CMap2_T : public CMap1_T this->set_orbit_embedding(f, this->template add_attribute_element()); if (this->template is_orbit_embedded()) - this->template set_orbit_embedding(Volume(d), this->template add_attribute_element()); + this->set_orbit_embedding(Volume(d), this->template add_attribute_element()); return f; } @@ -286,13 +286,13 @@ class CMap2_T : public CMap1_T if (this->template is_orbit_embedded()) { - this->template set_orbit_embedding(v, this->template add_attribute_element()); + this->set_orbit_embedding(v, this->template add_attribute_element()); } if (this->template is_orbit_embedded()) { this->template set_embedding(ne, this->template get_embedding(d.dart)); - this->template set_orbit_embedding(Edge(nd), this->template add_attribute_element()); + this->set_orbit_embedding(Edge(nd), this->template add_attribute_element()); } if (this->template is_orbit_embedded()) diff --git a/cgogn/multiresolution/cph/ihcmap2_regular.h b/cgogn/multiresolution/cph/ihcmap2_regular.h index 290589d0..5499da4c 100644 --- a/cgogn/multiresolution/cph/ihcmap2_regular.h +++ b/cgogn/multiresolution/cph/ihcmap2_regular.h @@ -37,6 +37,10 @@ class IHCMap2Regular : public IHCMap2 typedef IHCMap2 Inherit; typedef IHCMap2Regular Self; + using Vertex = typename Inherit::Vertex; + using Edge = typename Inherit::Edge; + using Face = typename Inherit::Face; + using Volume = typename Inherit::Volume; IHCMap2Regular() : Inherit() {} diff --git a/cgogn/multiresolution/examples/cph/cph2.cpp b/cgogn/multiresolution/examples/cph/cph2.cpp index 83195d93..df4ea084 100644 --- a/cgogn/multiresolution/examples/cph/cph2.cpp +++ b/cgogn/multiresolution/examples/cph/cph2.cpp @@ -26,7 +26,7 @@ int main() map.add_face(4); std::cout << "before add level Faces :" << std::endl; - map.template foreach_cell([&] (typename IHMap2::Face v) + map.template foreach_cell([&] (IHMap2::Face v) { std::cout << v << std::endl; }); @@ -38,7 +38,7 @@ int main() lerp.synthesis(); std::cout << "after add level Faces :" << std::endl; - map.template foreach_cell([&] (typename IHMap2::Face f) + map.template foreach_cell([&] (IHMap2::Face f) { std::cout << f << " | " << map.get_dart_level(f.dart) << std::endl; }); @@ -51,7 +51,7 @@ int main() map.set_current_level(cur - 1); std::cout << "after add level Faces :" << std::endl; - map.template foreach_cell([&] (typename IHMap2::Face f) + map.template foreach_cell([&] (IHMap2::Face f) { std::cout << f << " | " << map.get_dart_level(f.dart) << std::endl; }); diff --git a/cgogn/multiresolution/mra/lerp_triquad_mra.h b/cgogn/multiresolution/mra/lerp_triquad_mra.h index c461896f..1aa7f166 100644 --- a/cgogn/multiresolution/mra/lerp_triquad_mra.h +++ b/cgogn/multiresolution/mra/lerp_triquad_mra.h @@ -62,7 +62,7 @@ class LerpTriQuadMRAnalysis : public MRAnalysis std::function lerp_tri_quad_odd_synthesis_ = [this] () { - this->map_.template foreach_cell([&] (typename MRMAP::Face f) + this->map_.template foreach_cell([&] (MRMAP::Face f) { if(this->map_.degree(f) != 3) { @@ -71,7 +71,7 @@ class LerpTriQuadMRAnalysis : public MRAnalysis unsigned int count = 0; - this->map_.template foreach_incident_edge(f, [&] (typename MRMAP::Edge e) + this->map_.foreach_incident_edge(f, [&] (MRMAP::Edge e) { vf += va_[e.dart]; this->map_.inc_current_level(); @@ -92,7 +92,7 @@ class LerpTriQuadMRAnalysis : public MRAnalysis } }); - this->map_.template foreach_cell([&] (typename MRMAP::Edge e) + this->map_.template foreach_cell([&] (MRMAP::Edge e) { VEC3 ve = (va_[e.dart] + va_[this->map_.phi1(e)]) * 0.5; From f26b018e62b452718786702bc88a8befd1ded32f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 10 Feb 2016 15:22:26 +0100 Subject: [PATCH 085/402] typos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/cmap3.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index a35e7d74..a9d0fe04 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -410,7 +410,7 @@ class CMap3_T : public CMap2_T static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || ORBIT == Orbit::PHI2 || ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21 || ORBIT == Orbit::PHI1_PHI3 || ORBIT == Orbit::PHI2_PHI3 || ORBIT == Orbit::PHI21_PHI31, - "Orbit not supported in a CMap1"); + "Orbit not supported in a CMap3"); switch (ORBIT) { @@ -489,15 +489,13 @@ class CMap3_T : public CMap2_T template inline void foreach_dart_of_orbit_until(Cell c, const FUNC& f) const { - static_assert(check_func_parameter_type(FUNC, Dart), - "Wrong function parameter type"); static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || ORBIT == Orbit::PHI2 || ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21 || ORBIT == Orbit::PHI1_PHI3 || ORBIT == Orbit::PHI2_PHI3 || ORBIT == Orbit::PHI21_PHI31, - "Orbit not supported in a CMap1"); + "Orbit not supported in a CMap3"); switch (ORBIT) { From 01b0ed7ce0e074c3a9f2c89d0440a6f00af969db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 10 Feb 2016 15:24:15 +0100 Subject: [PATCH 086/402] same_cell first cheking if the orbit is embedded. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/map_base.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index b8c2103f..7e7a3043 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -453,6 +453,9 @@ class MapBase : public MapBaseData template bool same_cell(Cell c1, Cell c2) const { + if (this->template is_orbit_embedded()) + return this->get_embedding(c1) == this->get_embedding(c2); + const ConcreteMap* cmap = to_concrete(); bool result = false; cmap->template foreach_dart_of_orbit_until(c1, [&] (Dart d) -> bool From 692afdc89da8065bd42171067880d6632c97226a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 10 Feb 2016 17:00:45 +0100 Subject: [PATCH 087/402] extern templates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/multiresolution/CMakeLists.txt | 37 +- .../cph/{ihcmap_base.cpp => cph2.cpp} | 7 +- cgogn/multiresolution/cph/cph2.h | 5 +- cgogn/multiresolution/cph/cph3.cpp | 34 + cgogn/multiresolution/cph/cph3.h | 14 +- cgogn/multiresolution/cph/cph_base.cpp | 33 + cgogn/multiresolution/cph/cph_base.h | 16 +- cgogn/multiresolution/cph/ihcmap2.cpp | 34 + cgogn/multiresolution/cph/ihcmap2.h | 9 +- .../multiresolution/cph/ihcmap2_adaptive.cpp | 34 + cgogn/multiresolution/cph/ihcmap2_adaptive.h | 25 +- cgogn/multiresolution/cph/ihcmap2_regular.cpp | 34 + cgogn/multiresolution/cph/ihcmap2_regular.h | 4 + cgogn/multiresolution/cph/ihcmap3.cpp | 34 + cgogn/multiresolution/cph/ihcmap3.h | 682 +++++++++--------- cgogn/multiresolution/mra/lerp_triquad_mra.h | 62 +- cgogn/multiresolution/mra/mr_analysis.h | 40 +- 17 files changed, 677 insertions(+), 427 deletions(-) rename cgogn/multiresolution/cph/{ihcmap_base.cpp => cph2.cpp} (91%) create mode 100644 cgogn/multiresolution/cph/cph3.cpp create mode 100644 cgogn/multiresolution/cph/cph_base.cpp create mode 100644 cgogn/multiresolution/cph/ihcmap2.cpp create mode 100644 cgogn/multiresolution/cph/ihcmap2_adaptive.cpp create mode 100644 cgogn/multiresolution/cph/ihcmap2_regular.cpp create mode 100644 cgogn/multiresolution/cph/ihcmap3.cpp diff --git a/cgogn/multiresolution/CMakeLists.txt b/cgogn/multiresolution/CMakeLists.txt index 398742b7..ec3c821f 100644 --- a/cgogn/multiresolution/CMakeLists.txt +++ b/cgogn/multiresolution/CMakeLists.txt @@ -3,26 +3,33 @@ project(cgogn_multiresolution ) set(HEADER_FILES - dll.h - - cph/attribute_handler_cph.h - cph/cph_base.h - cph/cph2.h - cph/cph3.h - cph/ihcmap2.h - cph/ihcmap2_adaptive.h - cph/ihcmap2_regular.h - cph/ihcmap3.h - - mrcmap/mr_base.h + dll.h + + cph/attribute_handler_cph.h + cph/cph_base.h + cph/cph2.h + cph/cph3.h + cph/ihcmap2.h + cph/ihcmap2_adaptive.h + cph/ihcmap2_regular.h + cph/ihcmap3.h + + mrcmap/mr_base.h mrcmap/mrcmap2.h - mra/mr_analysis.h - mra/lerp_triquad_mra.h + mra/mr_analysis.h + mra/lerp_triquad_mra.h ) set(SOURCE_FILES - cph/ihcmap_base.cpp + cph/cph_base.cpp + cph/cph2.cpp + cph/cph3.cpp + + cph/ihcmap2.cpp + cph/ihcmap2_adaptive.cpp + cph/ihcmap2_regular.cpp + cph/ihcmap3.cpp ) add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) diff --git a/cgogn/multiresolution/cph/ihcmap_base.cpp b/cgogn/multiresolution/cph/cph2.cpp similarity index 91% rename from cgogn/multiresolution/cph/ihcmap_base.cpp rename to cgogn/multiresolution/cph/cph2.cpp index 99fde37e..8b80c4e5 100644 --- a/cgogn/multiresolution/cph/ihcmap_base.cpp +++ b/cgogn/multiresolution/cph/cph2.cpp @@ -21,9 +21,14 @@ * * *******************************************************************************/ +#define CGOGN_CORE_DLL_EXPORT +#define MULTIRESOLUTION_CPH_CPH2_CPP_ + +#include + namespace cgogn { - +template class CGOGN_MULTIRESOLUTION_API CPH2; } // namespace cgogn diff --git a/cgogn/multiresolution/cph/cph2.h b/cgogn/multiresolution/cph/cph2.h index 81c4bce1..718aef17 100644 --- a/cgogn/multiresolution/cph/cph2.h +++ b/cgogn/multiresolution/cph/cph2.h @@ -119,7 +119,10 @@ class CPH2 : public CPHBase }; -} // namespace cgogn +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_CPH2_CPP_)) +extern template class CGOGN_MULTIRESOLUTION_API CPH2; +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_CPH2_CPP_)) +} // namespace cgogn #endif // MULTIRESOLUTION_CPH_CPH2_BASE_H_ diff --git a/cgogn/multiresolution/cph/cph3.cpp b/cgogn/multiresolution/cph/cph3.cpp new file mode 100644 index 00000000..fc7f676d --- /dev/null +++ b/cgogn/multiresolution/cph/cph3.cpp @@ -0,0 +1,34 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#define CGOGN_CORE_DLL_EXPORT +#define MULTIRESOLUTION_CPH_CPH3_CPP_ + +#include + +namespace cgogn +{ + +template class CGOGN_MULTIRESOLUTION_API CPH3; + +} // namespace cgogn diff --git a/cgogn/multiresolution/cph/cph3.h b/cgogn/multiresolution/cph/cph3.h index b179260f..c2d4dcdb 100644 --- a/cgogn/multiresolution/cph/cph3.h +++ b/cgogn/multiresolution/cph/cph3.h @@ -30,12 +30,16 @@ namespace cgogn { template -class CPH3 : CPH2 +class CPH3 : public CPH2 { public: - typedef CPH3 Self; - typedef CPH2 Inherit; + using Self = CPH3; + using Inherit = CPH2; + template + using ChunkArray = typename Inherit::template ChunkArray; + template + using ChunkArrayContainer = typename Inherit::template ChunkArrayContainer; protected: ChunkArray* face_id_; @@ -87,6 +91,10 @@ class CPH3 : CPH2 } }; +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_CPH3_CPP_)) +extern template class CGOGN_MULTIRESOLUTION_API CPH3; +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_CPH3_CPP_)) + } // namespace cgogn #endif // MULTIRESOLUTION_CPH_CPH3_BASE_H_ diff --git a/cgogn/multiresolution/cph/cph_base.cpp b/cgogn/multiresolution/cph/cph_base.cpp new file mode 100644 index 00000000..27e52159 --- /dev/null +++ b/cgogn/multiresolution/cph/cph_base.cpp @@ -0,0 +1,33 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ +#define MULTIRESOLUTION_CPH_CPH_BASE_CPP_ +#define CGOGN_MULTIRESOLUTION_DLL_EXPORT + +#include + +namespace cgogn +{ + +template class CGOGN_MULTIRESOLUTION_API CPHBase; + +} // namespace cgogn diff --git a/cgogn/multiresolution/cph/cph_base.h b/cgogn/multiresolution/cph/cph_base.h index b204fb30..5e55993a 100644 --- a/cgogn/multiresolution/cph/cph_base.h +++ b/cgogn/multiresolution/cph/cph_base.h @@ -24,8 +24,12 @@ #ifndef MULTIRESOLUTION_CPH_CPH_BASE_H_ #define MULTIRESOLUTION_CPH_CPH_BASE_H_ -#include #include +#include +#include +#include + +#include namespace cgogn { @@ -35,7 +39,7 @@ class CPHBase { public: - typedef CPHBase Self; + using Self = CPHBase; template using ChunkArray = cgogn::ChunkArray; @@ -137,6 +141,12 @@ class CPHBase } }; -} + +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_CPH_BASE_CPP_)) +extern template class CGOGN_MULTIRESOLUTION_API CPHBase; +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_CPH_BASE_CPP_)) + + +} // namespace cgogn #endif // MULTIRESOLUTION_CPH_CPH_BASE_H_ diff --git a/cgogn/multiresolution/cph/ihcmap2.cpp b/cgogn/multiresolution/cph/ihcmap2.cpp new file mode 100644 index 00000000..4cc80055 --- /dev/null +++ b/cgogn/multiresolution/cph/ihcmap2.cpp @@ -0,0 +1,34 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#define CGOGN_CORE_DLL_EXPORT +#define MULTIRESOLUTION_CPH_IHCMAP2_CPP_ + +#include + +namespace cgogn +{ + +template class CGOGN_MULTIRESOLUTION_API IHCMap2_T>; + +} // namespace cgogn diff --git a/cgogn/multiresolution/cph/ihcmap2.h b/cgogn/multiresolution/cph/ihcmap2.h index cbe7f8ba..3772836a 100644 --- a/cgogn/multiresolution/cph/ihcmap2.h +++ b/cgogn/multiresolution/cph/ihcmap2.h @@ -54,7 +54,7 @@ class ContainerCPHBrowser : public ContainerBrowser }; template -class IHCMap2_T : public CMap2_T, public CPH2 +class IHCMap2_T : virtual public CMap2_T, virtual public CPH2 { public: @@ -358,7 +358,6 @@ class IHCMap2_T : public CMap2_T, public CPH2 struct IHCMap2Type { @@ -368,6 +367,12 @@ struct IHCMap2Type template using IHCMap2 = IHCMap2_T>; +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_IHCMAP2_CPP_)) +extern template class CGOGN_MULTIRESOLUTION_API IHCMap2_T>; +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_IHCMAP2_CPP_)) + + + } // namespace cgogn #endif // MULTIRESOLUTION_CPH_IHCMAP2_H_ diff --git a/cgogn/multiresolution/cph/ihcmap2_adaptive.cpp b/cgogn/multiresolution/cph/ihcmap2_adaptive.cpp new file mode 100644 index 00000000..db25f0ed --- /dev/null +++ b/cgogn/multiresolution/cph/ihcmap2_adaptive.cpp @@ -0,0 +1,34 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#define CGOGN_CORE_DLL_EXPORT +#define MULTIRESOLUTION_CPH_IHCMAP2_ADAPTIVE_CPP_ + +#include + +namespace cgogn +{ + +template class CGOGN_MULTIRESOLUTION_API IHCMap2Adaptive; + +} // namespace cgogn diff --git a/cgogn/multiresolution/cph/ihcmap2_adaptive.h b/cgogn/multiresolution/cph/ihcmap2_adaptive.h index a561b229..650e790d 100644 --- a/cgogn/multiresolution/cph/ihcmap2_adaptive.h +++ b/cgogn/multiresolution/cph/ihcmap2_adaptive.h @@ -47,7 +47,6 @@ class IHCMap2Adaptive : IHCMap2 IHCMap2Adaptive(Self&&) = delete; Self& operator=(const Self&) = delete; Self& operator=(Self&&) = delete; - inline ~IHCMap2Adaptive() = default; public: /*************************************************** @@ -62,12 +61,9 @@ class IHCMap2Adaptive : IHCMap2 */ unsigned int edge_level(Dart d) { - cgogn_message_assert(Inherit::getDartLevel(d) <= Inherit::getCurrentLevel(), + cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), "Access to a dart introduced after current level"); - - unsigned int ld = Inherit::getDartLevel(d); - unsigned int ldd = Inherit::getDartLevel(Inherit::phi1(d)); - return ld < ldd ? ldd : ld; + return std::max(Inherit::get_dart_level(d),Inherit::get_dart_level(Inherit::phi1(d))); } /** @@ -290,7 +286,7 @@ class IHCMap2Adaptive : IHCMap2 unsigned int cur2 = Inherit::get_current_level(); Inherit::set_current_level(cur2 + 1); if(Inherit::get_dart_level(Inherit::phi1(fit)) == Inherit::get_current_level() - && Inherit::get_edge_id(m_map.phi1(fit)) != Inherit::get_edge_id(fit)) + && Inherit::get_edge_id(this->phi1(fit)) != Inherit::get_edge_id(fit)) subdOnce = false ; Inherit::set_current_level(cur2); } @@ -411,7 +407,7 @@ class IHCMap2Adaptive : IHCMap2 it = Inherit::phi1(it); } while(it != old); - Inherit::setCurrentLevel(fLevel + 1); // go to the next level to perform face subdivision + Inherit::set_current_level(fLevel + 1); // go to the next level to perform face subdivision if((degree == 3) && triQuad) // if subdividing a triangle { @@ -447,10 +443,10 @@ class IHCMap2Adaptive : IHCMap2 else // if subdividing a polygonal face { Dart dd = Inherit::phi1(old); - Dart next = m_map.phi1(dd); + Dart next = this->phi1(dd); // (*vertexVertexFunctor)(next); next = Inherit::phi1(next); - Inherit::splitFace(dd, next); // insert a first edge + Inherit::split_face(dd, next); // insert a first edge Dart ne = Inherit::phi2(Inherit::phi_1(dd)); Dart ne2 = Inherit::phi2(ne); Inherit::cut_edge(ne); // cut the new edge to insert the central vertex @@ -469,7 +465,7 @@ class IHCMap2Adaptive : IHCMap2 dd = Inherit::phi1(dd); while(dd != ne) // turn around the face and insert new edges { // linked to the central vertex - Inherit::splitFace(Inherit::phi1(ne), dd); + Inherit::split_face(Inherit::phi1(ne), dd); Dart nne = Inherit::phi2(Inherit::phi_1(dd)); id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(nne))); @@ -518,7 +514,7 @@ class IHCMap2Adaptive : IHCMap2 Inherit::set_current_level(Inherit::get_maximum_level()); Inherit::merge_faces(innerEdge); Inherit::set_current_level(cur); - fit = m_map.phi1(fit); + fit = this->phi1(fit); } while(fit != d); } else @@ -540,6 +536,11 @@ class IHCMap2Adaptive : IHCMap2 } }; +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_IHCMAP2_ADAPTIVE_CPP_)) +extern template class CGOGN_MULTIRESOLUTION_API IHCMap2Adaptive; +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_IHCMAP2_ADAPTIVE_CPP_)) + + } // namespace cgogn #endif // MULTIRESOLUTION_CPH_IHCMAP2_ADAPTIVE_H_ diff --git a/cgogn/multiresolution/cph/ihcmap2_regular.cpp b/cgogn/multiresolution/cph/ihcmap2_regular.cpp new file mode 100644 index 00000000..4ea87498 --- /dev/null +++ b/cgogn/multiresolution/cph/ihcmap2_regular.cpp @@ -0,0 +1,34 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#define CGOGN_CORE_DLL_EXPORT +#define MULTIRESOLUTION_CPH_IHCMAP2_REGULAR_CPP_ + +#include + +namespace cgogn +{ + +template class CGOGN_MULTIRESOLUTION_API IHCMap2Regular; + +} // namespace cgogn diff --git a/cgogn/multiresolution/cph/ihcmap2_regular.h b/cgogn/multiresolution/cph/ihcmap2_regular.h index 5499da4c..7d108be2 100644 --- a/cgogn/multiresolution/cph/ihcmap2_regular.h +++ b/cgogn/multiresolution/cph/ihcmap2_regular.h @@ -257,6 +257,10 @@ class IHCMap2Regular : public IHCMap2 } }; +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_IHCMAP2_REGULAR_CPP_)) +extern template class CGOGN_MULTIRESOLUTION_API IHCMap2Regular; +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_IHCMAP2_REGULAR_CPP_)) + } // namespace cgogn #endif // MULTIRESOLUTION_CPH_IHCMAP2_REGULAR_H_ diff --git a/cgogn/multiresolution/cph/ihcmap3.cpp b/cgogn/multiresolution/cph/ihcmap3.cpp new file mode 100644 index 00000000..a544aa88 --- /dev/null +++ b/cgogn/multiresolution/cph/ihcmap3.cpp @@ -0,0 +1,34 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#define CGOGN_CORE_DLL_EXPORT +#define MULTIRESOLUTION_CPH_IHCMAP3_CPP_ + +#include + +namespace cgogn +{ + +template class CGOGN_MULTIRESOLUTION_API IHCMap3_T>; + +} // namespace cgogn diff --git a/cgogn/multiresolution/cph/ihcmap3.h b/cgogn/multiresolution/cph/ihcmap3.h index 8f4e2c0c..10921c28 100644 --- a/cgogn/multiresolution/cph/ihcmap3.h +++ b/cgogn/multiresolution/cph/ihcmap3.h @@ -33,374 +33,378 @@ namespace cgogn template -class IHCMap3_T : public CMap3_T, public CPH3 +class IHCMap3_T :virtual public CMap3_T, virtual public CPH3 { public: - typedef CMap3_T Inherit_CMAP; - typedef CPH3 Inherit_CPH; - typedef IHCMap3_T Self; - - friend typename Self::Inherit_CMAP; - // friend typename Inherit::Inherit; - - friend class DartMarker_T; - - static const Orbit DART = Orbit::DART; - static const Orbit VERTEX = Orbit::PHI21; - static const Orbit EDGE = Orbit::PHI2; - static const Orbit FACE = Orbit::PHI1; - static const Orbit VOLUME = Orbit::PHI1_PHI2; - - typedef Cell Vertex; - typedef Cell Edge; - typedef Cell Face; - typedef Cell Volume; - - template - using ChunkArray = typename Inherit_CMAP::template ChunkArray; - template - using ChunkArrayContainer = typename Inherit_CMAP::template ChunkArrayContainer; - - template - using AttributeHandler = typename Inherit_CMAP::template AttributeHandler; - template - using DartAttributeHandler = AttributeHandler; - template - using VertexAttributeHandler = AttributeHandler; - template - using EdgeAttributeHandler = AttributeHandler; - template - using FaceAttributeHandler = AttributeHandler; - template - using VolumeAttributeHandler = AttributeHandler; - using DartMarker = typename cgogn::DartMarker; - using DartMarkerStore = typename cgogn::DartMarkerStore; - - ChunkArray* next_level_cell[NB_ORBITS]; - - template - class ContainerCPHBrowser : public ContainerBrowser - { - const CONTAINER& cac_; - const MAP* map_; - - public: - ContainerCPHBrowser(const CONTAINER& cac, const MAP* map) : cac_(cac), map_(map) {} - virtual unsigned int begin() const { return cac_.real_begin(); } - virtual unsigned int end() const { return cac_.real_end(); } - virtual void next(unsigned int &it) const - { - cac_.real_next(it); - if(map_->get_dart_level(Dart(it)) > map_->get_current_level()) - it = cac_.real_end(); - } - virtual void next_primitive(unsigned int &it, unsigned int primSz) const { cac_.real_next_primitive(it,primSz); } - virtual void enable() {} - virtual void disable() {} - virtual ~ContainerCPHBrowser() {} - }; + using Inherit_CMAP = CMap3_T; + using Inherit_CPH = CPH3; + using Self = IHCMap3_T; + + friend typename Self::Inherit_CMAP; + // friend typename Inherit::Inherit; + + friend class DartMarker_T; + + static const Orbit DART = Orbit::DART; + static const Orbit VERTEX = Orbit::PHI21; + static const Orbit EDGE = Orbit::PHI2; + static const Orbit FACE = Orbit::PHI1; + static const Orbit VOLUME = Orbit::PHI1_PHI2; + + using Vertex = Cell; + using Edge = Cell; + using Face = Cell; + using Volume = Cell; + + template + using ChunkArray = typename Inherit_CMAP::template ChunkArray; + template + using ChunkArrayContainer = typename Inherit_CMAP::template ChunkArrayContainer; + + template + using AttributeHandler = typename Inherit_CMAP::template AttributeHandler; + template + using DartAttributeHandler = AttributeHandler; + template + using VertexAttributeHandler = AttributeHandler; + template + using EdgeAttributeHandler = AttributeHandler; + template + using FaceAttributeHandler = AttributeHandler; + template + using VolumeAttributeHandler = AttributeHandler; + using DartMarker = typename cgogn::DartMarker; + using DartMarkerStore = typename cgogn::DartMarkerStore; + + ChunkArray* next_level_cell[NB_ORBITS]; + + template + class ContainerCPHBrowser : public ContainerBrowser + { + const CONTAINER& cac_; + const MAP* map_; + + public: + ContainerCPHBrowser(const CONTAINER& cac, const MAP* map) : cac_(cac), map_(map) {} + virtual unsigned int begin() const { return cac_.real_begin(); } + virtual unsigned int end() const { return cac_.real_end(); } + virtual void next(unsigned int &it) const + { + cac_.real_next(it); + if(map_->get_dart_level(Dart(it)) > map_->get_current_level()) + it = cac_.real_end(); + } + virtual void next_primitive(unsigned int &it, unsigned int primSz) const { cac_.real_next_primitive(it,primSz); } + virtual void enable() {} + virtual void disable() {} + virtual ~ContainerCPHBrowser() {} + }; protected: - ContainerCPHBrowser, Self>* cph_browser; + ContainerCPHBrowser, Self>* cph_browser; - inline void init() - { - cph_browser = new ContainerCPHBrowser, Self>(this->topology_, this); - this->topology_.set_current_browser(cph_browser); + inline void init() + { + cph_browser = new ContainerCPHBrowser, Self>(this->topology_, this); + this->topology_.set_current_browser(cph_browser); - // Inherit_CPH::new_level_darts(); - } + // Inherit_CPH::new_level_darts(); + } public: - IHCMap3_T() : Inherit_CMAP(), Inherit_CPH(this->topology_) - { - init(); - } + IHCMap3_T() : Inherit_CMAP(), Inherit_CPH(this->topology_) + { + init(); + } - ~IHCMap3_T() override - {} + ~IHCMap3_T() override + {} - IHCMap3_T(Self const&) = delete; - IHCMap3_T(Self &&) = delete; - Self& operator=(Self const&) = delete; - Self& operator=(Self &&) = delete; + IHCMap3_T(Self const&) = delete; + IHCMap3_T(Self &&) = delete; + Self& operator=(Self const&) = delete; + Self& operator=(Self &&) = delete; public: - /******************************************************************************* - * Basic topological operations - *******************************************************************************/ - - inline Dart phi1(Dart d) const - { - cgogn_message_assert(Inherit_CPH::get_dart_level(d) <= Inherit_CPH::get_current_level(), "Access to a dart introduced after current level") ; - - bool finished = false ; - unsigned int edge_id = Inherit_CPH::get_edge_id(d) ; - Dart it = d ; - do - { - it = Inherit_CMAP::phi1(it) ; - if(Inherit_CPH::get_dart_level(it) <= Inherit_CPH::get_current_level()) - finished = true ; - else - { - while(Inherit_CPH::get_edge_id(it) != edge_id) - it = Inherit_CMAP::phi1(phi2bis(it)) ; - } - } while(!finished) ; - return it ; - } - - inline Dart phi_1(Dart d) const - { - cgogn_message_assert(Inherit_CPH::get_dart_level(d) <= Inherit_CPH::get_current_level(), "Access to a dart introduced after current level") ; - - bool finished = false ; - Dart it = Inherit_CMAP::phi_1(d) ; - unsigned int edge_id = Inherit_CPH::get_edge_id(d) ; - do - { - if(Inherit_CPH::get_dart_level(it) <= Inherit_CPH::get_current_level()) - finished = true ; - else - { - it = Inherit_CMAP::phi_1(it) ; - while(Inherit_CPH::get_edge_id(it) != edge_id) - it = Inherit_CMAP::phi_1(phi2bis(it)) ; - } - } while(!finished) ; - return it ; - } - - /** - * \brief phi2 - * @param d - * @return phi2(d) - */ - inline Dart phi2(Dart d) const - { - cgogn_message_assert(Inherit_CPH::get_dart_level(d) <= Inherit_CPH::get_current_level(), "Access to a dart introduced after current level") ; - - return Inherit_CMAP::phi2(Inherit_CMAP::phi_1(phi1(d))); - } - - inline Dart phi3(Dart d) const - { - cgogn_message_assert(Inherit_CPH::get_dart_level(d) <= Inherit_CPH::get_current_level(), "Access to a dart introduced after current level") ; - - if(Inherit_CMAP::phi3(d) == d); - return d; - - return Inherit_CMAP::phi3(Inherit_CMAP::phi_1(phi1(d))); - } - - /** - * \brief add a Dart in the map - * @return the new Dart - */ - inline Dart add_dart() - { - Dart d = Inherit_CMAP::add_dart(); - - Inherit_CPH::set_edge_id(d, 0); - Inherit_CPH::set_face_id(d, 0); - Inherit_CPH::set_dart_level(d, Inherit_CPH::get_current_level()); - - // update max level if needed - if(Inherit_CPH::get_current_level() > Inherit_CPH::get_maximum_level()) - { - Inherit_CPH::set_maximum_level(Inherit_CPH::get_current_level()); - // Inherit_CPH::new_level_darts(); - } - - // Inherit_CPH::inc_nb_darts(get_current_level()); - - return d ; - } + /******************************************************************************* + * Basic topological operations + *******************************************************************************/ + + inline Dart phi1(Dart d) const + { + cgogn_message_assert(Inherit_CPH::get_dart_level(d) <= Inherit_CPH::get_current_level(), "Access to a dart introduced after current level") ; + + bool finished = false ; + unsigned int edge_id = Inherit_CPH::get_edge_id(d) ; + Dart it = d ; + do + { + it = Inherit_CMAP::phi1(it) ; + if(Inherit_CPH::get_dart_level(it) <= Inherit_CPH::get_current_level()) + finished = true ; + else + { + while(Inherit_CPH::get_edge_id(it) != edge_id) + it = Inherit_CMAP::phi1(phi2bis(it)) ; + } + } while(!finished) ; + return it ; + } + + inline Dart phi_1(Dart d) const + { + cgogn_message_assert(Inherit_CPH::get_dart_level(d) <= Inherit_CPH::get_current_level(), "Access to a dart introduced after current level") ; + + bool finished = false ; + Dart it = Inherit_CMAP::phi_1(d) ; + unsigned int edge_id = Inherit_CPH::get_edge_id(d) ; + do + { + if(Inherit_CPH::get_dart_level(it) <= Inherit_CPH::get_current_level()) + finished = true ; + else + { + it = Inherit_CMAP::phi_1(it) ; + while(Inherit_CPH::get_edge_id(it) != edge_id) + it = Inherit_CMAP::phi_1(phi2bis(it)) ; + } + } while(!finished) ; + return it ; + } + + /** + * \brief phi2 + * @param d + * @return phi2(d) + */ + inline Dart phi2(Dart d) const + { + cgogn_message_assert(Inherit_CPH::get_dart_level(d) <= Inherit_CPH::get_current_level(), "Access to a dart introduced after current level") ; + + return Inherit_CMAP::phi2(Inherit_CMAP::phi_1(phi1(d))); + } + + inline Dart phi3(Dart d) const + { + cgogn_message_assert(Inherit_CPH::get_dart_level(d) <= Inherit_CPH::get_current_level(), "Access to a dart introduced after current level") ; + + if(Inherit_CMAP::phi3(d) == d); + return d; + + return Inherit_CMAP::phi3(Inherit_CMAP::phi_1(phi1(d))); + } + + /** + * \brief add a Dart in the map + * @return the new Dart + */ + inline Dart add_dart() + { + Dart d = Inherit_CMAP::add_dart(); + + Inherit_CPH::set_edge_id(d, 0); + Inherit_CPH::set_face_id(d, 0); + Inherit_CPH::set_dart_level(d, Inherit_CPH::get_current_level()); + + // update max level if needed + if(Inherit_CPH::get_current_level() > Inherit_CPH::get_maximum_level()) + { + Inherit_CPH::set_maximum_level(Inherit_CPH::get_current_level()); + // Inherit_CPH::new_level_darts(); + } + + // Inherit_CPH::inc_nb_darts(get_current_level()); + + return d ; + } protected: - inline Dart phi2bis(Dart d) const - { - unsigned int face_id = Inherit_CPH::get_face_id(d); - Dart it = d; - - it = Inherit_CMAP::phi2(it); - - if(Inherit_CPH::get_face_id(it) == face_id) - return it; - else - { - do - { - it = Inherit_CMAP::phi2(Inherit_CMAP::phi3(it)); - } - while(Inherit_CPH::get_face_id(it) != face_id); - - return it; - } - } - - /******************************************************************************* - * Orbits traversal - *******************************************************************************/ - - template - inline void foreach_dart_of_DART(Dart d, const FUNC& f) const - { - f(d); - } - - template - inline void foreach_dart_of_PHI1(Dart d, const FUNC& f) const - { - Dart it = d; - do - { - f(it); - it = phi1(it); - } while (it != d); - } - - template - inline void foreach_dart_of_PHI2(Dart d, const FUNC& f) const - { - f(d); - Dart d2 = phi2(d); - if (d2 != d) - f(d2); - } - - template - inline void foreach_dart_of_PHI21(Dart d, const FUNC& f) const - { - Dart it = d; - do - { - f(it); - it = Inherit_CMAP::phi2(Inherit_CMAP::phi_1(it)); - } while (it != d); - } - - template - void foreach_dart_of_PHI1_PHI2(Dart d, const FUNC& f) const - { - DartMarkerStore marker(*this); - - std::vector* visited_faces = cgogn::get_dart_buffers()->get_buffer(); - visited_faces->push_back(d); // Start with the face of d - - // For every face added to the list - for(unsigned int i = 0; i < visited_faces->size(); ++i) - { - if (!marker.is_marked((*visited_faces)[i])) // Face has not been visited yet - { - // mark visited darts (current face) - // and add non visited adjacent faces to the list of face - Dart e = (*visited_faces)[i] ; - do - { - f(e); // apply the function to the darts of the face - marker.mark(e); // Mark - Dart adj = phi2(e); // Get adjacent face - if (!marker.is_marked(adj)) - visited_faces->push_back(adj); // Add it - e = phi1(e); - } while (e != (*visited_faces)[i]); - } - } - - cgogn::get_dart_buffers()->release_buffer(visited_faces); - } - - template - inline void foreach_dart_of_PHI21_PHI31(Dart d, const FUNC& f) const - { - DartMarkerStore marker(*this); - const std::vector* marked_darts = marker.get_marked_darts(); - - marker.mark(d); - for(unsigned int i = 0; i < marked_darts->size(); ++i) - { - f((*marked_darts)[i]); - - Dart d2 = phi2((*marked_darts)[i]); - Dart d21 = phi1(d2); // turn in volume - Dart d23 = phi3(d2); // change volume - if(!marker.is_marked(d21)) - marker.mark(d21); - if(!marker.is_marked(d23)) - marker.mark(d23); - } - } - - template - inline void foreach_dart_of_PHI2_PHI3(Dart d, const FUNC& f) const - { - Dart it = d; - do - { - f(it); - it = phi2(it); - f(it); - it = phi3(it); - } while (it != d); - } - - template - inline void foreach_dart_of_PHI23(Dart d, const FUNC& f) const - { - Dart it = d; - do - { - f(it); - it = phi3(phi2(it)); - } while (it != d); - } - - template - inline void foreach_dart_of_PHI1_PHI3(Dart d, const FUNC& f) const - { - foreach_dart_of_PHI1(d, [&] (Dart fd) - { - f(fd); - f(phi3(fd)); - }); - } + inline Dart phi2bis(Dart d) const + { + unsigned int face_id = Inherit_CPH::get_face_id(d); + Dart it = d; + + it = Inherit_CMAP::phi2(it); + + if(Inherit_CPH::get_face_id(it) == face_id) + return it; + else + { + do + { + it = Inherit_CMAP::phi2(Inherit_CMAP::phi3(it)); + } + while(Inherit_CPH::get_face_id(it) != face_id); + + return it; + } + } + + /******************************************************************************* + * Orbits traversal + *******************************************************************************/ + + template + inline void foreach_dart_of_DART(Dart d, const FUNC& f) const + { + f(d); + } + + template + inline void foreach_dart_of_PHI1(Dart d, const FUNC& f) const + { + Dart it = d; + do + { + f(it); + it = phi1(it); + } while (it != d); + } + + template + inline void foreach_dart_of_PHI2(Dart d, const FUNC& f) const + { + f(d); + Dart d2 = phi2(d); + if (d2 != d) + f(d2); + } + + template + inline void foreach_dart_of_PHI21(Dart d, const FUNC& f) const + { + Dart it = d; + do + { + f(it); + it = Inherit_CMAP::phi2(Inherit_CMAP::phi_1(it)); + } while (it != d); + } + + template + void foreach_dart_of_PHI1_PHI2(Dart d, const FUNC& f) const + { + DartMarkerStore marker(*this); + + std::vector* visited_faces = cgogn::get_dart_buffers()->get_buffer(); + visited_faces->push_back(d); // Start with the face of d + + // For every face added to the list + for(unsigned int i = 0; i < visited_faces->size(); ++i) + { + if (!marker.is_marked((*visited_faces)[i])) // Face has not been visited yet + { + // mark visited darts (current face) + // and add non visited adjacent faces to the list of face + Dart e = (*visited_faces)[i] ; + do + { + f(e); // apply the function to the darts of the face + marker.mark(e); // Mark + Dart adj = phi2(e); // Get adjacent face + if (!marker.is_marked(adj)) + visited_faces->push_back(adj); // Add it + e = phi1(e); + } while (e != (*visited_faces)[i]); + } + } + + cgogn::get_dart_buffers()->release_buffer(visited_faces); + } + + template + inline void foreach_dart_of_PHI21_PHI31(Dart d, const FUNC& f) const + { + DartMarkerStore marker(*this); + const std::vector* marked_darts = marker.get_marked_darts(); + + marker.mark(d); + for(unsigned int i = 0; i < marked_darts->size(); ++i) + { + f((*marked_darts)[i]); + + Dart d2 = phi2((*marked_darts)[i]); + Dart d21 = phi1(d2); // turn in volume + Dart d23 = phi3(d2); // change volume + if(!marker.is_marked(d21)) + marker.mark(d21); + if(!marker.is_marked(d23)) + marker.mark(d23); + } + } + + template + inline void foreach_dart_of_PHI2_PHI3(Dart d, const FUNC& f) const + { + Dart it = d; + do + { + f(it); + it = phi2(it); + f(it); + it = phi3(it); + } while (it != d); + } + + template + inline void foreach_dart_of_PHI23(Dart d, const FUNC& f) const + { + Dart it = d; + do + { + f(it); + it = phi3(phi2(it)); + } while (it != d); + } + + template + inline void foreach_dart_of_PHI1_PHI3(Dart d, const FUNC& f) const + { + foreach_dart_of_PHI1(d, [&] (Dart fd) + { + f(fd); + f(phi3(fd)); + }); + } public: - template - inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const - { - static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || - ORBIT == Orbit::PHI2 || ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21, - "Orbit not supported in a CMap2"); - switch (ORBIT) - { - case Orbit::DART: foreach_dart_of_DART(c, f); break; - case Orbit::PHI1: foreach_dart_of_PHI1(c, f); break; - case Orbit::PHI2: foreach_dart_of_PHI2(c, f); break; - case Orbit::PHI1_PHI2: foreach_dart_of_PHI1_PHI2(c, f); break; - case Orbit::PHI1_PHI3: foreach_dart_of_PHI1_PHI3(c, f); break; - case Orbit::PHI2_PHI3: foreach_dart_of_PHI2_PHI3(c, f); break; - case Orbit::PHI21: foreach_dart_of_PHI21(c, f); break; - case Orbit::PHI21_PHI31: foreach_dart_of_PHI21_PHI31(c, f); break; - default: cgogn_assert_not_reached("Cells of this dimension are not handled"); break; - } - } + template + inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const + { + static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || + ORBIT == Orbit::PHI2 || ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21, + "Orbit not supported in a CMap2"); + switch (ORBIT) + { + case Orbit::DART: foreach_dart_of_DART(c, f); break; + case Orbit::PHI1: foreach_dart_of_PHI1(c, f); break; + case Orbit::PHI2: foreach_dart_of_PHI2(c, f); break; + case Orbit::PHI1_PHI2: foreach_dart_of_PHI1_PHI2(c, f); break; + case Orbit::PHI1_PHI3: foreach_dart_of_PHI1_PHI3(c, f); break; + case Orbit::PHI2_PHI3: foreach_dart_of_PHI2_PHI3(c, f); break; + case Orbit::PHI21: foreach_dart_of_PHI21(c, f); break; + case Orbit::PHI21_PHI31: foreach_dart_of_PHI21_PHI31(c, f); break; + default: cgogn_assert_not_reached("Cells of this dimension are not handled"); break; + } + } }; template struct IHCMap3Type { - typedef IHCMap3_T> TYPE; + typedef IHCMap3_T> TYPE; }; template using IHCMap3 = IHCMap3_T>; +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_IHCMAP3_CPP_)) +extern template class CGOGN_MULTIRESOLUTION_API IHCMap3_T>; +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_IHCMAP3_CPP_)) + } // namespace cgogn diff --git a/cgogn/multiresolution/mra/lerp_triquad_mra.h b/cgogn/multiresolution/mra/lerp_triquad_mra.h index 1aa7f166..e4a40f98 100644 --- a/cgogn/multiresolution/mra/lerp_triquad_mra.h +++ b/cgogn/multiresolution/mra/lerp_triquad_mra.h @@ -37,18 +37,18 @@ class LerpTriQuadMRAnalysis : public MRAnalysis typedef LerpTriQuadMRAnalysis Self; typedef MRAnalysis Inherit; - using VertexAttributeHandler = typename MRMAP::template VertexAttributeHandler; + using VertexAttributeHandler = typename MRMAP::template VertexAttributeHandler; protected: - VertexAttributeHandler& va_; + VertexAttributeHandler& va_; public: LerpTriQuadMRAnalysis(MRMAP& map, VertexAttributeHandler& v): Inherit(map), - va_(v) - { + va_(v) + { this->synthesis_filters_.push_back(lerp_tri_quad_odd_synthesis_); - } + } LerpTriQuadMRAnalysis(Self const& ) = delete; LerpTriQuadMRAnalysis(Self&& ) = delete; @@ -60,55 +60,55 @@ class LerpTriQuadMRAnalysis : public MRAnalysis protected: - std::function lerp_tri_quad_odd_synthesis_ = [this] () - { - this->map_.template foreach_cell([&] (MRMAP::Face f) - { + std::function lerp_tri_quad_odd_synthesis_ = [this] () + { + this->map_.template foreach_cell([&] (typename MRMAP::Face f) + { if(this->map_.degree(f) != 3) - { - VEC3 vf(0.0); - VEC3 ef(0.0); + { + VEC3 vf(0.0); + VEC3 ef(0.0); - unsigned int count = 0; + unsigned int count = 0; - this->map_.foreach_incident_edge(f, [&] (MRMAP::Edge e) - { - vf += va_[e.dart]; + this->map_.foreach_incident_edge(f, [&] (typename MRMAP::Edge e) + { + vf += va_[e.dart]; this->map_.inc_current_level(); ef += va_[this->map_.phi1(e.dart)]; this->map_.dec_current_level(); - ++count; - }); + ++count; + }); - ef /= count; - ef *= 2.0; + ef /= count; + ef *= 2.0; - vf /= count; + vf /= count; this->map_.inc_current_level() ; Dart midF = this->map_.phi1(this->map_.phi1(f.dart)); - va_[midF] += vf + ef ; + va_[midF] += vf + ef ; this->map_.dec_current_level() ; - } - }); + } + }); - this->map_.template foreach_cell([&] (MRMAP::Edge e) - { + this->map_.template foreach_cell([&] (typename MRMAP::Edge e) + { VEC3 ve = (va_[e.dart] + va_[this->map_.phi1(e)]) * 0.5; this->map_.inc_current_level() ; Dart midV = this->map_.phi1(e) ; - va_[midV] += ve ; + va_[midV] += ve ; this->map_.dec_current_level() ; - }); - }; + }); + }; public: void add_level() override - { + { this->map_.add_mixed_level(); - } + } }; diff --git a/cgogn/multiresolution/mra/mr_analysis.h b/cgogn/multiresolution/mra/mr_analysis.h index 5699f04d..d8b9bf21 100644 --- a/cgogn/multiresolution/mra/mr_analysis.h +++ b/cgogn/multiresolution/mra/mr_analysis.h @@ -34,15 +34,15 @@ class MRAnalysis protected: - MRMAP& map_; + MRMAP& map_; - std::vector> synthesis_filters_; - std::vector> analysis_filters_; + std::vector> synthesis_filters_; + std::vector> analysis_filters_; public: - MRAnalysis(MRMAP& map): - map_(map) - {} + MRAnalysis(MRMAP& map): + map_(map) + {} MRAnalysis(Self const& ) = delete; MRAnalysis(Self&& ) = delete; @@ -52,25 +52,25 @@ class MRAnalysis virtual ~MRAnalysis() {} - void analysis() - { - cgogn_message_assert(map_.get_current_level() > 0, "analysis : called on level 0") ; + void analysis() + { + cgogn_message_assert(map_.get_current_level() > 0, "analysis : called on level 0") ; - map_.dec_current_level() ; + map_.dec_current_level() ; - for(unsigned int i = 0; i < analysis_filters_.size(); ++i) - analysis_filters_[i](); - } + for(unsigned int i = 0; i < analysis_filters_.size(); ++i) + analysis_filters_[i](); + } - void synthesis() - { - cgogn_message_assert(map_.get_current_level() < map_.get_maximum_level(), "synthesis : called on max level") ; + void synthesis() + { + cgogn_message_assert(map_.get_current_level() < map_.get_maximum_level(), "synthesis : called on max level") ; - for(unsigned int i = 0; i < synthesis_filters_.size(); ++i) - synthesis_filters_[i](); + for(unsigned int i = 0; i < synthesis_filters_.size(); ++i) + synthesis_filters_[i](); - map_.inc_current_level(); - } + map_.inc_current_level(); + } virtual void add_level() = 0; }; From 1998315b54e9f2d6ef0f59b1ecfac898270bc238 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 10 Feb 2016 17:54:29 +0100 Subject: [PATCH 088/402] no virtual inheritance (CRTP) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/multiresolution/cph/ihcmap2.h | 2 +- cgogn/multiresolution/cph/ihcmap3.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cgogn/multiresolution/cph/ihcmap2.h b/cgogn/multiresolution/cph/ihcmap2.h index 3772836a..7673be26 100644 --- a/cgogn/multiresolution/cph/ihcmap2.h +++ b/cgogn/multiresolution/cph/ihcmap2.h @@ -54,7 +54,7 @@ class ContainerCPHBrowser : public ContainerBrowser }; template -class IHCMap2_T : virtual public CMap2_T, virtual public CPH2 +class IHCMap2_T : public CMap2_T, public CPH2 // Can't use virtual inheritance because of the use of the CRTP { public: diff --git a/cgogn/multiresolution/cph/ihcmap3.h b/cgogn/multiresolution/cph/ihcmap3.h index 10921c28..2e107df6 100644 --- a/cgogn/multiresolution/cph/ihcmap3.h +++ b/cgogn/multiresolution/cph/ihcmap3.h @@ -33,7 +33,7 @@ namespace cgogn template -class IHCMap3_T :virtual public CMap3_T, virtual public CPH3 +class IHCMap3_T :public CMap3_T, public CPH3 // Can't use virtual inheritance because of the use of the CRTP { public: From c450a88127eaf129ce6468b1c0649cb07f1ae656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Thu, 11 Feb 2016 17:40:45 +0100 Subject: [PATCH 089/402] added close_hole_topo for cmap3. Handling embeddings in close_map of cmap3. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/cmap3.h | 156 ++++++++++++++++++++++++++++------------ 1 file changed, 112 insertions(+), 44 deletions(-) diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index a9d0fe04..7a4efa5d 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -215,6 +215,63 @@ class CMap3_T : public CMap2_T return dres; } + inline void close_hole_topo(Dart d) + { + cgogn_message_assert(phi3(d) == d, "CMap3: close hole called on a dart that is not a phi3 fix point"); + DartMarkerStore dmarker(*this); + DartMarkerStore boundary_marker(*this); + + std::vector visitedFaces; // Faces that are traversed + visitedFaces.reserve(1024); + + visitedFaces.push_back(d); // Start with the face of d + dmarker.template mark_orbit(d); + + unsigned int count = 0u; + + // For every face added to the list + for(unsigned int i = 0u; i < visitedFaces.size(); ++i) + { + Dart it = visitedFaces[i]; + Dart f = it; + + const Dart b = this->add_face_topo(this->degree(Face(f))); + boundary_marker.template mark_orbit(b); + ++count; + + Dart bit = b; + do + { + Dart e = this->phi3(this->phi2(f));; + bool found = false; + do + { + if (phi3(e) == e) + { + found = true; + if(!dmarker.is_marked(e)) + { + visitedFaces.push_back(e); + dmarker.template mark_orbit(e); + } + } else { + if(boundary_marker.is_marked(e)) + { + found = true; + this->phi2_sew(e, bit); + } else { + e = this->phi3(this->phi2(e)); + } + } + } while(!found); + + phi3_sew(f, bit); + bit = this->phi_1(bit); + f = this->phi1(f); + } while(f != it); + } + } + /** * @brief close_map : /!\ DO NOT USE /!\ Close the map removing topological holes (only for import/creation) * Add volumes to the map that close every existing hole. @@ -229,57 +286,69 @@ class CMap3_T : public CMap2_T if (phi3(d) == d) { ++nb; - DartMarkerStore dmarker(*this); - DartMarkerStore boundary_marker(*this); + close_hole_topo(d); + const Dart new_volume = phi3(d); + + if (this->template is_orbit_embedded()) + { + foreach_dart_of_orbit(new_volume, [this] (Dart wd) + { + this->template set_orbit_embedding(wd, this->template add_attribute_element()); + }); + } - std::vector visitedFaces; // Faces that are traversed - visitedFaces.reserve(1024); + if (this->template is_orbit_embedded()) // cmap2 vertices + { - visitedFaces.push_back(d); // Start with the face of d - dmarker.template mark_orbit(d); + Inherit::foreach_incident_vertex(Volume(new_volume), [this] (Cell v) + { + this->set_orbit_embedding(v, this->template add_attribute_element()); + }); + } + + if (this->template is_orbit_embedded()) // cmap2 edges + { + Inherit::foreach_incident_edge(Volume(new_volume), [this] (Cell e) + { + this->set_orbit_embedding(e, this->template add_attribute_element()); + }); + } - unsigned int count = 0u; + if (this->template is_orbit_embedded()) // cmap2 faces + { + Inherit::foreach_incident_face(Volume(new_volume), [this] (Cell f) + { + this->set_orbit_embedding(f, this->template add_attribute_element()); + }); + } - // For every face added to the list - for(unsigned int i = 0u; i < visitedFaces.size(); ++i) + if (this->template is_orbit_embedded()) { - Dart it = visitedFaces[i]; - Dart f = it; + foreach_dart_of_orbit(new_volume, [this] (Dart wd) + { + this->template set_embedding(wd, this->template get_embedding(this->phi1(phi3(wd)))); + }); + } - const Dart b = this->add_face_topo(this->degree(Face(f))); - boundary_marker.template mark_orbit(b); - ++count; + if (this->template is_orbit_embedded()) + { + foreach_dart_of_orbit(new_volume, [this] (Dart wd) + { + this->template set_embedding(wd, this->template get_embedding(phi3(wd))); + }); + } - Dart bit = b; - do + if (this->template is_orbit_embedded()) + { + foreach_dart_of_orbit(new_volume, [this] (Dart wd) { - Dart e = this->phi3(this->phi2(f));; - bool found = false; - do - { - if (phi3(e) == e) - { - found = true; - if(!dmarker.is_marked(e)) - { - visitedFaces.push_back(e); - dmarker.template mark_orbit(e); - } - } else { - if(boundary_marker.is_marked(e)) - { - found = true; - this->phi2_sew(e, bit); - } else { - e = this->phi3(this->phi2(e)); - } - } - } while(!found); - - phi3_sew(f, bit); - bit = this->phi_1(bit); - f = this->phi1(f); - } while(f != it); + this->template set_embedding(wd, this->template get_embedding(phi3(wd))); + }); + + } + if (this->template is_orbit_embedded()) + { + this->template set_orbit_embedding(new_volume, this->template add_attribute_element()); } } } @@ -323,7 +392,6 @@ class CMap3_T : public CMap2_T */ inline Dart add_dart() { - CGOGN_CHECK_CONCRETE_TYPE; Dart d = Inherit::add_dart(); (*phi3_)[d.index] = d; return d; From a83ef1ab4a9c23190cb22cad1e808b6ee4292e9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Thu, 11 Feb 2016 17:42:37 +0100 Subject: [PATCH 090/402] added all DartMarkers as friends. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/cmap1.h | 5 ++++- cgogn/core/cmap/cmap2.h | 11 +++++++---- cgogn/core/cmap/cmap3.h | 6 ++++-- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 44730aa5..70206cd5 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -44,7 +44,10 @@ class CMap1_T : public MapBase typedef CMap1_T Self; friend typename Self::Inherit; - friend class DartMarker_T; + template + friend class DartMarker_T; + template + friend class DartMarkerStore; static const Orbit DART = Orbit::DART; static const Orbit VERTEX = Orbit::DART; diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index dfdca391..a6f2b4eb 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -49,7 +49,10 @@ class CMap2_T : public CMap1_T friend typename Self::Inherit; friend typename Inherit::Inherit; friend class CMap2Builder_T; - friend class DartMarker_T; + template + friend class DartMarker_T; + template + friend class DartMarkerStore; static const Orbit DART = Orbit::DART; static const Orbit VERTEX = Orbit::PHI21; @@ -617,7 +620,7 @@ class CMap2_T : public CMap1_T { if (!marker.is_marked(d)) { - marker.mark_orbit(d); + marker.template mark_orbit(d); f(d); } }); @@ -632,7 +635,7 @@ class CMap2_T : public CMap1_T { if (!marker.is_marked(d)) { - marker.mark_orbit(d); + marker.template mark_orbit(d); f(d); } }); @@ -647,7 +650,7 @@ class CMap2_T : public CMap1_T { if (!marker.is_marked(d)) { - marker.mark_orbit(d); + marker.template mark_orbit(d); f(d); } }); diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 7a4efa5d..9fce68b0 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -49,8 +49,10 @@ class CMap3_T : public CMap2_T friend typename Self::Inherit; friend typename Inherit::Inherit; friend typename Inherit::Inherit::Inherit; - friend class DartMarker_T; - friend class cgogn::DartMarkerStore; + template + friend class DartMarker_T; + template + friend class DartMarkerStore; friend class CMap3Builder_T; static const Orbit VERTEX = Orbit::PHI21_PHI31; From 5b1df6c1a658a878eab52aabc208ca4c83e06afd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Thu, 11 Feb 2016 17:48:58 +0100 Subject: [PATCH 091/402] renamed some variables. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/volume_import.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/cgogn/io/volume_import.h b/cgogn/io/volume_import.h index c5bb3e89..e80b15ab 100644 --- a/cgogn/io/volume_import.h +++ b/cgogn/io/volume_import.h @@ -72,7 +72,7 @@ class VolumeImport unsigned int nb_faces_; unsigned int nb_volumes_; - std::vector volumes_nb_faces_; + std::vector volumes_nb_vertices_; std::vector volumes_vertex_indices_; ChunkArrayContainer vertex_attributes_; @@ -81,7 +81,7 @@ class VolumeImport nb_vertices_(0u) ,nb_edges_(0u) ,nb_faces_(0u) - ,volumes_nb_faces_() + ,volumes_nb_vertices_() ,volumes_vertex_indices_() {} @@ -98,7 +98,7 @@ class VolumeImport nb_vertices_ = 0; nb_edges_ = 0; nb_faces_ = 0; - volumes_nb_faces_.clear(); + volumes_nb_vertices_.clear(); volumes_vertex_indices_.clear(); vertex_attributes_.remove_attributes(); } @@ -159,11 +159,11 @@ class VolumeImport for(unsigned int i = 0u; i < this->nb_volumes_; ++i) { // store volume in buffer, removing degenated faces - const unsigned int nbf = this->volumes_nb_faces_[i]; + const unsigned int nbv = this->volumes_nb_vertices_[i]; edgesBuffer.clear(); unsigned int prec = std::numeric_limits::max(); - for (unsigned int j = 0u; j < nbf; ++j) + for (unsigned int j = 0u; j < nbv; ++j) { unsigned int em = this->volumes_vertex_indices_[index++]; if (em != prec) @@ -173,7 +173,7 @@ class VolumeImport } } - if(nbf == 4u) //tetrahedral case + if(nbv == 4u) //tetrahedral case { const Dart d = mbuild.add_pyramid_topo(3u); @@ -198,7 +198,7 @@ class VolumeImport } while(dd != dv); } } - else if(nbf == 5u) //pyramidal case + else if(nbv == 5u) //pyramidal case { Dart d = mbuild.add_pyramid_topo(4u); @@ -224,7 +224,7 @@ class VolumeImport } while(dd != dv); } } - else if(nbf == 6u) //prism case + else if(nbv == 6u) //prism case { Dart d = mbuild.add_prism_topo(3u); const std::array vertices_of_prism = { @@ -251,7 +251,7 @@ class VolumeImport } while(dd != dv); } } - else if(nbf == 8u) //hexahedral case + else if(nbv == 8u) //hexahedral case { Dart d = mbuild.add_prism_topo(4u); const std::array vertices_of_hexa = { @@ -477,7 +477,7 @@ class VolumeImport { if (typeVols[i]==12u) { - volumes_nb_faces_.push_back(8u); + volumes_nb_vertices_.push_back(8u); std::array pt; VEC3 const& P = position->operator [](verticesID[indices[currentOffset+4]]); @@ -520,7 +520,7 @@ class VolumeImport } else if (typeVols[i]==10u) { - volumes_nb_faces_.push_back(4u); + volumes_nb_vertices_.push_back(4u); std::array pt; pt[0] = indices[currentOffset]; From 710dda31add1634eb51a1a7a07f98e1ed3c739e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Thu, 11 Feb 2016 17:58:08 +0100 Subject: [PATCH 092/402] add_dart_internal() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/cmap0.h | 2 +- cgogn/core/cmap/cmap1.h | 9 ++++----- cgogn/core/cmap/cmap2.h | 9 ++++----- cgogn/core/cmap/cmap3.h | 4 ++-- cgogn/core/cmap/map_base.h | 5 +++++ cgogn/multiresolution/cph/ihcmap2.h | 4 ++-- cgogn/multiresolution/cph/ihcmap3.h | 4 ++-- 7 files changed, 20 insertions(+), 17 deletions(-) diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index 56b4369a..a3cf8199 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -86,7 +86,7 @@ class CMap0_T : public MapBase Self& operator=(Self &&) = delete; protected: - inline Dart add_dart() + inline Dart add_dart_internal() { CGOGN_CHECK_CONCRETE_TYPE; return Dart(this->add_topology_element()); diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 70206cd5..b495b1e1 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -174,9 +174,8 @@ class CMap1_T : public MapBase * \brief add a Dart in the map * @return the new Dart */ - inline Dart add_dart() + inline Dart add_dart_internal() { - CGOGN_CHECK_CONCRETE_TYPE; unsigned int di = this->add_topology_element(); Dart d(di); (*phi1_)[di] = d; @@ -199,7 +198,7 @@ class CMap1_T : public MapBase { cgogn_message_assert(nb_edges > 0u, "Cannot create a face with no edge"); - Dart d = this->to_concrete()->add_dart(); + Dart d = this->add_dart(); for (unsigned int i = 1u; i < nb_edges; ++i) cut_edge_topo(d); @@ -226,8 +225,8 @@ class CMap1_T : public MapBase */ inline Dart cut_edge_topo(Dart d) { - Dart e = this->to_concrete()->add_dart(); // Create a new dart e - phi1_sew(d, e); // Insert e between d and phi1(d) + Dart e = this->add_dart(); // Create a new dart e + phi1_sew(d, e); // Insert e between d and phi1(d) return e; } diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index a6f2b4eb..86cc3fa0 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -162,10 +162,9 @@ class CMap2_T : public CMap1_T * \brief add a Dart in the map * @return the new Dart */ - inline Dart add_dart() + inline Dart add_dart_internal() { - CGOGN_CHECK_CONCRETE_TYPE; - Dart d = Inherit::add_dart(); + Dart d = Inherit::add_dart_internal(); (*phi2_)[d.index] = d; return d; } @@ -389,7 +388,7 @@ class CMap2_T : public CMap1_T { cgogn_message_assert(phi2(d) == d, "CMap2: close hole called on a dart that is not a phi2 fix point"); - Dart first = add_dart(); // First edge of the face that will fill the hole + Dart first = this->add_dart(); // First edge of the face that will fill the hole phi2_sew(d, first); // phi2-link the new edge to the hole Dart d_next = d; // Turn around the hole @@ -404,7 +403,7 @@ class CMap2_T : public CMap1_T if (d_phi1 != d) { - Dart next = add_dart(); // Add a new edge there and link it to the face + Dart next = this->add_dart(); // Add a new edge there and link it to the face this->phi1_sew(first, next); // the edge is linked to the face phi2_sew(d_next, next); // the face is linked to the hole } diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 9fce68b0..0215fa96 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -392,9 +392,9 @@ class CMap3_T : public CMap2_T * \brief add a Dart in the map * @return the new Dart */ - inline Dart add_dart() + inline Dart add_dart_internal() { - Dart d = Inherit::add_dart(); + Dart d = Inherit::add_dart_internal(); (*phi3_)[d.index] = d; return d; } diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 7e7a3043..fc7b7344 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -136,6 +136,11 @@ class MapBase : public MapBaseData return static_cast(this); } + inline Dart add_dart() + { + return this->to_concrete()->add_dart_internal(); + } + /******************************************************************************* * Container elements management *******************************************************************************/ diff --git a/cgogn/multiresolution/cph/ihcmap2.h b/cgogn/multiresolution/cph/ihcmap2.h index 7673be26..ef9211fc 100644 --- a/cgogn/multiresolution/cph/ihcmap2.h +++ b/cgogn/multiresolution/cph/ihcmap2.h @@ -194,9 +194,9 @@ class IHCMap2_T : public CMap2_T, public CPH2, public CPH3 * \brief add a Dart in the map * @return the new Dart */ - inline Dart add_dart() + inline Dart add_dart_internal() { - Dart d = Inherit_CMAP::add_dart(); + Dart d = Inherit_CMAP::add_dart_internal(); Inherit_CPH::set_edge_id(d, 0); Inherit_CPH::set_face_id(d, 0); From be92cd161bd8d32e0633ebab64ac507012a1e075 Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Fri, 12 Feb 2016 15:09:37 +0100 Subject: [PATCH 093/402] clean commit of simple Masks lambdas on foreach_xxx --- cgogn/CMakeLists.txt | 2 +- cgogn/core/cmap/cmap2.h | 8 +- cgogn/core/cmap/cmap3.h | 8 +- cgogn/core/cmap/map_base.h | 474 +++++++++++++++------- cgogn/core/cmap/map_base_data.h | 38 +- cgogn/core/cmap/sanity_check.h | 15 +- cgogn/core/examples/map/map.cpp | 5 +- cgogn/geometry/tests/algos/algos_test.cpp | 60 ++- cgogn/io/surface_import.h | 4 +- cgogn/io/volume_import.h | 4 +- 10 files changed, 410 insertions(+), 208 deletions(-) diff --git a/cgogn/CMakeLists.txt b/cgogn/CMakeLists.txt index 0e58899a..190b1a7b 100644 --- a/cgogn/CMakeLists.txt +++ b/cgogn/CMakeLists.txt @@ -6,4 +6,4 @@ if(CGOGN_USE_QT) add_subdirectory(rendering) endif(CGOGN_USE_QT) -add_subdirectory(multiresolution) +#add_subdirectory(multiresolution) diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index dfdca391..bc108867 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -172,7 +172,13 @@ class CMap2_T : public CMap1_T */ void close_map() { - for (Dart d : *this) + std::vector fix_point_darts; + this->foreach_dart([&] (Dart d) + { + if (phi2(d) == d) + fix_point_darts.push_back(d); + }); + for (Dart d : fix_point_darts) { if (phi2(d) == d) { diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index a9d0fe04..e8550742 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -224,7 +224,13 @@ class CMap3_T : public CMap2_T { // Search the map for topological holes (fix points of phi3) unsigned int nb = 0u; - for (Dart d: (*this)) + std::vector fix_point_darts; + this->foreach_dart([&] (Dart d) + { + if (phi3(d) == d) + fix_point_darts.push_back(d); + }); + for (Dart d : fix_point_darts) { if (phi3(d) == d) { diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 7e7a3043..f297d562 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -75,7 +75,8 @@ class MapBase : public MapBaseData template using CellMarker = cgogn::CellMarker; - MapBase() : Inherit() + MapBase() : + Inherit() {} ~MapBase() @@ -324,16 +325,16 @@ class MapBase : public MapBaseData this->embeddings_[ORBIT] = ca; // initialize all darts indices to EMBNULL for this ORBIT - foreach_dart([this] (Dart d) - { - (*this->embeddings_[ORBIT])[d.index] = EMBNULL; - }); + foreach_dart( + [this] (Dart d) { (*this->embeddings_[ORBIT])[d.index] = EMBNULL; }, + [] (Dart) { return true; } + ); // initialize the indices of the existing orbits - foreach_cell([this] (Cell c) - { - set_orbit_embedding(c, add_attribute_element()); - }); + foreach_cell( + [this] (Cell c) { set_orbit_embedding(c, add_attribute_element()); }, + [] (Dart) { return true; } + ); } template @@ -360,12 +361,15 @@ class MapBase : public MapBaseData for (unsigned int& i : counter) i = 0; ConcreteMap* cmap = to_concrete(); - foreach_cell([cmap, &counter] (Cell c) - { - if (counter[c] > 0) - cmap->set_orbit_embedding(c, cmap->template add_attribute_element()); - counter[c]++; - }); + foreach_cell( + [cmap, &counter] (Cell c) + { + if (counter[c] > 0) + cmap->set_orbit_embedding(c, cmap->template add_attribute_element()); + counter[c]++; + }, + [] (Dart) { return true; } + ); remove_attribute(counter); } @@ -424,10 +428,10 @@ class MapBase : public MapBaseData static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); cgogn_message_assert(is_topo_cache_enabled(), "Trying to update a disabled global topo cache"); - foreach_cell([this] (Cell c) - { - (*this->global_topo_cache_[ORBIT])[this->get_embedding(c)] = c.dart; - }); + foreach_cell( + [this] (Cell c) { (*this->global_topo_cache_[ORBIT])[this->get_embedding(c)] = c.dart; }, + [] (Dart) { return true; } + ); } template @@ -507,37 +511,67 @@ class MapBase : public MapBaseData return result; } + inline bool is_boundary(Dart d) const + { + return (*this->boundary_marker_)[d.index]; + } + + inline void set_boundary(Dart d, bool b) + { + this->boundary_marker_->set_value(d.index, b); + } + + template + inline bool is_boundary(Cell c) + { + static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); + static_assert(ORBIT == ConcreteMap::BOUNDARY, "Cell is not of current map boundary dimension"); + + return is_boundary(c.dart); + } + /******************************************************************************* * Traversals *******************************************************************************/ +protected: + + template class const_iterator { public: const Self& map_; + const MASK& mask_; Dart dart_; - inline const_iterator(const Self& map, Dart d) : + inline const_iterator(const Self& map, Dart d, const MASK& mask) : map_(map), - dart_(d) + dart_(d), + mask_(mask) {} inline const_iterator(const const_iterator& it) : map_(it.map_), - dart_(it.dart_) + dart_(it.dart_), + mask_(it.mask_) {} inline const_iterator& operator=(const const_iterator& it) { map_ = it.map_; dart_ = it.dart_; + mask_ = it.mask_; return *this; } inline const_iterator& operator++() { - map_.topology_.next(dart_.index); + const Dart end = Dart(map_.topology_.end()); + do + { + map_.topology_.next(dart_.index); + } while (dart_ != end && !mask_(dart_)); return *this; } @@ -551,18 +585,32 @@ class MapBase : public MapBaseData cgogn_assert(&map_ == &(it.map_)); return dart_ != it.dart_; } + + inline bool operator==(const const_iterator& it) const + { + cgogn_assert(&map_ == &(it.map_)); + return dart_ == it.dart_; + } }; - inline const_iterator begin() const + template + inline const_iterator begin(const MASK& mask) const { - return const_iterator(*this, Dart(this->topology_.begin())); + Dart d = Dart(this->topology_.begin()); + const Dart end = Dart(this->topology_.end()); + while (d != end && !mask(d)) + this->topology_.next(d.index); + return const_iterator(*this, d, mask); } - inline const_iterator end() const + template + inline const_iterator end(const MASK& mask) const { - return const_iterator(*this, Dart(this->topology_.end())); + return const_iterator(*this, Dart(this->topology_.end()), mask); } +public: + /** * \brief apply a function on each dart of the map * @tparam FUNC type of the callable @@ -570,22 +618,46 @@ class MapBase : public MapBaseData */ template inline void foreach_dart(const FUNC& f) const + { + foreach_dart(f, [this] (Dart d) { return !this->is_boundary(d); }); + } + + template + inline void foreach_boundary_dart(const FUNC& f) const + { + foreach_dart(f, [this] (Dart d) { return this->is_boundary(d); }); + } + + template + inline void foreach_dart(const FUNC& f, const MASK& mask) const { static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); + static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); + static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); - for (Dart d = Dart(this->topology_.begin()), end = Dart(this->topology_.end()); - d != end; - this->topology_.next(d.index)) - { - f(d); - } + for (const_iterator it = this->begin(mask), end = this->end(mask); it != end; ++it) + f(*it); } template inline void parallel_foreach_dart(const FUNC& f) const + { + parallel_foreach_dart(f, [this] (Dart d) { return !this->is_boundary(d); }); + } + + template + inline void parallel_foreach_boundary_dart(const FUNC& f) const + { + parallel_foreach_dart(f, [this] (Dart d) { return this->is_boundary(d); }); + } + + template + inline void parallel_foreach_dart(const FUNC& f, const MASK& mask) const { static_assert(check_func_ith_parameter_type(FUNC, 0, Dart), "Wrong function first parameter type"); static_assert(check_func_ith_parameter_type(FUNC, 1, unsigned int), "Wrong function second parameter type"); + static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); + static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); using Future = std::future< typename std::result_of::type >; using VecDarts = std::vector; @@ -600,17 +672,16 @@ class MapBase : public MapBaseData futures[0].reserve(nb_threads_pool); futures[1].reserve(nb_threads_pool); - Buffers* dbuffs = cgogn::get_dart_buffers(); - Dart it = Dart(this->topology_.begin()); - const Dart end = Dart(this->topology_.end()); + const_iterator it = this->begin(mask); + const const_iterator end = this->end(mask); while (it != end) { for (unsigned i = 0u; i < 2u; ++i) { - for (unsigned int j = 0u; j < nb_threads_pool && it != end ; ++j) + for (unsigned int j = 0u; j < nb_threads_pool && it != end; ++j) { dart_buffers[i].push_back(dbuffs->get_buffer()); cgogn_assert(dart_buffers[i].size() <= nb_threads_pool); @@ -618,18 +689,19 @@ class MapBase : public MapBaseData darts.reserve(PARALLEL_BUFFER_SIZE); for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != end; ++k) { - darts.push_back(it); - this->topology_.next(it.index); + darts.push_back(*it); + ++it; } - futures[i].push_back(thread_pool->enqueue( [&darts ,&f](unsigned int th_id){ + futures[i].push_back(thread_pool->enqueue([&darts ,&f] (unsigned int th_id) + { for (auto d : darts) - f(d,th_id); + f(d, th_id); })); } - const unsigned int id = (i+1u)%2u; - for (auto& fu: futures[id]) + const unsigned int id = (i+1u) % 2u; + for (auto& fu : futures[id]) fu.wait(); - for (auto &b : dart_buffers[id]) + for (auto& b : dart_buffers[id]) dbuffs->release_cell_buffer(b); futures[id].clear(); @@ -638,13 +710,12 @@ class MapBase : public MapBaseData // if we reach the end of the map while filling buffers from the second set we need to clean them too. if (it == end && i == 1u) { - for (auto& fu: futures[1u]) + for (auto& fu : futures[1u]) fu.wait(); for (auto &b : dart_buffers[1u]) dbuffs->release_buffer(b); } } - } } @@ -655,15 +726,27 @@ class MapBase : public MapBaseData */ template inline void foreach_dart_until(const FUNC& f) const + { + foreach_dart_until(f, [this] (Dart d) { return !this->is_boundary(d); }); + } + + template + inline void foreach_boundary_dart_until(const FUNC& f) const + { + foreach_dart_until(f, [this] (Dart d) { return this->is_boundary(d); }); + } + + template + inline void foreach_dart_until(const FUNC& f, const MASK& mask) const { static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); + static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); + static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); - for (Dart d = Dart(this->topology_.begin()), end = Dart(this->topology_.end()); - d != end; - this->topology_.next(d.index)) + for (const_iterator it = this->begin(mask), end = this->end(mask); it != end; ++it) { - if(!f(d)) + if (!f(*it)) break; } } @@ -676,55 +759,83 @@ class MapBase : public MapBaseData */ template inline void foreach_cell(const FUNC& f) const + { + foreach_cell(f, [this] (Dart d) { return !this->is_boundary(d); }); + } + + template + inline void foreach_boundary_cell(const FUNC& f) const + { + foreach_cell(f, [this] (Dart d) { return this->is_boundary(d); }); + } + + template + inline void foreach_cell(const FUNC& f, const MASK& mask) const { static_assert(check_func_parameter_type(FUNC, Cell), "Wrong function cell parameter type"); + static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); + static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); switch (STRATEGY) { case FORCE_DART_MARKING : - foreach_cell_dart_marking(f); + foreach_cell_dart_marking(f, mask); break; case FORCE_CELL_MARKING : - foreach_cell_cell_marking(f); + foreach_cell_cell_marking(f, mask); break; case FORCE_TOPO_CACHE : - foreach_cell_topo_cache(f); + foreach_cell_topo_cache(f, mask); break; case AUTO : if (is_topo_cache_enabled()) - foreach_cell_topo_cache(f); + foreach_cell_topo_cache(f, mask); else if (this->template is_orbit_embedded()) - foreach_cell_cell_marking(f); + foreach_cell_cell_marking(f, mask); else - foreach_cell_dart_marking(f); + foreach_cell_dart_marking(f, mask); break; } } template inline void parallel_foreach_cell(const FUNC& f) const + { + parallel_foreach_cell(f, [this] (Dart d) { return !this->is_boundary(d); }); + } + + template + inline void parallel_foreach_boundary_cell(const FUNC& f) const + { + parallel_foreach_cell(f, [this] (Dart d) { return this->is_boundary(d); }); + } + + template + inline void parallel_foreach_cell(const FUNC& f, const MASK& mask) const { static_assert(check_func_ith_parameter_type(FUNC, 0, Cell), "Wrong function first parameter type"); static_assert(check_func_ith_parameter_type(FUNC, 1, unsigned int), "Wrong function second parameter type"); + static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); + static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); switch (STRATEGY) { case FORCE_DART_MARKING : - parallel_foreach_cell_dart_marking(f); + parallel_foreach_cell_dart_marking(f, mask); break; case FORCE_CELL_MARKING : - parallel_foreach_cell_cell_marking(f); + parallel_foreach_cell_cell_marking(f, mask); break; case FORCE_TOPO_CACHE : - parallel_foreach_cell_topo_cache(f); + parallel_foreach_cell_topo_cache(f, mask); break; case AUTO : if (is_topo_cache_enabled()) - parallel_foreach_cell_topo_cache(f); + parallel_foreach_cell_topo_cache(f, mask); else if (this->template is_orbit_embedded()) - parallel_foreach_cell_cell_marking(f); + parallel_foreach_cell_cell_marking(f, mask); else - parallel_foreach_cell_dart_marking(f); + parallel_foreach_cell_dart_marking(f, mask); break; } } @@ -736,56 +847,68 @@ class MapBase : public MapBaseData * @param f a callable */ template - void foreach_cell_until(const FUNC& f) const + inline void foreach_cell_until(const FUNC& f) const + { + foreach_cell_until(f, [this] (Dart d) { return !this->is_boundary(d); }); + } + + template + inline void foreach_boundary_cell_until(const FUNC& f) const + { + foreach_cell_until(f, [this] (Dart d) { return this->is_boundary(d); }); + } + + template + void foreach_cell_until(const FUNC& f, const MASK& mask) const { static_assert(check_func_parameter_type(FUNC, Cell), "Wrong function cell parameter type"); static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); + static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); + static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); switch (STRATEGY) { case FORCE_DART_MARKING : - foreach_cell_until_dart_marking(f); + foreach_cell_until_dart_marking(f, mask); break; case FORCE_CELL_MARKING : - foreach_cell_until_cell_marking(f); + foreach_cell_until_cell_marking(f, mask); break; case FORCE_TOPO_CACHE : - foreach_cell_until_topo_cache(f); + foreach_cell_until_topo_cache(f, mask); break; case AUTO : if (is_topo_cache_enabled()) - foreach_cell_until_topo_cache(f); + foreach_cell_until_topo_cache(f, mask); else if (this->template is_orbit_embedded()) - foreach_cell_until_cell_marking(f); + foreach_cell_until_cell_marking(f, mask); else - foreach_cell_until_dart_marking(f); + foreach_cell_until_dart_marking(f, mask); break; } } protected: - template - inline void foreach_cell_dart_marking(const FUNC& f) const + template + inline void foreach_cell_dart_marking(const FUNC& f, const MASK& mask) const { DartMarker dm(*to_concrete()); - for (Dart d = Dart(this->topology_.begin()), end = Dart(this->topology_.end()); - d != end; - this->topology_.next(d.index)) + for (const_iterator it = this->begin(mask), end = this->end(mask); it != end; ++it) { - if (!dm.is_marked(d)) + if (!dm.is_marked(*it)) { - dm.template mark_orbit(d); - f(d); + dm.template mark_orbit(*it); + f(*it); } } } - template - inline void parallel_foreach_cell_dart_marking(const FUNC& f) const + template + inline void parallel_foreach_cell_dart_marking(const FUNC& f, const MASK& mask) const { using VecCell = std::vector>; - using Future = std::future< typename std::result_of, unsigned int)>::type >; + using Future = std::future< typename std::result_of, unsigned int)>::type>; ThreadPool* thread_pool = cgogn::get_thread_pool(); const std::size_t nb_threads_pool = thread_pool->get_nb_threads(); @@ -800,35 +923,36 @@ class MapBase : public MapBaseData Buffers* dbuffs = cgogn::get_dart_buffers(); DartMarker dm(*to_concrete()); - Dart it = Dart(this->topology_.begin()); - const Dart end = Dart(this->topology_.end()); + const_iterator it = this->begin(mask); + const const_iterator end = this->end(mask); while (it != end) { for (unsigned i = 0u; i < 2u; ++i) { - for (unsigned int j = 0u; j < nb_threads_pool && it != end ; ++j) + for (unsigned int j = 0u; j < nb_threads_pool && it != end; ++j) { cells_buffers[i].push_back(dbuffs->template get_cell_buffer>()); VecCell& cells = *cells_buffers[i].back(); cells.reserve(PARALLEL_BUFFER_SIZE); for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != end; ) { - if (!dm.is_marked(it)) + if (!dm.is_marked(*it)) { - dm.template mark_orbit(it); - cells.push_back(Cell(it)); + dm.template mark_orbit(*it); + cells.push_back(Cell(*it)); ++k; } - this->topology_.next(it.index); + ++it; } - futures[i].push_back(thread_pool->enqueue( [&cells,&f](unsigned int th_id){ + futures[i].push_back(thread_pool->enqueue([&cells, &f] (unsigned int th_id) + { for (auto c : cells) - f(c,th_id); + f(c, th_id); })); } - const unsigned int id = (i+1u)%2u; - for (auto& fu: futures[id]) + const unsigned int id = (i+1u) % 2u; + for (auto& fu : futures[id]) fu.wait(); for (auto &b : cells_buffers[id]) dbuffs->release_cell_buffer(b); @@ -839,7 +963,7 @@ class MapBase : public MapBaseData // if we reach the end of the map while filling buffers from the second set we need to clean them too. if (it == end && i == 1u) { - for (auto& fu: futures[1u]) + for (auto& fu : futures[1u]) fu.wait(); for (auto &b : cells_buffers[1u]) dbuffs->release_cell_buffer(b); @@ -848,27 +972,25 @@ class MapBase : public MapBaseData } } - template - inline void foreach_cell_cell_marking(const FUNC& f) const + template + inline void foreach_cell_cell_marking(const FUNC& f, const MASK& mask) const { CellMarker cm(*to_concrete()); - for (Dart d = Dart(this->topology_.begin()), end = Dart(this->topology_.end()); - d != end; - this->topology_.next(d.index)) + for (const_iterator it = this->begin(mask), end = this->end(mask); it != end; ++it) { - if (!cm.is_marked(d)) + if (!cm.is_marked(*it)) { - cm.mark(d); - f(d); + cm.mark(*it); + f(*it); } } } - template - inline void parallel_foreach_cell_cell_marking(const FUNC& f) const + template + inline void parallel_foreach_cell_cell_marking(const FUNC& f, const MASK& mask) const { using VecCell = std::vector>; - using Future = std::future< typename std::result_of, unsigned int)>::type >; + using Future = std::future, unsigned int)>::type>; ThreadPool* thread_pool = cgogn::get_thread_pool(); const std::size_t nb_threads_pool = thread_pool->get_nb_threads(); @@ -883,35 +1005,36 @@ class MapBase : public MapBaseData Buffers* dbuffs = cgogn::get_dart_buffers(); CellMarker cm(*to_concrete()); - Dart it = Dart(this->topology_.begin()); - const Dart end = Dart(this->topology_.end()); + const_iterator it = this->begin(mask); + const const_iterator end = this->end(mask); while (it != end) { for (unsigned i = 0u; i < 2u; ++i) { - for (unsigned int j = 0u; j < nb_threads_pool && it != end ; ++j) + for (unsigned int j = 0u; j < nb_threads_pool && it != end; ++j) { cells_buffers[i].push_back(dbuffs->template get_cell_buffer>()); VecCell& cells = *cells_buffers[i].back(); cells.reserve(PARALLEL_BUFFER_SIZE); for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != end; ) { - if (!cm.is_marked(it)) + if (!cm.is_marked(*it)) { - cm.mark(it); - cells.push_back(it); + cm.mark(*it); + cells.push_back(*it); ++k; } - this->topology_.next(it.index); + ++it; } - futures[i].push_back(thread_pool->enqueue( [&cells,&f](unsigned int th_id){ + futures[i].push_back(thread_pool->enqueue([&cells, &f] (unsigned int th_id) + { for (auto c : cells) - f(c,th_id); + f(c, th_id); })); } - const unsigned int id = (i+1u)%2u; - for (auto& fu: futures[id]) + const unsigned int id = (i+1u) % 2u; + for (auto& fu : futures[id]) fu.wait(); for (auto &b : cells_buffers[id]) dbuffs->release_cell_buffer(b); @@ -922,7 +1045,7 @@ class MapBase : public MapBaseData // if we reach the end of the map while filling buffers from the second set we need to clean them too. if (it == end && i == 1u) { - for (auto& fu: futures[1u]) + for (auto& fu : futures[1u]) fu.wait(); for (auto &b : cells_buffers[1u]) dbuffs->release_cell_buffer(b); @@ -931,22 +1054,39 @@ class MapBase : public MapBaseData } } - template - inline void foreach_cell_topo_cache(const FUNC& f) const + template + inline void foreach_cell_topo_cache(const FUNC& f, const MASK& mask) const { - for (unsigned int i = this->attributes_[ORBIT].begin(), end = this->attributes_[ORBIT].end(); - i != end; - this->attributes_[ORBIT].next(i)) + const auto& cache = *(this->global_topo_cache_[ORBIT]); + const auto& attr = this->attributes_[ORBIT]; + + unsigned int it = attr.begin(); + const unsigned int end = attr.end(); + Dart d = cache[it]; + // find first valid dart in the topo cache + while (it != end && !mask(d)) { - f((*this->global_topo_cache_[ORBIT])[i]); + attr.next(it); + d = cache[it]; + } + // apply function over valid darts of the cache + while (it != end) + { + f(d); + // next valid dart + do + { + attr.next(it); + d = cache[it]; + } while (it != end && !mask(d)); } } - template - inline void parallel_foreach_cell_topo_cache(const FUNC& f) const + template + inline void parallel_foreach_cell_topo_cache(const FUNC& f, const MASK& mask) const { using VecCell = std::vector>; - using Future = std::future< typename std::result_of, unsigned int)>::type >; + using Future = std::future, unsigned int)>::type>; ThreadPool* thread_pool = cgogn::get_thread_pool(); const std::size_t nb_threads_pool = thread_pool->get_nb_threads(); @@ -958,15 +1098,21 @@ class MapBase : public MapBaseData futures[0].reserve(nb_threads_pool); futures[1].reserve(nb_threads_pool); - Buffers* dbuffs = cgogn::get_dart_buffers(); - unsigned int it = this->attributes_[ORBIT].begin(); - const unsigned int end = this->attributes_[ORBIT].end(); - const auto& cache = *(this->global_topo_cache_[ORBIT]); const auto& attr = this->attributes_[ORBIT]; + unsigned int it = attr.begin(); + const unsigned int end = attr.end(); + Dart d = cache[it]; + // find first valid dart in the topo cache + while (it != end && !mask(d)) + { + attr.next(it); + d = cache[it]; + } + while (it != end) { for (unsigned i = 0u; i < 2u; ++i) @@ -979,15 +1125,20 @@ class MapBase : public MapBaseData for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != end; ++k) { cells.push_back(cache[it]); - attr.next(it); + do + { + attr.next(it); + d = cache[it]; + } while (it != end && !mask(d)); } - futures[i].push_back(thread_pool->enqueue( [&cells,&f](unsigned int th_id){ + futures[i].push_back(thread_pool->enqueue([&cells, &f] (unsigned int th_id) + { for (auto c : cells) - f(c,th_id); + f(c, th_id); })); } - const unsigned int id = (i+1u)%2u; - for (auto& fu: futures[id]) + const unsigned int id = (i+1u) % 2u; + for (auto& fu : futures[id]) fu.wait(); for (auto &b : cells_buffers[id]) dbuffs->release_cell_buffer(b); @@ -1007,49 +1158,62 @@ class MapBase : public MapBaseData } } - template - inline void foreach_cell_until_dart_marking(const FUNC& f) const + template + inline void foreach_cell_until_dart_marking(const FUNC& f, const MASK& mask) const { DartMarker dm(*to_concrete()); - for (Dart d = Dart(this->topology_.begin()), end = Dart(this->topology_.end()); - d != end; - this->topology_.next(d.index)) + for (const_iterator it = this->begin(mask), end = this->end(mask); it != end; ++it) { - if (!dm.is_marked(d)) + if (!dm.is_marked(*it)) { - dm.template mark_orbit(d); - if(!f(d)) + dm.template mark_orbit(*it); + if (!f(*it)) break; } } } - template - inline void foreach_cell_until_cell_marking(const FUNC& f) const + template + inline void foreach_cell_until_cell_marking(const FUNC& f, const MASK& mask) const { CellMarker cm(*to_concrete()); - for (Dart d = Dart(this->topology_.begin()), end = Dart(this->topology_.end()); - d != end; - this->topology_.next(d.index)) + for (const_iterator it = this->begin(mask), end = this->end(mask); it != end; ++it) { - if (!cm.is_marked(d)) + if (!cm.is_marked(*it)) { - cm.mark(d); - if(!f(d)) + cm.mark(*it); + if (!f(*it)) break; } } } - template - inline void foreach_cell_until_topo_cache(const FUNC& f) const + template + inline void foreach_cell_until_topo_cache(const FUNC& f, const MASK& mask) const { - for (unsigned int i = this->attributes_[ORBIT].begin(), end = this->attributes_[ORBIT].end(); - i != end; - this->attributes_[ORBIT].next(i)) + const auto& cache = *(this->global_topo_cache_[ORBIT]); + const auto& attr = this->attributes_[ORBIT]; + + unsigned int it = attr.begin(); + const unsigned int end = attr.end(); + Dart d = cache[it]; + // find first valid dart in the topo cache + while (it != end && !mask.valid(d)) { - if(!f((*this->global_topo_cache_[ORBIT])[i])) + attr.next(it); + d = cache[it]; + } + // apply function over valid darts of the cache + while (it != end) + { + if (!f(d)) break; + // next valid dart + do + { + attr.next(it); + d = cache[it]; + } while (it != end && !mask.valid(d)); } } }; diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index 89c41ec2..ee613c48 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -38,7 +38,7 @@ #include #include #include - +//#include #define CGOGN_CHECK_CONCRETE_TYPE cgogn_message_assert(typeid(*this).hash_code() == typeid(Self).hash_code(),\ std::string("dynamic type of current object : ") + cgogn::internal::demangle(std::string(typeid(*this).name())) + std::string(",\nwhereas Self = ") + cgogn::name_of_type(Self())) @@ -96,6 +96,7 @@ class MapBaseData : public MapGen static const unsigned int CHUNKSIZE = MAP_TRAITS::CHUNK_SIZE; static const unsigned int NB_UNKNOWN_THREADS = 4u; template friend class AttributeHandlerOrbit; + template friend class AttributeHandler; template using ChunkArrayContainer = cgogn::ChunkArrayContainer; @@ -105,7 +106,7 @@ class MapBaseData : public MapGen protected: - /// topology & embedding indices + // topology & embedding indices ChunkArrayContainer topology_; /// per orbit attributes @@ -114,9 +115,8 @@ class MapBaseData : public MapGen /// embedding indices shortcuts std::array*, NB_ORBITS> embeddings_; - /// boundary markers shortcuts - std::array*, 2> boundary_markers_; - // TODO: ?? store in a std::vector ? + /// boundary marker shortcut + ChunkArray* boundary_marker_; /// vector of available mark attributes per thread on the topology container std::vector*>> mark_attributes_topology_; @@ -160,8 +160,11 @@ class MapBaseData : public MapGen for (unsigned int i = 0; i < MAX_NB_THREADS; ++i) mark_attributes_topology_[i].reserve(8); + boundary_marker_ = topology_.add_marker_attribute(); + thread_ids_.reserve(NB_UNKNOWN_THREADS + 2u*MAX_NB_THREADS); thread_ids_.resize(NB_UNKNOWN_THREADS); + this->add_thread(std::this_thread::get_id()); const auto& pool_threads_ids = cgogn::get_thread_pool()->get_threads_ids(); for (const std::thread::id& ids : pool_threads_ids) @@ -273,6 +276,8 @@ class MapBaseData : public MapGen (*this->embeddings_[ORBIT])[d.index] = emb; // affect the embedding to the dart } +protected: + /******************************************************************************* * Thread management *******************************************************************************/ @@ -285,7 +290,7 @@ class MapBaseData : public MapGen std::cerr << "Data can be lost. Please use add_thread and remove_thread interface." << std::endl; thread_ids_[index] = th_id; const unsigned old_index = index; - index = (index+1u)% NB_UNKNOWN_THREADS; + index = (index+1u) % NB_UNKNOWN_THREADS; return old_index; } @@ -303,13 +308,13 @@ class MapBaseData : public MapGen inline std::size_t get_current_thread_index() const { // avoid the unknown threads stored at the beginning of the vector - auto real_begin =thread_ids_.begin(); + auto real_begin = thread_ids_.begin(); std::advance(real_begin, NB_UNKNOWN_THREADS); const auto end = thread_ids_.end(); auto it_lower_bound = std::lower_bound(real_begin, end, std::this_thread::get_id()); if (it_lower_bound != end) - return std::distance(thread_ids_.begin(),it_lower_bound); + return std::distance(thread_ids_.begin(), it_lower_bound); return get_unknown_thread_index(std::this_thread::get_id()); } @@ -317,12 +322,12 @@ class MapBaseData : public MapGen inline void remove_thread(std::thread::id thread_id) const { // avoid the unknown threads stored at the beginning of the vector - auto real_begin =thread_ids_.begin(); + auto real_begin = thread_ids_.begin(); std::advance(real_begin, NB_UNKNOWN_THREADS); - cgogn_message_assert(std::binary_search(real_begin, thread_ids_.end(), thread_id),"Unable to find the thread."); - auto it = std::lower_bound(real_begin, thread_ids_.end(),thread_id); - cgogn_message_assert((*it) == thread_id,"Unable to find the thread."); + cgogn_message_assert(std::binary_search(real_begin, thread_ids_.end(), thread_id), "Unable to find the thread."); + auto it = std::lower_bound(real_begin, thread_ids_.end(), thread_id); + cgogn_message_assert(*it == thread_id, "Unable to find the thread."); thread_ids_.erase(it); } @@ -332,12 +337,9 @@ class MapBaseData : public MapGen auto real_begin =thread_ids_.begin(); std::advance(real_begin, NB_UNKNOWN_THREADS); - auto it = std::lower_bound(real_begin, thread_ids_.end(),thread_id); - if ((it == thread_ids_.end()) || (*it != thread_id)) - { - thread_ids_.insert(it,thread_id); - } - + auto it = std::lower_bound(real_begin, thread_ids_.end(), thread_id); + if (it == thread_ids_.end() || *it != thread_id) + thread_ids_.insert(it, thread_id); } }; diff --git a/cgogn/core/cmap/sanity_check.h b/cgogn/core/cmap/sanity_check.h index cbb7f9b1..20b40057 100644 --- a/cgogn/core/cmap/sanity_check.h +++ b/cgogn/core/cmap/sanity_check.h @@ -24,6 +24,8 @@ #ifndef CORE_CMAP_SANITY_CHECK_H_ #define CORE_CMAP_SANITY_CHECK_H_ +#include + namespace cgogn { @@ -39,10 +41,10 @@ template bool is_well_embedded(const MAP& map) { bool result = true; - map.template foreach_cell([&] (Cell c) - { - result = map.template is_well_embedded(c); - }); + map.template foreach_cell( + [&] (Cell c) { result = map.template is_well_embedded(c); }, + [] (Dart) { return true; } + ); return result; } @@ -101,7 +103,10 @@ bool is_container_well_referenced(MAP& map) counter[i] = 0; // for each dart of the map, the counter corresponding to its embedding index is incremented - map.foreach_dart([&] (Dart d) { counter[map.template get_embedding(d)]++; }); + map.foreach_dart( + [&] (Dart d) { counter[map.template get_embedding(d)]++; }, + [] (Dart) { return true; } + ); bool result = true; for (unsigned int i = container.begin(), end = container.end(); i != end; container.next(i)) diff --git a/cgogn/core/examples/map/map.cpp b/cgogn/core/examples/map/map.cpp index a2dd0851..535e4797 100644 --- a/cgogn/core/examples/map/map.cpp +++ b/cgogn/core/examples/map/map.cpp @@ -93,10 +93,7 @@ int test1(MAP& map) dm.mark(d1); std::cout << "Darts :" << std::endl; - for (Dart dit : map) - { - std::cout << dit << std::endl; - } + map.foreach_dart([] (Dart d) { std::cout << d << std::endl; }); std::cout << "End Darts" << std::endl; std::cout << "Vertices :" << std::endl; diff --git a/cgogn/geometry/tests/algos/algos_test.cpp b/cgogn/geometry/tests/algos/algos_test.cpp index 029d96fa..a8a06647 100644 --- a/cgogn/geometry/tests/algos/algos_test.cpp +++ b/cgogn/geometry/tests/algos/algos_test.cpp @@ -40,6 +40,7 @@ using StdArray = cgogn::geometry::Vec_T>; using EigenVec3d = Eigen::Vector3d; using CMap2 = cgogn::CMap2; +using Dart = cgogn::Dart; template using VertexAttributeHandler = CMap2::VertexAttributeHandler; @@ -49,8 +50,10 @@ TEST(Algos_TEST, TriangleArea) CMap2 map; cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); VertexAttributeHandler vertex_position = map.get_attribute("position"); - const double area = cgogn::geometry::triangle_area(map, *map.begin(), vertex_position); - const double cf_area = cgogn::geometry::convex_face_area(map, *map.begin(), vertex_position); + Dart t; + map.foreach_dart_until([&t] (Dart d) { t = d; return false; }); + const double area = cgogn::geometry::triangle_area(map, t, vertex_position); + const double cf_area = cgogn::geometry::convex_face_area(map, t, vertex_position); EXPECT_DOUBLE_EQ(area, 12.5); EXPECT_DOUBLE_EQ(cf_area, 12.5); } @@ -58,8 +61,10 @@ TEST(Algos_TEST, TriangleArea) CMap2 map; cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); VertexAttributeHandler vertex_position = map.get_attribute("position"); - const double area = cgogn::geometry::triangle_area(map, *map.begin(), vertex_position); - const double cf_area = cgogn::geometry::convex_face_area(map, *map.begin(), vertex_position); + Dart t; + map.foreach_dart_until([&t] (Dart d) { t = d; return false; }); + const double area = cgogn::geometry::triangle_area(map, t, vertex_position); + const double cf_area = cgogn::geometry::convex_face_area(map, t, vertex_position); EXPECT_DOUBLE_EQ(area, 12.5); EXPECT_DOUBLE_EQ(cf_area, 12.5); } @@ -71,16 +76,19 @@ TEST(Algos_TEST, QuadArea) CMap2 map; cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); VertexAttributeHandler vertex_position = map.get_attribute("position"); - const double area = cgogn::geometry::convex_face_area(map, *map.begin(), vertex_position); + Dart q; + map.foreach_dart_until([&q] (Dart d) { q = d; return false; }); + const double area = cgogn::geometry::convex_face_area(map, q, vertex_position); EXPECT_DOUBLE_EQ(area, 10); } { CMap2 map; cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); VertexAttributeHandler vertex_position = map.get_attribute("position"); - const double area = cgogn::geometry::convex_face_area(map, *map.begin(), vertex_position); + Dart q; + map.foreach_dart_until([&q] (Dart d) { q = d; return false; }); + const double area = cgogn::geometry::convex_face_area(map, q, vertex_position); EXPECT_DOUBLE_EQ(area, 10); - } } @@ -90,7 +98,9 @@ TEST(Algos_TEST, TriangleCentroid) CMap2 map; cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); VertexAttributeHandler vertex_position = map.get_attribute("position"); - const StdArray centroid = cgogn::geometry::centroid(map, cgogn::Cell(*map.begin()), vertex_position); + Dart t; + map.foreach_dart_until([&t] (Dart d) { t = d; return false; }); + const StdArray centroid = cgogn::geometry::centroid(map, cgogn::Cell(t), vertex_position); EXPECT_DOUBLE_EQ(centroid[0], 5.0/3.0); EXPECT_DOUBLE_EQ(centroid[1], 5.0/3.0); EXPECT_DOUBLE_EQ(centroid[2], 0); @@ -100,7 +110,9 @@ TEST(Algos_TEST, TriangleCentroid) CMap2 map; cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); VertexAttributeHandler vertex_position = map.get_attribute("position"); - const EigenVec3d centroid = cgogn::geometry::centroid(map, cgogn::Cell(*map.begin()), vertex_position); + Dart t; + map.foreach_dart_until([&t] (Dart d) { t = d; return false; }); + const EigenVec3d centroid = cgogn::geometry::centroid(map, cgogn::Cell(t), vertex_position); EXPECT_DOUBLE_EQ(centroid[0], 5.0/3.0); EXPECT_DOUBLE_EQ(centroid[1], 5.0/3.0); EXPECT_DOUBLE_EQ(centroid[2], 0); @@ -113,7 +125,9 @@ TEST(Algos_TEST, QuadCentroid) CMap2 map; cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); VertexAttributeHandler vertex_position = map.get_attribute("position"); - const StdArray centroid = cgogn::geometry::centroid(map, cgogn::Cell(*map.begin()), vertex_position); + Dart q; + map.foreach_dart_until([&q] (Dart d) { q = d; return false; }); + const StdArray centroid = cgogn::geometry::centroid(map, cgogn::Cell(q), vertex_position); EXPECT_DOUBLE_EQ(centroid[0], 2.5); EXPECT_DOUBLE_EQ(centroid[1], 1); EXPECT_DOUBLE_EQ(centroid[2], 0); @@ -123,7 +137,9 @@ TEST(Algos_TEST, QuadCentroid) CMap2 map; cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); VertexAttributeHandler vertex_position = map.get_attribute("position"); - const EigenVec3d centroid = cgogn::geometry::centroid(map, cgogn::Cell(*map.begin()), vertex_position); + Dart q; + map.foreach_dart_until([&q] (Dart d) { q = d; return false; }); + const EigenVec3d centroid = cgogn::geometry::centroid(map, cgogn::Cell(q), vertex_position); EXPECT_DOUBLE_EQ(centroid[0], 2.5); EXPECT_DOUBLE_EQ(centroid[1], 1); EXPECT_DOUBLE_EQ(centroid[2], 0); @@ -136,12 +152,13 @@ TEST(Algos_TEST, TriangleNormal) CMap2 map; cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); VertexAttributeHandler vertex_position = map.get_attribute("position"); - const StdArray& n1 = cgogn::geometry::triangle_normal(map, cgogn::Cell(*map.begin()), vertex_position); - const StdArray& n2 = cgogn::geometry::face_normal(map, cgogn::Cell(*map.begin()), vertex_position); + Dart t; + map.foreach_dart_until([&t] (Dart d) { t = d; return false; }); + const StdArray& n1 = cgogn::geometry::triangle_normal(map, cgogn::Cell(t), vertex_position); + const StdArray& n2 = cgogn::geometry::face_normal(map, cgogn::Cell(t), vertex_position); EXPECT_TRUE(cgogn::almost_equal_relative(n1[0], n2[0])); EXPECT_TRUE(cgogn::almost_equal_relative(n1[1], n2[1])); EXPECT_TRUE(cgogn::almost_equal_relative(n1[2], n2[2])); - const StdArray& cross = n1.cross(StdArray(0.,0.,1.)); EXPECT_TRUE(cgogn::almost_equal_relative(cross[0], 0.)); EXPECT_TRUE(cgogn::almost_equal_relative(cross[1], 0.)); @@ -151,12 +168,13 @@ TEST(Algos_TEST, TriangleNormal) CMap2 map; cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); VertexAttributeHandler vertex_position = map.get_attribute("position"); - const EigenVec3d& n1 = cgogn::geometry::triangle_normal(map, cgogn::Cell(*map.begin()), vertex_position); - const EigenVec3d& n2 = cgogn::geometry::face_normal(map, cgogn::Cell(*map.begin()), vertex_position); + Dart t; + map.foreach_dart_until([&t] (Dart d) { t = d; return false; }); + const EigenVec3d& n1 = cgogn::geometry::triangle_normal(map, cgogn::Cell(t), vertex_position); + const EigenVec3d& n2 = cgogn::geometry::face_normal(map, cgogn::Cell(t), vertex_position); EXPECT_TRUE(cgogn::almost_equal_relative(n1[0], n2[0])); EXPECT_TRUE(cgogn::almost_equal_relative(n1[1], n2[1])); EXPECT_TRUE(cgogn::almost_equal_relative(n1[2], n2[2])); - const EigenVec3d& cross = n1.cross(EigenVec3d(0,0,1)); EXPECT_TRUE(cgogn::almost_equal_relative(cross[0], 0.)); EXPECT_TRUE(cgogn::almost_equal_relative(cross[1], 0.)); @@ -170,7 +188,9 @@ TEST(Algos_TEST, QuadNormal) CMap2 map; cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); VertexAttributeHandler vertex_position = map.get_attribute("position"); - const StdArray& n1 = cgogn::geometry::face_normal(map, cgogn::Cell(*map.begin()), vertex_position); + Dart q; + map.foreach_dart_until([&q] (Dart d) { q = d; return false; }); + const StdArray& n1 = cgogn::geometry::face_normal(map, cgogn::Cell(q), vertex_position); const StdArray& cross = n1.cross(StdArray(0.,0.,1.)); EXPECT_TRUE(cgogn::almost_equal_relative(cross[0], 0.)); EXPECT_TRUE(cgogn::almost_equal_relative(cross[1], 0.)); @@ -180,7 +200,9 @@ TEST(Algos_TEST, QuadNormal) CMap2 map; cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); VertexAttributeHandler vertex_position = map.get_attribute("position"); - const EigenVec3d& n1 = cgogn::geometry::triangle_normal(map, cgogn::Cell(*map.begin()), vertex_position); + Dart q; + map.foreach_dart_until([&q] (Dart d) { q = d; return false; }); + const EigenVec3d& n1 = cgogn::geometry::triangle_normal(map, cgogn::Cell(q), vertex_position); const EigenVec3d& cross = n1.cross(EigenVec3d(0,0,1)); EXPECT_TRUE(cgogn::almost_equal_relative(cross[0], 0.)); EXPECT_TRUE(cgogn::almost_equal_relative(cross[1], 0.)); diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index f201161f..1892bb19 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -207,7 +207,7 @@ class SurfaceImport bool need_vertex_unicity_check = false; unsigned int nb_boundary_edges = 0; - for (Dart d : map) + map.foreach_dart([&] (Dart d) { if (map.phi2(d) == d) { @@ -241,7 +241,7 @@ class SurfaceImport if (!first_OK) need_vertex_unicity_check = true; } - } + }); if (nb_boundary_edges > 0) mbuild.close_map(); diff --git a/cgogn/io/volume_import.h b/cgogn/io/volume_import.h index c5bb3e89..b63e819d 100644 --- a/cgogn/io/volume_import.h +++ b/cgogn/io/volume_import.h @@ -288,7 +288,7 @@ class VolumeImport //reconstruct neighbourhood unsigned int nbBoundaryFaces = 0; - for (Dart d : map) + map.foreach_dart([&] (Dart d) { if (m.is_marked(d)) { @@ -331,7 +331,7 @@ class VolumeImport ++nbBoundaryFaces; } } - } + }); if (nbBoundaryFaces > 0) { From 4d1bcb8c015cd49f85d38c6914f74e1abcda49f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Fri, 12 Feb 2016 15:41:04 +0100 Subject: [PATCH 094/402] Removed useless orbits of cmap0 and removed an extra "to_concrete()" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/cmap0.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index a3cf8199..e61b0ffd 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -47,14 +47,8 @@ class CMap0_T : public MapBase static const Orbit DART = Orbit::DART; static const Orbit VERTEX = Orbit::DART; - static const Orbit EDGE = Orbit::DART; - static const Orbit FACE = Orbit::DART; - static const Orbit VOLUME = Orbit::DART; typedef Cell Vertex; - typedef Cell Edge; - typedef Cell Face; - typedef Cell Volume; template using ChunkArray = typename Inherit::template ChunkArray; @@ -95,7 +89,7 @@ class CMap0_T : public MapBase public: Vertex add_vertex() { - const Vertex v(this->to_concrete()->add_dart()); + const Vertex v(this->add_dart()); if (this->template is_orbit_embedded()) this->template set_embedding(v.dart, this->template add_attribute_element()); From 82a15fecc23ad9a595d6693b0def66c3a27de364 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Fri, 12 Feb 2016 15:41:40 +0100 Subject: [PATCH 095/402] delete_dart() method is now part of map_base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/cmap1.h | 5 ----- cgogn/core/cmap/map_base.h | 5 +++++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index b495b1e1..974d6e58 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -183,11 +183,6 @@ class CMap1_T : public MapBase return d; } - inline void delete_dart(Dart d) - { - this->remove_topology_element(d.index); - } - /******************************************************************************* * High-level topological operations *******************************************************************************/ diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index fc7b7344..2c5bb77a 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -141,6 +141,11 @@ class MapBase : public MapBaseData return this->to_concrete()->add_dart_internal(); } + inline void delete_dart(Dart d) + { + this->remove_topology_element(d.index); + } + /******************************************************************************* * Container elements management *******************************************************************************/ From e2b1cfc2912e4296e28f43cec1ffccb8e5e5e75e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Fri, 12 Feb 2016 15:42:18 +0100 Subject: [PATCH 096/402] CGOGN_CHECK_CONCRETE_TYPE improved. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/cmap1.h | 9 +++++---- cgogn/core/cmap/cmap2.h | 6 ++++++ cgogn/core/cmap/cmap3.h | 1 + cgogn/core/cmap/map_base_data.h | 4 +++- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 974d6e58..acc792db 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -206,11 +206,11 @@ class CMap1_T : public MapBase while(e != d) { Dart f = phi1(e); - delete_dart(e); + this->delete_dart(e); e = f; } - delete_dart(d); + this->delete_dart(d); } /** @@ -231,7 +231,7 @@ class CMap1_T : public MapBase // Dart d is linked to the successor of its successor phi1_unsew(d); // Dart d1 is erased - delete_dart(d1); + this->delete_dart(d1); } inline void collapse_edge_topo(Dart d) @@ -239,7 +239,7 @@ class CMap1_T : public MapBase // Dart before d is linked to its successor phi1_unsew(phi_1(d)); // Dart d is erased - delete_dart(d); + this->delete_dart(d); } inline void split_face_topo(Dart d, Dart e) @@ -302,6 +302,7 @@ class CMap1_T : public MapBase */ Face add_face(unsigned int nb_edges) { + CGOGN_CHECK_CONCRETE_TYPE; cgogn_message_assert(nb_edges > 0, "Cannot create a face with no edge"); const Face f(this->add_face_topo(nb_edges)); diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 86cc3fa0..481546ca 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -174,6 +174,8 @@ class CMap2_T : public CMap1_T */ void close_map() { + CGOGN_CHECK_CONCRETE_TYPE; + for (Dart d : *this) { if (phi2(d) == d) @@ -226,6 +228,7 @@ class CMap2_T : public CMap1_T Face add_face(unsigned int nb_edges) { + CGOGN_CHECK_CONCRETE_TYPE; cgogn_message_assert(nb_edges > 0, "Cannot create a face with no edge"); Dart d = Inherit::add_face_topo(nb_edges); @@ -275,6 +278,8 @@ class CMap2_T : public CMap1_T inline Vertex cut_edge(Edge d) { + CGOGN_CHECK_CONCRETE_TYPE; + const Dart e = phi2(d); const Dart nd = cut_edge_topo(d); const Dart ne = phi2(d); @@ -315,6 +320,7 @@ class CMap2_T : public CMap1_T inline void split_face(Dart d, Dart e) { + CGOGN_CHECK_CONCRETE_TYPE; split_face_topo(d,e); const Dart nd = this->phi_1(e); const Dart ne = this->phi_1(d); diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 0215fa96..1e0dd450 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -281,6 +281,7 @@ class CMap3_T : public CMap2_T */ inline unsigned int close_map() { + CGOGN_CHECK_CONCRETE_TYPE; // Search the map for topological holes (fix points of phi3) unsigned int nb = 0u; for (Dart d: (*this)) diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index 89c41ec2..fe6d000e 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -40,9 +40,11 @@ #include -#define CGOGN_CHECK_CONCRETE_TYPE cgogn_message_assert(typeid(*this).hash_code() == typeid(Self).hash_code(),\ +#define CGOGN_CHECK_CONCRETE_TYPE static_assert(std::is_same::value,"The concrete map type has to be equal to Self") +#define CGOGN_CHECK_DYNAMIC_TYPE cgogn_message_assert(typeid(*this).hash_code() == typeid(Self).hash_code(),\ std::string("dynamic type of current object : ") + cgogn::internal::demangle(std::string(typeid(*this).name())) + std::string(",\nwhereas Self = ") + cgogn::name_of_type(Self())) + namespace cgogn { From 30c364ceb849652a28b5f9b0dfe538e899cedd56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Fri, 12 Feb 2016 15:47:01 +0100 Subject: [PATCH 097/402] cph map were calling the wrong embedded version of cut_edge and split_face. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/multiresolution/cph/ihcmap2_adaptive.h | 32 ++++++++++---------- cgogn/multiresolution/examples/cph/cph2.cpp | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/cgogn/multiresolution/cph/ihcmap2_adaptive.h b/cgogn/multiresolution/cph/ihcmap2_adaptive.h index 650e790d..2e5506d0 100644 --- a/cgogn/multiresolution/cph/ihcmap2_adaptive.h +++ b/cgogn/multiresolution/cph/ihcmap2_adaptive.h @@ -217,12 +217,12 @@ class IHCMap2Adaptive : IHCMap2 Dart d2 = Inherit::phi2(d) ; unsigned int cur = Inherit::get_current_level(); Inherit::set_current_level(cur + 1); - if(Inherit::vertexDegree(Inherit::phi1(d)) == 2) - { - degree2 = true ; - if(edge_is_subdivided(d) || edge_is_subdivided(d2)) - subdOnce = false ; - } +// if(Inherit::vertexDegree(Inherit::phi1(d)) == 2) +// { +// degree2 = true ; +// if(edge_is_subdivided(d) || edge_is_subdivided(d2)) +// subdOnce = false ; +// } Inherit::set_current_level(cur); } @@ -335,7 +335,7 @@ class IHCMap2Adaptive : IHCMap2 Inherit::set_current_level(eLevel + 1); - Inherit::cut_edge(d); + this->cut_edge_topo(d);// previously : Inherit::cut_edge(d); TODO : write cut_edge for ihcmap2 unsigned int eId = Inherit::get_edge_id(d); Inherit::set_edge_id(Inherit::phi1(d), eId); Inherit::set_edge_id(Inherit::phi1(dd), eId); @@ -369,7 +369,7 @@ class IHCMap2Adaptive : IHCMap2 // unsigned int dl = Inherit::get_dart_level(e); // Inherit::set_dart_level(Inherit::phi1(e), dl); // Inherit::collapseEdge(e); - Inherit::uncut_edge(d); +// Inherit::uncut_edge(d); Inherit::set_current_level(cur); } @@ -416,7 +416,7 @@ class IHCMap2Adaptive : IHCMap2 // (*vertexVertexFunctor)(e) ; e = Inherit::phi1(e); - Inherit::split_face(dd, e); + this->split_face_topo(dd,e); // previously Inherit::split_face(dd, e); TODO : write split_face for ihcmap2 unsigned int id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id); // set the edge id of the inserted @@ -426,7 +426,7 @@ class IHCMap2Adaptive : IHCMap2 e = Inherit::phi1(dd); // (*vertexVertexFunctor)(e); e = Inherit::phi1(e); - Inherit::split_face(dd, e); + this->split_face_topo(dd,e); // previously : Inherit::split_face(dd, e); TODO : write split_face for ihcmap2 id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id); Inherit::set_edge_id(Inherit::phi_1(e), id); @@ -435,7 +435,7 @@ class IHCMap2Adaptive : IHCMap2 e = Inherit::phi1(dd); // (*vertexVertexFunctor)(e); e = Inherit::phi1(e); - Inherit::split_face(dd, e); + this->split_face_topo(dd,e);// previously : Inherit::split_face(dd, e); TODO : write split_face for ihcmap2 id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id); Inherit::set_edge_id(Inherit::phi_1(e), id); @@ -446,10 +446,10 @@ class IHCMap2Adaptive : IHCMap2 Dart next = this->phi1(dd); // (*vertexVertexFunctor)(next); next = Inherit::phi1(next); - Inherit::split_face(dd, next); // insert a first edge + this->split_face_topo(dd,next);// previously : Inherit::split_face(dd, next); TODO : write split_face for ihcmap2 // insert a first edge Dart ne = Inherit::phi2(Inherit::phi_1(dd)); Dart ne2 = Inherit::phi2(ne); - Inherit::cut_edge(ne); // cut the new edge to insert the central vertex + this->cut_edge_topo(ne);// previously : Inherit::cut_edge(ne); TODO : write cut_edge for ihcmap2// cut the new edge to insert the central vertex unsigned int id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(ne))); Inherit::set_edge_id(ne, id); @@ -465,7 +465,7 @@ class IHCMap2Adaptive : IHCMap2 dd = Inherit::phi1(dd); while(dd != ne) // turn around the face and insert new edges { // linked to the central vertex - Inherit::split_face(Inherit::phi1(ne), dd); + this->split_face_topo(Inherit::phi1(ne), dd);// previously : Inherit::split_face(Inherit::phi1(ne), dd); TODO : write split_face for ihcmap2 Dart nne = Inherit::phi2(Inherit::phi_1(dd)); id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(nne))); @@ -512,7 +512,7 @@ class IHCMap2Adaptive : IHCMap2 Inherit::set_current_level(cur + 1); Dart innerEdge = Inherit::phi1(fit); Inherit::set_current_level(Inherit::get_maximum_level()); - Inherit::merge_faces(innerEdge); +// Inherit::merge_faces(innerEdge); Inherit::set_current_level(cur); fit = this->phi1(fit); } while(fit != d); @@ -522,7 +522,7 @@ class IHCMap2Adaptive : IHCMap2 Inherit::set_current_level(cur + 1); Dart centralV = Inherit::phi1(Inherit::phi1(d)); Inherit::set_current_level(Inherit::get_maximum_level()); - Inherit::delete_vertex(centralV); +// Inherit::delete_vertex(centralV); Inherit::set_current_level(cur); } diff --git a/cgogn/multiresolution/examples/cph/cph2.cpp b/cgogn/multiresolution/examples/cph/cph2.cpp index df4ea084..6194f924 100644 --- a/cgogn/multiresolution/examples/cph/cph2.cpp +++ b/cgogn/multiresolution/examples/cph/cph2.cpp @@ -23,7 +23,7 @@ int main() LerpTriQuadMRAnalysis lerp(map, position); - map.add_face(4); +// map.add_face(4); // TODO : write add_face for IHMap2 ! std::cout << "before add level Faces :" << std::endl; map.template foreach_cell([&] (IHMap2::Face v) From e97834aa954c1be311d0202c91313ea0c9b8f926 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Fri, 12 Feb 2016 16:14:59 +0100 Subject: [PATCH 098/402] =?UTF-8?q?Nettoyage=20de=20CMap1,=20op=C3=A9rateu?= =?UTF-8?q?rs=201D=20et=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cgogn/core/cmap/cmap1.h | 103 ++++++++---------- cgogn/core/cmap/cmap2.h | 40 ++++--- cgogn/core/tests/CMakeLists.txt | 1 + cgogn/core/tests/cmap/cmap1_test.cpp | 101 ++++------------- cgogn/core/tests/cmap/cmap1_topo_test.cpp | 107 +++++++++++++++++++ cgogn/multiresolution/cph/ihcmap2_adaptive.h | 2 +- 6 files changed, 195 insertions(+), 159 deletions(-) create mode 100644 cgogn/core/tests/cmap/cmap1_topo_test.cpp diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 44730aa5..fcf856d0 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -46,7 +46,6 @@ class CMap1_T : public MapBase friend typename Self::Inherit; friend class DartMarker_T; - static const Orbit DART = Orbit::DART; static const Orbit VERTEX = Orbit::DART; static const Orbit EDGE = Orbit::DART; static const Orbit FACE = Orbit::PHI1; @@ -86,10 +85,27 @@ class CMap1_T : public MapBase phi_1_ = this->topology_.template add_attribute("phi_1"); } +public: + + CMap1_T() : Inherit() + { + init(); + } + + virtual ~CMap1_T() override + {} + + CMap1_T(Self const&) = delete; + CMap1_T(Self &&) = delete; + Self& operator=(Self const&) = delete; + Self& operator=(Self &&) = delete; + /******************************************************************************* * Low-level topological operations *******************************************************************************/ +protected: + /** * \brief Link the current dart to dart d with a permutation * @param d the dart to which the current is linked @@ -126,25 +142,12 @@ class CMap1_T : public MapBase (*phi_1_)[e.index] = e; } -public: - - CMap1_T() : Inherit() - { - init(); - } - - virtual ~CMap1_T() override - {} - - CMap1_T(Self const&) = delete; - CMap1_T(Self &&) = delete; - Self& operator=(Self const&) = delete; - Self& operator=(Self &&) = delete; - /******************************************************************************* * Basic topological operations *******************************************************************************/ +public: + /** * \brief phi1 * @param d @@ -181,7 +184,7 @@ class CMap1_T : public MapBase return d; } - inline void delete_dart(Dart d) + inline void remove_dart(Dart d) { this->remove_topology_element(d.index); } @@ -203,17 +206,17 @@ class CMap1_T : public MapBase return d; } - inline void delete_face_topo(Dart d) + inline void remove_face_topo(Dart d) { Dart e = phi1(d); while(e != d) { Dart f = phi1(e); - delete_dart(e); + remove_dart(e); e = f; } - delete_dart(d); + remove_dart(d); } /** @@ -228,43 +231,17 @@ class CMap1_T : public MapBase return e; } - inline void uncut_edge_topo(Dart d) - { - Dart d1 = phi1(d); - // Dart d is linked to the successor of its successor - phi1_unsew(d); - // Dart d1 is erased - delete_dart(d1); - } - + /** + * \brief remove edge d from its face and delete it + * @param d : the edge to collapse + * the edge preceeding d in the face is linked to the successor of d + */ inline void collapse_edge_topo(Dart d) { - // Dart before d is linked to its successor - phi1_unsew(phi_1(d)); - // Dart d is erased - delete_dart(d); - } - - inline void split_face_topo(Dart d, Dart e) - { - cgogn_assert(d != e && this->same_cell(Face(d), Face(e))); - phi1_sew(phi_1(d), phi_1(e)); - } - - inline void merge_faces_topo(Dart d, Dart e) - { - cgogn_assert(!this->same_cell(Face(d), Face(e))); - phi1_sew(phi_1(d), phi_1(e)); - } - - inline void link_faces_topo(Dart d, Dart e) - { - cgogn_assert(d != e && !this->same_cell(Face(d), Face(e))); - - Dart nd = cut_edge_topo(phi_1(d)); // cut the edge before d (insert a new dart before d) - Dart ne = cut_edge_topo(phi_1(e)); // cut the edge before e (insert a new dart before e) - - phi1_sew(nd, ne); // subdivide phi1 cycle at the inserted darts + Dart e = phi_1(d); + cgogn_message_assert(e != d,"phi1_unsew: Cannot collapse fixed point"); + phi1_unsew(e); + remove_dart(d); } inline void reverse_face_topo(Dart d) @@ -296,6 +273,10 @@ class CMap1_T : public MapBase phi1_sew(e, d); } + /******************************************************************************* + * High-level embedded operations + *******************************************************************************/ + public: /** @@ -309,16 +290,16 @@ class CMap1_T : public MapBase const Face f(this->add_face_topo(nb_edges)); - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) { foreach_dart_of_orbit(f, [this](Dart d) { - this->template set_orbit_embedding(d, this->template add_attribute_element()); + this->template set_orbit_embedding(d, this->template add_attribute_element()); }); } - if (this->template is_orbit_embedded()) - this->set_orbit_embedding(f, this->template add_attribute_element()); + if (this->template is_orbit_embedded()) + this->set_orbit_embedding(f, this->template add_attribute_element()); return f; } @@ -416,14 +397,14 @@ class CMap1_T : public MapBase inline void foreach_incident_vertex(Face f, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); - foreach_dart_of_orbit(f, func); + foreach_dart_of_orbit(f, func); } template inline void foreach_incident_edge(Face f, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); - foreach_dart_of_orbit(f, func); + foreach_dart_of_orbit(f, func); } /******************************************************************************* diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index dfdca391..8a648ab8 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -311,11 +311,24 @@ class CMap2_T : public CMap1_T return v; } + /** + * @brief Split the face of d and e by inserting an edge between the vertex of d and e + * @param d : first vertex + * @param e : second vertex + * Darts d and e should belong to the same face and be distinct from each other. + * An edge made of two new darts is inserted between the two given vertices. + */ inline void split_face(Dart d, Dart e) { - split_face_topo(d,e); - const Dart nd = this->phi_1(e); - const Dart ne = this->phi_1(d); + cgogn_message_assert(d != e, "split_face: d and e should be distinct"); + cgogn_message_assert(this->same_cell(Face(d), Face(e)), "split_face: d and e should belong to the same face"); + + Dart dd = this->phi_1(d); + Dart ee = this->phi_1(e); + Dart nd = Inherit::cut_edge_topo(dd); // cut the edge before d (insert a new dart before d) + Dart ne = Inherit::cut_edge_topo(ee); // cut the edge before e (insert a new dart before e) + this->phi1_sew(dd, ee); // subdivide phi1 cycle at the inserted darts + phi2_sew(nd, ne); // build the new 2D-edge from the inserted darts if(this->template is_orbit_embedded()) { @@ -325,8 +338,8 @@ class CMap2_T : public CMap1_T if (this->template is_orbit_embedded()) { - this->template set_embedding(nd, this->template get_embedding(d)); - this->template set_embedding(ne, this->template get_embedding(e)); + this->template set_embedding(nd, this->template get_embedding(e)); + this->template set_embedding(ne, this->template get_embedding(d)); } if (this->template is_orbit_embedded()) @@ -353,6 +366,11 @@ class CMap2_T : public CMap1_T return Inherit::degree(f); } + inline unsigned int degree(Vertex v) const + { + return this->nb_darts(v); + } + protected: inline Dart cut_edge_topo(Dart d) @@ -370,18 +388,6 @@ class CMap2_T : public CMap1_T return nd; } - inline void split_face_topo(Dart d, Dart e) - { - cgogn_message_assert(d != e, "split_face: d and e should be distinct"); - cgogn_message_assert(this->same_cell(Face(d), Face(e)), "split_face: d and e should belong to the same face"); - - Dart nd = Inherit::cut_edge_topo(this->phi_1(d)); // cut the edge before d (insert a new dart before d) - Dart ne = Inherit::cut_edge_topo(this->phi_1(e)); // cut the edge before e (insert a new dart before e) - - Inherit::split_face_topo(nd, ne); // subdivide phi1 cycle at the inserted darts - phi2_sew(nd, ne); // build the new 2D-edge from the inserted darts - } - inline void close_hole_topo(Dart d) { cgogn_message_assert(phi2(d) == d, "CMap2: close hole called on a dart that is not a phi2 fix point"); diff --git a/cgogn/core/tests/CMakeLists.txt b/cgogn/core/tests/CMakeLists.txt index 9ed41f4e..a47001c0 100644 --- a/cgogn/core/tests/CMakeLists.txt +++ b/cgogn/core/tests/CMakeLists.txt @@ -6,6 +6,7 @@ set(SOURCE_FILES basic/dart_test.cpp basic/cell_test.cpp container/chunk_array_container_test.cpp + cmap/cmap1_topo_test.cpp cmap/cmap1_test.cpp utils/name_types_test.cpp diff --git a/cgogn/core/tests/cmap/cmap1_test.cpp b/cgogn/core/tests/cmap/cmap1_test.cpp index 7c2c13e6..b6fafd2f 100644 --- a/cgogn/core/tests/cmap/cmap1_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_test.cpp @@ -1,106 +1,47 @@ -/******************************************************************************* -* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * -* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * -* * -* This library is free software; you can redistribute it and/or modify it * -* under the terms of the GNU Lesser General Public License as published by the * -* Free Software Foundation; either version 2.1 of the License, or (at your * -* option) any later version. * -* * -* This library is distributed in the hope that it will be useful, but WITHOUT * -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * -* for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with this library; if not, write to the Free Software Foundation, * -* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * -* * -* Web site: http://cgogn.unistra.fr/ * -* Contact information: cgogn@unistra.fr * -* * -*******************************************************************************/ - #include #include #include +#include +#include namespace cgogn { - -// class CMap1TopoMock : public CMap1 { -// public: -// MOCK_METHOD0( add_dart, Dart() ); -// MOCK_METHOD1( cut_edge_topo, Dart(Dart d) ); -// MOCK_METHOD1( add_face_topo, Dart(unsigned int nb_edges) ); -// }; - -class CMap1TopoTest: public CMap1, public ::testing::Test +class CMap1Test: public ::testing::Test { - using CMap1 = cgogn::CMap1; - public: - CMap1 cmap_; - Dart d_; + typedef CMap1 myCMap1; + typedef myCMap1::Vertex Vertex; + typedef myCMap1::Edge Edge; + typedef myCMap1::Face Face; protected: + myCMap1 cmap_; - CMap1TopoTest() + CMap1Test() {} - void SetUp() - { - d_ = this->add_face_topo(10); - } - void TearDown() - {} }; -TEST_F(CMap1TopoTest, testFaceDegree) +TEST_F(CMap1Test, addFace) { - EXPECT_EQ(10, this->degree(d_)); -} + Face f = cmap_.add_face(10); -TEST_F(CMap1TopoTest, testCutEdge) -{ - Dart d1 = this->phi1(d_); - Dart e = this->cut_edge_topo(d_); +// cmap_.cut_edge(Edge(f)); - EXPECT_EQ(d1.index, this->phi1(e).index); - EXPECT_EQ(d_.index, this->phi_1(e).index); - EXPECT_EQ(11, this->degree(d_)); -} + EXPECT_TRUE(is_well_embedded(cmap_)); + EXPECT_TRUE(is_well_embedded(cmap_)); + EXPECT_TRUE(is_well_embedded(cmap_)); + EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); + EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); + EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); + EXPECT_TRUE(is_container_well_referenced(cmap_)); + EXPECT_TRUE(is_container_well_referenced(cmap_)); + EXPECT_TRUE(is_container_well_referenced(cmap_)); -TEST_F(CMap1TopoTest, testUncutEdge) -{ - Dart e = this->phi1(d_); - Dart d1 = this->phi1(e); - this->uncut_edge_topo(e); - - EXPECT_EQ(d1.index, this->phi1(d_).index); - EXPECT_EQ(10, this->degree(d_)); -} - -TEST_F(CMap1TopoTest, testSplitFace) -{ - Dart e = this->phi1(d_); - Dart d1 = this->phi1(e); - this->uncut_edge_topo(e); - - EXPECT_EQ(d1.index, this->phi1(d_).index); - EXPECT_EQ(10, this->degree(d_)); } -// TEST_F(CMap1TopoTest, testDeleteFace) -// { -// this->delete_face_topo(d_); -// EXPECT_EQ(0, this->degree(d_)); -// } - - - } // namespace cgogn diff --git a/cgogn/core/tests/cmap/cmap1_topo_test.cpp b/cgogn/core/tests/cmap/cmap1_topo_test.cpp new file mode 100644 index 00000000..97343dfc --- /dev/null +++ b/cgogn/core/tests/cmap/cmap1_topo_test.cpp @@ -0,0 +1,107 @@ +#include +#include + +#include + +namespace cgogn +{ + + +class CMap1TopoTest: public CMap1, public ::testing::Test +{ +public: + typedef CMap1TopoTest::Face Face; + +protected: + + CMap1TopoTest() + {} +}; + + +TEST_F(CMap1TopoTest, testAddDart) +{ + +} + +TEST_F(CMap1TopoTest, testDeleteDart) +{ + +} + +TEST_F(CMap1TopoTest, testFaceDegree) +{ + Dart d = this->add_face_topo(10); + EXPECT_EQ(10, this->degree(Face(d))); +} + +TEST_F(CMap1TopoTest, testCutEdge) +{ + Dart d = this->add_face_topo(10); + Dart d1 = this->phi1(d); + + Dart e = this->cut_edge_topo(d); + + EXPECT_EQ(d1.index, this->phi1(e).index); + EXPECT_EQ(d.index, this->phi_1(e).index); + EXPECT_EQ(11, this->degree(Face(d))); +} + +TEST_F(CMap1TopoTest, testCollapseEdge) +{ + Dart d = this->add_face_topo(10); + Dart d_1 = this->phi_1(d); + Dart d1 = this->phi1(d); + + this->collapse_edge_topo(d); + + EXPECT_EQ(d1.index, this->phi1(d_1).index); + EXPECT_EQ(9, this->degree(Face(d_1))); +} + +TEST_F(CMap1TopoTest, testReverseFace) +{ + Dart d = this->add_face_topo(10); + std::vector successors; + + { + Dart dit = d; + do + { + successors.push_back(this->phi1(dit)); + dit = this->phi1(dit); + } + while(dit != d); + } + + this->reverse_face_topo(d); + + { + Dart dit = d; + unsigned i = 0; + do + { + EXPECT_EQ(this->phi_1(dit).index, successors[i].index); + dit = this->phi_1(dit); + ++i; + } + while(dit != d); + } +} + +TEST_F(CMap1TopoTest, testForEachDartOfVertex) +{ + +} + +TEST_F(CMap1TopoTest, testForEachDartOfEdge) +{ + +} + +TEST_F(CMap1TopoTest, testForEachDartOfFace) +{ + +} + +} // namespace cgogn diff --git a/cgogn/multiresolution/cph/ihcmap2_adaptive.h b/cgogn/multiresolution/cph/ihcmap2_adaptive.h index 650e790d..f6b17f10 100644 --- a/cgogn/multiresolution/cph/ihcmap2_adaptive.h +++ b/cgogn/multiresolution/cph/ihcmap2_adaptive.h @@ -217,7 +217,7 @@ class IHCMap2Adaptive : IHCMap2 Dart d2 = Inherit::phi2(d) ; unsigned int cur = Inherit::get_current_level(); Inherit::set_current_level(cur + 1); - if(Inherit::vertexDegree(Inherit::phi1(d)) == 2) + if(Inherit::degree(typename Inherit::Vertex(Inherit::phi1(d))) == 2) { degree2 = true ; if(edge_is_subdivided(d) || edge_is_subdivided(d2)) From 22e4ef34a6acf80b5954a4d34c672549bb8ce2e8 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Fri, 12 Feb 2016 16:46:22 +0100 Subject: [PATCH 099/402] simplification & optimisation of parallel_foreach... --- cgogn/core/cmap/map_base.h | 196 +++++++++++++++++++------------------ 1 file changed, 100 insertions(+), 96 deletions(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 7e7a3043..79d953f9 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -803,49 +803,52 @@ class MapBase : public MapBaseData Dart it = Dart(this->topology_.begin()); const Dart end = Dart(this->topology_.end()); + unsigned i = 0u; // buffer id (0/1) + unsigned int j = 0u;// thread id (0..nb_threads_pool) while (it != end) { - for (unsigned i = 0u; i < 2u; ++i) + // fill buffer + cells_buffers[i].push_back(dbuffs->template get_cell_buffer>()); + VecCell& cells = *cells_buffers[i].back(); + cells.reserve(PARALLEL_BUFFER_SIZE); + for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != end; ) { - for (unsigned int j = 0u; j < nb_threads_pool && it != end ; ++j) + if (!dm.is_marked(it)) { - cells_buffers[i].push_back(dbuffs->template get_cell_buffer>()); - VecCell& cells = *cells_buffers[i].back(); - cells.reserve(PARALLEL_BUFFER_SIZE); - for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != end; ) - { - if (!dm.is_marked(it)) - { - dm.template mark_orbit(it); - cells.push_back(Cell(it)); - ++k; - } - this->topology_.next(it.index); - } - futures[i].push_back(thread_pool->enqueue( [&cells,&f](unsigned int th_id){ - for (auto c : cells) - f(c,th_id); - })); + dm.template mark_orbit(it); + cells.push_back(Cell(it)); + ++k; } + this->topology_.next(it.index); + } + //launch thread + futures[i].push_back(thread_pool->enqueue( [&cells,&f](unsigned int th_id){ + for (auto c : cells) + f(c,th_id); + })); + // next thread + if (++j == nb_threads_pool) + { // again from 0 & change buffer + j = 0; const unsigned int id = (i+1u)%2u; for (auto& fu: futures[id]) fu.wait(); for (auto &b : cells_buffers[id]) dbuffs->release_cell_buffer(b); - futures[id].clear(); cells_buffers[id].clear(); - - // if we reach the end of the map while filling buffers from the second set we need to clean them too. - if (it == end && i == 1u) - { - for (auto& fu: futures[1u]) - fu.wait(); - for (auto &b : cells_buffers[1u]) - dbuffs->release_cell_buffer(b); - } } } + + // clean all at end + for (auto& fu: futures[0u]) + fu.wait(); + for (auto &b : cells_buffers[0u]) + dbuffs->release_cell_buffer(b); + for (auto& fu: futures[1u]) + fu.wait(); + for (auto &b : cells_buffers[1u]) + dbuffs->release_cell_buffer(b); } template @@ -886,49 +889,53 @@ class MapBase : public MapBaseData Dart it = Dart(this->topology_.begin()); const Dart end = Dart(this->topology_.end()); + unsigned i = 0u; // buffer id (0/1) + unsigned int j = 0u;// thread id (0..nb_threads_pool) while (it != end) { - for (unsigned i = 0u; i < 2u; ++i) + // fill buffer + cells_buffers[i].push_back(dbuffs->template get_cell_buffer>()); + VecCell& cells = *cells_buffers[i].back(); + cells.reserve(PARALLEL_BUFFER_SIZE); + for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != end; ) { - for (unsigned int j = 0u; j < nb_threads_pool && it != end ; ++j) + if (!cm.is_marked(it)) { - cells_buffers[i].push_back(dbuffs->template get_cell_buffer>()); - VecCell& cells = *cells_buffers[i].back(); - cells.reserve(PARALLEL_BUFFER_SIZE); - for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != end; ) - { - if (!cm.is_marked(it)) - { - cm.mark(it); - cells.push_back(it); - ++k; - } - this->topology_.next(it.index); - } - futures[i].push_back(thread_pool->enqueue( [&cells,&f](unsigned int th_id){ - for (auto c : cells) - f(c,th_id); - })); + cm.mark(it); + cells.push_back(it); + ++k; } + this->topology_.next(it.index); + } + //launch thread + futures[i].push_back(thread_pool->enqueue( [&cells,&f](unsigned int th_id){ + for (auto c : cells) + f(c,th_id); + })); + // next thread + if (++j == nb_threads_pool) + { // again from 0 & change buffer + j = 0; const unsigned int id = (i+1u)%2u; for (auto& fu: futures[id]) fu.wait(); for (auto &b : cells_buffers[id]) dbuffs->release_cell_buffer(b); - futures[id].clear(); cells_buffers[id].clear(); - - // if we reach the end of the map while filling buffers from the second set we need to clean them too. - if (it == end && i == 1u) - { - for (auto& fu: futures[1u]) - fu.wait(); - for (auto &b : cells_buffers[1u]) - dbuffs->release_cell_buffer(b); - } } } + + // clean all at end + for (auto& fu: futures[0u]) + fu.wait(); + for (auto &b : cells_buffers[0u]) + dbuffs->release_cell_buffer(b); + for (auto& fu: futures[1u]) + fu.wait(); + for (auto &b : cells_buffers[1u]) + dbuffs->release_cell_buffer(b); + } template @@ -942,71 +949,68 @@ class MapBase : public MapBaseData } } + template inline void parallel_foreach_cell_topo_cache(const FUNC& f) const { - using VecCell = std::vector>; - using Future = std::future< typename std::result_of, unsigned int)>::type >; - ThreadPool* thread_pool = cgogn::get_thread_pool(); const std::size_t nb_threads_pool = thread_pool->get_nb_threads(); - std::array, 2> cells_buffers; + using Future = std::future< typename std::result_of, unsigned int)>::type >; + std::array, 2> futures; - cells_buffers[0].reserve(nb_threads_pool); - cells_buffers[1].reserve(nb_threads_pool); futures[0].reserve(nb_threads_pool); futures[1].reserve(nb_threads_pool); - Buffers* dbuffs = cgogn::get_dart_buffers(); + const auto& attr = this->attributes_[ORBIT]; + unsigned int it = attr.begin(); + unsigned int end = attr.end(); + + unsigned int nbc = PARALLEL_BUFFER_SIZE; - unsigned int it = this->attributes_[ORBIT].begin(); - const unsigned int end = this->attributes_[ORBIT].end(); + // do block of PARALLEL_BUFFER_SIZE only if nb cells is huge else just divide + if ( (end - it) < 16*nb_threads_pool*PARALLEL_BUFFER_SIZE ) + nbc = (end - it) / nb_threads_pool; + + unsigned int local_end = it+nbc; const auto& cache = *(this->global_topo_cache_[ORBIT]); - const auto& attr = this->attributes_[ORBIT]; + unsigned int i=0; // used buffered futures 0/1 + unsigned int j=0;// thread num while (it != end) { - for (unsigned i = 0u; i < 2u; ++i) - { - for (unsigned int j = 0u; j < nb_threads_pool && it != end ; ++j) + futures[i].push_back(thread_pool->enqueue( [&cache,&attr,it,local_end,&f](unsigned int th_id){ + unsigned int loc_it = it; + while (loc_it < local_end) { - cells_buffers[i].push_back(dbuffs->template get_cell_buffer>()); - VecCell& cells = *cells_buffers[i].back(); - cells.reserve(PARALLEL_BUFFER_SIZE); - for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != end; ++k) - { - cells.push_back(cache[it]); - attr.next(it); - } - futures[i].push_back(thread_pool->enqueue( [&cells,&f](unsigned int th_id){ - for (auto c : cells) - f(c,th_id); - })); + f(cache[loc_it],th_id); + attr.next(loc_it); } + })); + it = local_end; + local_end = std::min(local_end+nbc,end); + + if (++j == nb_threads_pool) // change thread + { // again from 0 & change buffer + j = 0; const unsigned int id = (i+1u)%2u; for (auto& fu: futures[id]) fu.wait(); - for (auto &b : cells_buffers[id]) - dbuffs->release_cell_buffer(b); - futures[id].clear(); - cells_buffers[id].clear(); - - // if we reach the end of the map while filling buffers from the second set we need to clean them too. - if (it == end && i == 1u) - { - for (auto& fu: futures[1u]) - fu.wait(); - for (auto &b : cells_buffers[1u]) - dbuffs->release_cell_buffer(b); - } + i = id; } } + + // wait for remaining running threads + for (auto& fu: futures[0u]) + fu.wait(); + for (auto& fu: futures[1u]) + fu.wait(); } + template inline void foreach_cell_until_dart_marking(const FUNC& f) const { From 826778ef699749ad3646cf1ca26278b1c1388f64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Fri, 12 Feb 2016 17:12:29 +0100 Subject: [PATCH 100/402] fixed incorrect use of CRTP. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- .../multiresolution/cph/ihcmap2_adaptive.cpp | 2 +- cgogn/multiresolution/cph/ihcmap2_adaptive.h | 34 +++++++++++++------ cgogn/multiresolution/cph/ihcmap2_regular.cpp | 2 +- cgogn/multiresolution/cph/ihcmap2_regular.h | 27 ++++++++++----- 4 files changed, 44 insertions(+), 21 deletions(-) diff --git a/cgogn/multiresolution/cph/ihcmap2_adaptive.cpp b/cgogn/multiresolution/cph/ihcmap2_adaptive.cpp index db25f0ed..410a7f4d 100644 --- a/cgogn/multiresolution/cph/ihcmap2_adaptive.cpp +++ b/cgogn/multiresolution/cph/ihcmap2_adaptive.cpp @@ -29,6 +29,6 @@ namespace cgogn { -template class CGOGN_MULTIRESOLUTION_API IHCMap2Adaptive; +template class CGOGN_MULTIRESOLUTION_API IHCMap2Adaptive_T>; } // namespace cgogn diff --git a/cgogn/multiresolution/cph/ihcmap2_adaptive.h b/cgogn/multiresolution/cph/ihcmap2_adaptive.h index 2e5506d0..5a1ff02a 100644 --- a/cgogn/multiresolution/cph/ihcmap2_adaptive.h +++ b/cgogn/multiresolution/cph/ihcmap2_adaptive.h @@ -29,22 +29,27 @@ namespace cgogn { -template -class IHCMap2Adaptive : IHCMap2 +template +class IHCMap2Adaptive_T : public IHCMap2_T { public: - typedef IHCMap2 Inherit; - typedef IHCMap2Adaptive Self; + using Inherit = IHCMap2_T; + using Self = IHCMap2Adaptive_T; + friend class Inherit::Inherit_CMAP; + using Vertex = typename Inherit::Vertex; + using Edge = typename Inherit::Edge; + using Face = typename Inherit::Face; + using Volume = typename Inherit::Volume; - IHCMap2Adaptive() : Inherit() + IHCMap2Adaptive_T() : Inherit() {} - ~IHCMap2Adaptive() override + ~IHCMap2Adaptive_T() override {} - IHCMap2Adaptive(const Self&) = delete; - IHCMap2Adaptive(Self&&) = delete; + IHCMap2Adaptive_T(const Self&) = delete; + IHCMap2Adaptive_T(Self&&) = delete; Self& operator=(const Self&) = delete; Self& operator=(Self&&) = delete; @@ -449,7 +454,7 @@ class IHCMap2Adaptive : IHCMap2 this->split_face_topo(dd,next);// previously : Inherit::split_face(dd, next); TODO : write split_face for ihcmap2 // insert a first edge Dart ne = Inherit::phi2(Inherit::phi_1(dd)); Dart ne2 = Inherit::phi2(ne); - this->cut_edge_topo(ne);// previously : Inherit::cut_edge(ne); TODO : write cut_edge for ihcmap2// cut the new edge to insert the central vertex + this->cut_edge(ne);// previously : Inherit::cut_edge(ne); TODO : write cut_edge for ihcmap2// cut the new edge to insert the central vertex unsigned int id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(ne))); Inherit::set_edge_id(ne, id); @@ -536,8 +541,17 @@ class IHCMap2Adaptive : IHCMap2 } }; +template +struct IHCMap2AdaptiveType +{ + typedef IHCMap2Adaptive_T> TYPE; +}; + +template +using IHCMap2Adaptive = IHCMap2Adaptive_T>; + #if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_IHCMAP2_ADAPTIVE_CPP_)) -extern template class CGOGN_MULTIRESOLUTION_API IHCMap2Adaptive; +extern template class CGOGN_MULTIRESOLUTION_API IHCMap2Adaptive_T>; #endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_IHCMAP2_ADAPTIVE_CPP_)) diff --git a/cgogn/multiresolution/cph/ihcmap2_regular.cpp b/cgogn/multiresolution/cph/ihcmap2_regular.cpp index 4ea87498..ecfd2336 100644 --- a/cgogn/multiresolution/cph/ihcmap2_regular.cpp +++ b/cgogn/multiresolution/cph/ihcmap2_regular.cpp @@ -29,6 +29,6 @@ namespace cgogn { -template class CGOGN_MULTIRESOLUTION_API IHCMap2Regular; +template class CGOGN_MULTIRESOLUTION_API IHCMap2Regular_T>; } // namespace cgogn diff --git a/cgogn/multiresolution/cph/ihcmap2_regular.h b/cgogn/multiresolution/cph/ihcmap2_regular.h index 7d108be2..39386d41 100644 --- a/cgogn/multiresolution/cph/ihcmap2_regular.h +++ b/cgogn/multiresolution/cph/ihcmap2_regular.h @@ -29,27 +29,27 @@ namespace cgogn { -template -class IHCMap2Regular : public IHCMap2 +template +class IHCMap2Regular_T : public IHCMap2_T { public: - typedef IHCMap2 Inherit; - typedef IHCMap2Regular Self; + using Inherit = IHCMap2_T; + using Self = IHCMap2Regular_T; using Vertex = typename Inherit::Vertex; using Edge = typename Inherit::Edge; using Face = typename Inherit::Face; using Volume = typename Inherit::Volume; - IHCMap2Regular() : Inherit() + IHCMap2Regular_T() : Inherit() {} - IHCMap2Regular(const Self&) = delete; - IHCMap2Regular(Self&&) = delete; + IHCMap2Regular_T(const Self&) = delete; + IHCMap2Regular_T(Self&&) = delete; Self& operator=(const Self&) = delete; Self& operator=(Self&&) = delete; - inline ~IHCMap2Regular() = default; + inline ~IHCMap2Regular_T() = default; public: @@ -257,8 +257,17 @@ class IHCMap2Regular : public IHCMap2 } }; +template +struct IHCMap2RegularType +{ + typedef IHCMap2Regular_T> TYPE; +}; + +template +using IHCMap2Regular = IHCMap2Regular_T>; + #if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_IHCMAP2_REGULAR_CPP_)) -extern template class CGOGN_MULTIRESOLUTION_API IHCMap2Regular; +extern template class CGOGN_MULTIRESOLUTION_API IHCMap2Regular_T>; #endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_IHCMAP2_REGULAR_CPP_)) } // namespace cgogn From efd090be126d17b9ee1ba6651e48e8b6cc3ad97e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Fri, 12 Feb 2016 17:39:46 +0100 Subject: [PATCH 101/402] add_face_update_emb, split_face_update_emb and cut_edge_update_emb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/cmap1.h | 21 +-- cgogn/core/cmap/cmap2.h | 144 ++++++++++--------- cgogn/multiresolution/cph/ihcmap2_adaptive.h | 28 +++- cgogn/multiresolution/cph/ihcmap2_regular.h | 10 +- cgogn/multiresolution/examples/cph/cph2.cpp | 3 +- 5 files changed, 122 insertions(+), 84 deletions(-) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index acc792db..96033390 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -302,11 +302,21 @@ class CMap1_T : public MapBase */ Face add_face(unsigned int nb_edges) { - CGOGN_CHECK_CONCRETE_TYPE; cgogn_message_assert(nb_edges > 0, "Cannot create a face with no edge"); - const Face f(this->add_face_topo(nb_edges)); + return this->to_concrete()->add_face_update_emb(this->add_face_topo(nb_edges)); + } + + inline unsigned int degree(Face f) const + { + return this->nb_darts(f); + } + +protected: + Face add_face_update_emb(Face f) + { + CGOGN_CHECK_CONCRETE_TYPE; if (this->template is_orbit_embedded()) { foreach_dart_of_orbit(f, [this](Dart d) @@ -321,13 +331,6 @@ class CMap1_T : public MapBase return f; } - inline unsigned int degree(Face f) const - { - return this->nb_darts(f); - } - -protected: - /******************************************************************************* * Orbits traversal *******************************************************************************/ diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 481546ca..4d7398be 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -228,11 +228,11 @@ class CMap2_T : public CMap1_T Face add_face(unsigned int nb_edges) { - CGOGN_CHECK_CONCRETE_TYPE; cgogn_message_assert(nb_edges > 0, "Cannot create a face with no edge"); Dart d = Inherit::add_face_topo(nb_edges); Dart b = Inherit::add_face_topo(nb_edges); + Dart it = d; do { @@ -241,48 +241,50 @@ class CMap2_T : public CMap1_T b = this->phi_1(b); } while (it != d); - Face f(d); + return this->to_concrete()->add_face_update_emb(d); + } - if (this->template is_orbit_embedded()) - { - this->foreach_dart_of_orbit(f, [this] (Dart df) - { - this->template set_orbit_embedding(df, this->template add_attribute_element()); - }); - } + inline Vertex cut_edge(Edge e) + { + const Dart e2 = phi2(e); + const Dart nd = cut_edge_topo(e); - if (this->template is_orbit_embedded()) - { - foreach_incident_vertex(f, [this] (Vertex v) - { - this->set_orbit_embedding(v, this->template add_attribute_element()); - }); - } + return this->to_concrete()->cut_edge_update_emb(e.dart, e2, nd); + } - if (this->template is_orbit_embedded()) - { - foreach_incident_edge(f, [this] (Edge e) - { - this->set_orbit_embedding(e, this->template add_attribute_element()); - }); - } + inline void split_face(Dart d, Dart e) + { + split_face_topo(d,e); + this->to_concrete()->split_face_update_emb(d,e); + } - if (this->template is_orbit_embedded()) - this->set_orbit_embedding(f, this->template add_attribute_element()); + inline unsigned int degree(Face f) const + { + return Inherit::degree(f); + } - if (this->template is_orbit_embedded()) - this->set_orbit_embedding(Volume(d), this->template add_attribute_element()); +protected: - return f; + inline Dart cut_edge_topo(Dart d) + { + Dart e = phi2(d); // Get the adjacent 1D-edge + + phi2_unsew(d); // Unsew the initial 2D-edge, + // separating its two 1D-edges + Dart nd = Inherit::cut_edge_topo(d); + Dart ne = Inherit::cut_edge_topo(e); // Cut the two adjacent 1D-edges + + phi2_sew(d, ne); // Sew the new 1D-edges + phi2_sew(e, nd); // To build the new 2D-edges + + return nd; } - inline Vertex cut_edge(Edge d) + inline Vertex cut_edge_update_emb(Dart e, Dart e2, Dart nd) { CGOGN_CHECK_CONCRETE_TYPE; - const Dart e = phi2(d); - const Dart nd = cut_edge_topo(d); - const Dart ne = phi2(d); + const Dart ne = phi2(e); const Vertex v(nd); if(this->template is_orbit_embedded()) @@ -298,30 +300,40 @@ class CMap2_T : public CMap1_T if (this->template is_orbit_embedded()) { - this->template set_embedding(ne, this->template get_embedding(d.dart)); + this->template set_embedding(ne, this->template get_embedding(e)); this->set_orbit_embedding(Edge(nd), this->template add_attribute_element()); } if (this->template is_orbit_embedded()) { - this->template set_embedding(nd, this->template get_embedding(d.dart)); - this->template set_embedding(ne, this->template get_embedding(e)); + this->template set_embedding(nd, this->template get_embedding(e)); + this->template set_embedding(ne, this->template get_embedding(e2)); } if (this->template is_orbit_embedded()) { - const unsigned int idx = this->template get_embedding(d.dart); + const unsigned int idx = this->template get_embedding(e); this->template set_embedding(nd, idx); this->template set_embedding(ne, idx); } - return v; } - inline void split_face(Dart d, Dart e) + inline void split_face_topo(Dart d, Dart e) + { + cgogn_message_assert(d != e, "split_face: d and e should be distinct"); + cgogn_message_assert(this->same_cell(Face(d), Face(e)), "split_face: d and e should belong to the same face"); + + Dart nd = Inherit::cut_edge_topo(this->phi_1(d)); // cut the edge before d (insert a new dart before d) + Dart ne = Inherit::cut_edge_topo(this->phi_1(e)); // cut the edge before e (insert a new dart before e) + + Inherit::split_face_topo(nd, ne); // subdivide phi1 cycle at the inserted darts + phi2_sew(nd, ne); // build the new 2D-edge from the inserted darts + } + + inline void split_face_update_emb(Dart d, Dart e) { CGOGN_CHECK_CONCRETE_TYPE; - split_face_topo(d,e); const Dart nd = this->phi_1(e); const Dart ne = this->phi_1(d); @@ -356,38 +368,40 @@ class CMap2_T : public CMap1_T } } - inline unsigned int degree(Face f) const - { - return Inherit::degree(f); - } - -protected: - - inline Dart cut_edge_topo(Dart d) + inline Face add_face_update_emb(Face f) { - Dart e = phi2(d); // Get the adjacent 1D-edge - - phi2_unsew(d); // Unsew the initial 2D-edge, - // separating its two 1D-edges - Dart nd = Inherit::cut_edge_topo(d); - Dart ne = Inherit::cut_edge_topo(e); // Cut the two adjacent 1D-edges + CGOGN_CHECK_CONCRETE_TYPE; + if (this->template is_orbit_embedded()) + { + this->foreach_dart_of_orbit(f, [this] (Dart df) + { + this->template set_orbit_embedding(df, this->template add_attribute_element()); + }); + } - phi2_sew(d, ne); // Sew the new 1D-edges - phi2_sew(e, nd); // To build the new 2D-edges + if (this->template is_orbit_embedded()) + { + foreach_incident_vertex(f, [this] (Vertex v) + { + this->set_orbit_embedding(v, this->template add_attribute_element()); + }); + } - return nd; - } + if (this->template is_orbit_embedded()) + { + foreach_incident_edge(f, [this] (Edge e) + { + this->set_orbit_embedding(e, this->template add_attribute_element()); + }); + } - inline void split_face_topo(Dart d, Dart e) - { - cgogn_message_assert(d != e, "split_face: d and e should be distinct"); - cgogn_message_assert(this->same_cell(Face(d), Face(e)), "split_face: d and e should belong to the same face"); + if (this->template is_orbit_embedded()) + this->set_orbit_embedding(f, this->template add_attribute_element()); - Dart nd = Inherit::cut_edge_topo(this->phi_1(d)); // cut the edge before d (insert a new dart before d) - Dart ne = Inherit::cut_edge_topo(this->phi_1(e)); // cut the edge before e (insert a new dart before e) + if (this->template is_orbit_embedded()) + this->set_orbit_embedding(Volume(f.dart), this->template add_attribute_element()); - Inherit::split_face_topo(nd, ne); // subdivide phi1 cycle at the inserted darts - phi2_sew(nd, ne); // build the new 2D-edge from the inserted darts + return f; } inline void close_hole_topo(Dart d) diff --git a/cgogn/multiresolution/cph/ihcmap2_adaptive.h b/cgogn/multiresolution/cph/ihcmap2_adaptive.h index 5a1ff02a..61d3a04c 100644 --- a/cgogn/multiresolution/cph/ihcmap2_adaptive.h +++ b/cgogn/multiresolution/cph/ihcmap2_adaptive.h @@ -33,6 +33,7 @@ template class IHCMap2Adaptive_T : public IHCMap2_T { public: + using MapType = MAP_TYPE; using Inherit = IHCMap2_T; using Self = IHCMap2Adaptive_T; friend class Inherit::Inherit_CMAP; @@ -318,6 +319,19 @@ class IHCMap2Adaptive_T : public IHCMap2_T } protected: + inline Vertex cut_edge_update_emb(Dart e, Dart e2, Dart nd) + { + CGOGN_CHECK_CONCRETE_TYPE; + std::cerr << "IHCMap2Adaptive_T::cut_edge_update_emb method is not implemented yet." << std::endl; + return Vertex(); + } + + inline void split_face_update_emb(Dart e, Dart e2) + { + CGOGN_CHECK_CONCRETE_TYPE; + std::cerr << "IHCMap2Adaptive_T::split_face_update_emb method is not implemented yet." << std::endl; + } + /*************************************************** * SUBDIVISION * ***************************************************/ @@ -340,7 +354,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T Inherit::set_current_level(eLevel + 1); - this->cut_edge_topo(d);// previously : Inherit::cut_edge(d); TODO : write cut_edge for ihcmap2 + this->cut_edge(d); unsigned int eId = Inherit::get_edge_id(d); Inherit::set_edge_id(Inherit::phi1(d), eId); Inherit::set_edge_id(Inherit::phi1(dd), eId); @@ -421,7 +435,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T // (*vertexVertexFunctor)(e) ; e = Inherit::phi1(e); - this->split_face_topo(dd,e); // previously Inherit::split_face(dd, e); TODO : write split_face for ihcmap2 + this->split_face(dd,e); unsigned int id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id); // set the edge id of the inserted @@ -431,7 +445,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T e = Inherit::phi1(dd); // (*vertexVertexFunctor)(e); e = Inherit::phi1(e); - this->split_face_topo(dd,e); // previously : Inherit::split_face(dd, e); TODO : write split_face for ihcmap2 + this->split_face(dd,e); id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id); Inherit::set_edge_id(Inherit::phi_1(e), id); @@ -440,7 +454,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T e = Inherit::phi1(dd); // (*vertexVertexFunctor)(e); e = Inherit::phi1(e); - this->split_face_topo(dd,e);// previously : Inherit::split_face(dd, e); TODO : write split_face for ihcmap2 + this->split_face(dd,e); id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id); Inherit::set_edge_id(Inherit::phi_1(e), id); @@ -451,10 +465,10 @@ class IHCMap2Adaptive_T : public IHCMap2_T Dart next = this->phi1(dd); // (*vertexVertexFunctor)(next); next = Inherit::phi1(next); - this->split_face_topo(dd,next);// previously : Inherit::split_face(dd, next); TODO : write split_face for ihcmap2 // insert a first edge + this->split_face(dd,next); // insert a first edge Dart ne = Inherit::phi2(Inherit::phi_1(dd)); Dart ne2 = Inherit::phi2(ne); - this->cut_edge(ne);// previously : Inherit::cut_edge(ne); TODO : write cut_edge for ihcmap2// cut the new edge to insert the central vertex + this->cut_edge(ne); // cut the new edge to insert the central vertex unsigned int id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(ne))); Inherit::set_edge_id(ne, id); @@ -470,7 +484,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T dd = Inherit::phi1(dd); while(dd != ne) // turn around the face and insert new edges { // linked to the central vertex - this->split_face_topo(Inherit::phi1(ne), dd);// previously : Inherit::split_face(Inherit::phi1(ne), dd); TODO : write split_face for ihcmap2 + this->split_face(Inherit::phi1(ne), dd); Dart nne = Inherit::phi2(Inherit::phi_1(dd)); id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(nne))); diff --git a/cgogn/multiresolution/cph/ihcmap2_regular.h b/cgogn/multiresolution/cph/ihcmap2_regular.h index 39386d41..71743e23 100644 --- a/cgogn/multiresolution/cph/ihcmap2_regular.h +++ b/cgogn/multiresolution/cph/ihcmap2_regular.h @@ -33,9 +33,10 @@ template class IHCMap2Regular_T : public IHCMap2_T { public: - + using MapType = MAP_TYPE; using Inherit = IHCMap2_T; using Self = IHCMap2Regular_T; + friend typename Inherit::Inherit_CMAP; using Vertex = typename Inherit::Vertex; using Edge = typename Inherit::Edge; @@ -255,6 +256,13 @@ class IHCMap2Regular_T : public IHCMap2_T Inherit::set_current_level(cur) ; } +protected: + inline Face add_face_update_emb(Face f) + { + CGOGN_CHECK_CONCRETE_TYPE; + std::cerr << "IHCMap2Regular_T::add_face_update_emb method is not implemented yet." << std::endl; + return f; + } }; template diff --git a/cgogn/multiresolution/examples/cph/cph2.cpp b/cgogn/multiresolution/examples/cph/cph2.cpp index 6194f924..b1808b2e 100644 --- a/cgogn/multiresolution/examples/cph/cph2.cpp +++ b/cgogn/multiresolution/examples/cph/cph2.cpp @@ -23,8 +23,7 @@ int main() LerpTriQuadMRAnalysis lerp(map, position); -// map.add_face(4); // TODO : write add_face for IHMap2 ! - + map.add_face(4); std::cout << "before add level Faces :" << std::endl; map.template foreach_cell([&] (IHMap2::Face v) { From d950c581d6fd760beeafe21578941215933ca688 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Fri, 12 Feb 2016 17:45:58 +0100 Subject: [PATCH 102/402] =?UTF-8?q?Nettoyage=20de=20CMap2=20et=20op=C3=A9r?= =?UTF-8?q?ateurs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cgogn/core/cmap/cmap1.h | 28 +++-- cgogn/core/cmap/cmap2.h | 234 ++++++++++++++++++++++------------------ 2 files changed, 149 insertions(+), 113 deletions(-) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index fcf856d0..e05a7785 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -92,7 +92,7 @@ class CMap1_T : public MapBase init(); } - virtual ~CMap1_T() override + ~CMap1_T() override {} CMap1_T(Self const&) = delete; @@ -106,15 +106,19 @@ class CMap1_T : public MapBase protected: - /** - * \brief Link the current dart to dart d with a permutation - * @param d the dart to which the current is linked + /*! + * \brief Link two darts with the phi1 permutation what either merge or split their orbit(s). + * @param d: the first dart + * @param e: the second dart * - Before: d->f and e->g * - After: d->g and e->f - * Join the permutations cycles of dart d and e + * Join the orbits of dart d and e if they are distinct * - Starting from two cycles : d->f->...->d and e->g->...->e * - It makes one cycle d->g->...->e->f->...->d * If e = g then insert e in the cycle of d : d->e->f->...->d + * If d and e are in the same orbit of phi1, this orbit is split in two cycles. + * - Starting with d->g->...e->f->...->d + * - It makes two cycles : d->f->...->d and e->g->...->e */ void phi1_sew(Dart d, Dart e) { @@ -126,8 +130,8 @@ class CMap1_T : public MapBase (*phi_1_)[f.index] = e; } - /** - * \brief Unlink the successor of a given dart in a permutation + /*! + * \brief Remove the successor of a given dart from its permutation * @param d a dart * - Before: d->e->f * - After: d->f and e->e @@ -148,7 +152,7 @@ class CMap1_T : public MapBase public: - /** + /*! * \brief phi1 * @param d * @return phi1(d) @@ -158,7 +162,7 @@ class CMap1_T : public MapBase return (*phi1_)[d.index]; } - /** + /*! * \brief phi_1 * @param d * @return phi_1(d) @@ -170,7 +174,7 @@ class CMap1_T : public MapBase protected: - /** + /*! * \brief add a Dart in the map * @return the new Dart */ @@ -184,6 +188,10 @@ class CMap1_T : public MapBase return d; } + /*! + * \brief remove a dart from the map + * \param d: the dart to remove + */ inline void remove_dart(Dart d) { this->remove_topology_element(d.index); diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 8a648ab8..7428a3d9 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -93,12 +93,27 @@ class CMap2_T : public CMap1_T phi2_ = this->topology_.template add_attribute("phi2"); } +public: + + CMap2_T() : Inherit() + { + init(); + } + + ~CMap2_T() override + {} + + CMap2_T(Self const&) = delete; + CMap2_T(Self &&) = delete; + Self& operator=(Self const&) = delete; + Self& operator=(Self &&) = delete; + /******************************************************************************* * Low-level topological operations *******************************************************************************/ /** - * \brief Link dart d with dart e by an involution + * \brief Link dart d with dart e by the phi2 involution * @param d,e the darts to link * - Before: d->d and e->e * - After: d->e and e->d @@ -112,7 +127,7 @@ class CMap2_T : public CMap1_T } /** - * \brief Unlink the current dart by an involution + * \brief Remove the phi2 link of the current dart and its linked dart * @param d the dart to unlink * - Before: d->e and e->d * - After: d->d and e->e @@ -124,25 +139,12 @@ class CMap2_T : public CMap1_T (*phi2_)[e.index] = e; } -public: - - CMap2_T() : Inherit() - { - init(); - } - - ~CMap2_T() override - {} - - CMap2_T(Self const&) = delete; - CMap2_T(Self &&) = delete; - Self& operator=(Self const&) = delete; - Self& operator=(Self &&) = delete; - /******************************************************************************* * Basic topological operations *******************************************************************************/ +public: + /** * \brief phi2 * @param d @@ -167,61 +169,59 @@ class CMap2_T : public CMap1_T return d; } - /** - * @brief close_map closes the map so that there are no phi2 fix points - */ - void close_map() - { - for (Dart d : *this) + /******************************************************************************* + * High-level topological operations + *******************************************************************************/ + + protected: + + inline Dart cut_edge_topo(Dart d) { - if (phi2(d) == d) - { - close_hole_topo(d); - const Dart new_face = phi2(d); + Dart e = phi2(d); // Get the adjacent 1D-edge - if (this->template is_orbit_embedded()) - { - foreach_dart_of_orbit(new_face, [this] (Dart fd) - { - this->template set_orbit_embedding(fd, this->template add_attribute_element()); - }); - } - if (this->template is_orbit_embedded()) - { - foreach_dart_of_orbit(new_face, [this] (Dart fd) - { - this->template set_embedding(fd, this->template get_embedding(this->phi1(phi2(fd)))); - }); - } - if (this->template is_orbit_embedded()) - { - foreach_dart_of_orbit(new_face, [this] (Dart fd) - { - this->template set_embedding(fd, this->template get_embedding(phi2(fd))); - }); - } - if (this->template is_orbit_embedded()) + phi2_unsew(d); // Unsew the initial 2D-edge, + // separating its two 1D-edges + Dart nd = Inherit::cut_edge_topo(d); + Dart ne = Inherit::cut_edge_topo(e); // Cut the two adjacent 1D-edges + + phi2_sew(d, ne); // Sew the new 1D-edges + phi2_sew(e, nd); // To build the new 2D-edges + + return nd; + } + + inline void close_hole_topo(Dart d) + { + cgogn_message_assert(phi2(d) == d, "CMap2: close hole called on a dart that is not a phi2 fix point"); + + Dart first = add_dart(); // First edge of the face that will fill the hole + phi2_sew(d, first); // phi2-link the new edge to the hole + + Dart d_next = d; // Turn around the hole + Dart d_phi1; // to complete the face + do + { + do { - this->template set_orbit_embedding(new_face, this->template add_attribute_element()); - } - if (this->template is_orbit_embedded()) + d_phi1 = this->phi1(d_next); // Search and put in d_next + d_next = phi2(d_phi1); // the next dart of the hole + } while (d_next != d_phi1 && d_phi1 != d); + + if (d_phi1 != d) { - const unsigned int idx = this->template get_embedding(d); - foreach_dart_of_orbit(new_face, [this, idx] (Dart fd) - { - this->template set_embedding(fd, idx); - }); + Dart next = add_dart(); // Add a new edge there and link it to the face + this->phi1_sew(first, next); // the edge is linked to the face + phi2_sew(d_next, next); // the face is linked to the hole } - } + } while (d_phi1 != d); } - } - -public: /******************************************************************************* * High-level topological operations *******************************************************************************/ +public: + Face add_face(unsigned int nb_edges) { cgogn_message_assert(nb_edges > 0, "Cannot create a face with no edge"); @@ -311,6 +311,27 @@ class CMap2_T : public CMap1_T return v; } + inline void collapse_edge(Edge d) + { + const Dart d1 = this->phi1(d); + cgogn_message_assert(d1 != d, "collapse_edge: cannot collapse in degenerated face"); + cgogn_message_assert(d1 != this->phi_1(d), "collapse_edge: collapse will produce degenerated face"); + + const Dart e = this->phi2(d); + cgogn_message_assert(this->phi1(e) != e, "collapse_edge: cannot collapse in degenerated face"); + cgogn_message_assert(this->phi1(e) != this->phi_1(e), "collapse_edge: collapse will produce degenerated face"); + + unsigned int idx = this->template get_embedding(d.dart); + + Inherit::collapse_edge_topo(d); + Inherit::collapse_edge_topo(e); + + if (this->template is_orbit_embedded()) + { + this->set_orbit_embedding(Vertex(d1), idx); + } + } + /** * @brief Split the face of d and e by inserting an edge between the vertex of d and e * @param d : first vertex @@ -361,6 +382,55 @@ class CMap2_T : public CMap1_T } } + /** + * @brief close_map closes the map so that there are no phi2 fix points + */ + void close_map() + { + for (Dart d : *this) + { + if (phi2(d) == d) + { + close_hole_topo(d); + const Dart new_face = phi2(d); + + if (this->template is_orbit_embedded()) + { + foreach_dart_of_orbit(new_face, [this] (Dart fd) + { + this->template set_orbit_embedding(fd, this->template add_attribute_element()); + }); + } + if (this->template is_orbit_embedded()) + { + foreach_dart_of_orbit(new_face, [this] (Dart fd) + { + this->template set_embedding(fd, this->template get_embedding(this->phi1(phi2(fd)))); + }); + } + if (this->template is_orbit_embedded()) + { + foreach_dart_of_orbit(new_face, [this] (Dart fd) + { + this->template set_embedding(fd, this->template get_embedding(phi2(fd))); + }); + } + if (this->template is_orbit_embedded()) + { + this->template set_orbit_embedding(new_face, this->template add_attribute_element()); + } + if (this->template is_orbit_embedded()) + { + const unsigned int idx = this->template get_embedding(d); + foreach_dart_of_orbit(new_face, [this, idx] (Dart fd) + { + this->template set_embedding(fd, idx); + }); + } + } + } + } + inline unsigned int degree(Face f) const { return Inherit::degree(f); @@ -371,48 +441,6 @@ class CMap2_T : public CMap1_T return this->nb_darts(v); } -protected: - - inline Dart cut_edge_topo(Dart d) - { - Dart e = phi2(d); // Get the adjacent 1D-edge - - phi2_unsew(d); // Unsew the initial 2D-edge, - // separating its two 1D-edges - Dart nd = Inherit::cut_edge_topo(d); - Dart ne = Inherit::cut_edge_topo(e); // Cut the two adjacent 1D-edges - - phi2_sew(d, ne); // Sew the new 1D-edges - phi2_sew(e, nd); // To build the new 2D-edges - - return nd; - } - - inline void close_hole_topo(Dart d) - { - cgogn_message_assert(phi2(d) == d, "CMap2: close hole called on a dart that is not a phi2 fix point"); - - Dart first = add_dart(); // First edge of the face that will fill the hole - phi2_sew(d, first); // phi2-link the new edge to the hole - - Dart d_next = d; // Turn around the hole - Dart d_phi1; // to complete the face - do - { - do - { - d_phi1 = this->phi1(d_next); // Search and put in d_next - d_next = phi2(d_phi1); // the next dart of the hole - } while (d_next != d_phi1 && d_phi1 != d); - - if (d_phi1 != d) - { - Dart next = add_dart(); // Add a new edge there and link it to the face - this->phi1_sew(first, next); // the edge is linked to the face - phi2_sew(d_next, next); // the face is linked to the hole - } - } while (d_phi1 != d); - } /******************************************************************************* * Orbits traversal From 73d0e3758f207a4f75af7df441427c14588bd6b4 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Fri, 12 Feb 2016 17:53:38 +0100 Subject: [PATCH 103/402] off binary support --- cgogn/io/surface_import.h | 95 +++++++++++++++++++ thirdparty/CMakeLists.txt | 2 + thirdparty/OffBinConverter/CMakeLists.txt | 1 + thirdparty/OffBinConverter/off_ascii2bin.cpp | 96 ++++++++++++++++++++ 4 files changed, 194 insertions(+) create mode 100644 thirdparty/OffBinConverter/CMakeLists.txt create mode 100644 thirdparty/OffBinConverter/off_ascii2bin.cpp diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index f201161f..3c763291 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -269,6 +269,12 @@ class SurfaceImport return false; } + if (line.rfind("BINARY") != std::string::npos) + { + return import_OFF_BIN(fp); + } + + // read number of vertices, edges, faces do { @@ -336,6 +342,95 @@ class SurfaceImport return true; } + inline unsigned int changeEndianness(unsigned int x) + { + return (x>>24) | ((x<<8) & 0x00FF0000) | ((x>>8) & 0x0000FF00) | (x<<24); + } + + + template + bool import_OFF_BIN(std::ifstream& fp) + { + std::string line; + + char buffer1[12]; + fp.read(buffer1,12); + + nb_vertices_= changeEndianness(*(reinterpret_cast(buffer1))); + nb_faces_= changeEndianness(*(reinterpret_cast(buffer1+4))); + nb_edges_= changeEndianness(*(reinterpret_cast(buffer1+8))); + + + ChunkArray* position = vertex_attributes_.template add_attribute("position"); + + // read vertices position + float* buff_pos = new float[3*nb_vertices_]; + fp.read(reinterpret_cast(buff_pos),12*nb_vertices_); + + //endian + unsigned int* ptr = reinterpret_cast(buff_pos); + for (unsigned int i=0; i< 3*nb_vertices_;++i) + { + *ptr = changeEndianness(*ptr); + ++ptr; + } + + std::vector vertices_id; + vertices_id.reserve(nb_vertices_); + + for (unsigned int i = 0; i < nb_vertices_; ++i) + { + VEC3 pos{buff_pos[3*i], buff_pos[3*i+1], buff_pos[3*i+2]}; + + unsigned int vertex_id = vertex_attributes_.template insert_lines<1>(); + (*position)[vertex_id] = pos; + + vertices_id.push_back(vertex_id); + } + + delete[] buff_pos; + + // read faces (vertex indices) + int current_pos = fp.tellg(); + + fp.seekg (0, fp.end); + int length_file = fp.tellg(); + fp.seekg (current_pos, fp.beg); + + unsigned int nb_buff_ind = (length_file - current_pos)/4; + + unsigned int* buff_ind = new unsigned int[nb_buff_ind]; + + fp.read(reinterpret_cast(buff_ind),nb_buff_ind*4); + + ptr = buff_ind; + for (unsigned int i=0; i< nb_buff_ind;++i) + { + *ptr = changeEndianness(*ptr); + ++ptr; + } + + unsigned int* ind_ptr = buff_ind; + + faces_nb_edges_.reserve(nb_faces_); + faces_vertex_indices_.reserve(nb_vertices_ * 8); + for (unsigned int i = 0; i < nb_faces_; ++i) + { + unsigned int n = *ind_ptr++; + faces_nb_edges_.push_back(n); + for (unsigned int j = 0; j < n; ++j) + { + unsigned int index = *ind_ptr++; + faces_vertex_indices_.push_back(vertices_id[index]); + } + } + + delete[] buff_ind; + + return true; + } + + template bool import_OBJ(std::ifstream& fp) { diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index d37e96ba..ad249fa1 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -17,3 +17,5 @@ endif(CGOGN_USE_QT) if (CGOGN_BUILD_BENCHS) add_subdirectory(google-benchmark) endif(CGOGN_BUILD_BENCHS) + +add_subdirectory(OffBinConverter) diff --git a/thirdparty/OffBinConverter/CMakeLists.txt b/thirdparty/OffBinConverter/CMakeLists.txt new file mode 100644 index 00000000..25ff33f8 --- /dev/null +++ b/thirdparty/OffBinConverter/CMakeLists.txt @@ -0,0 +1 @@ +add_executable(off_ascii2bin off_ascii2bin.cpp) diff --git a/thirdparty/OffBinConverter/off_ascii2bin.cpp b/thirdparty/OffBinConverter/off_ascii2bin.cpp new file mode 100644 index 00000000..e2d9d867 --- /dev/null +++ b/thirdparty/OffBinConverter/off_ascii2bin.cpp @@ -0,0 +1,96 @@ +#include +#include +#include + +inline unsigned int changeEndian(unsigned int x) +{ + return (x>>24) | ((x<<8) & 0x00FF0000) | ((x>>8) & 0x0000FF00) | (x<<24); +} + +int main(int argc, char **argv) +{ + if (argc < 3) + { + std::cerr << argv[0] << "input_ascii.off output_bin.off" << std::endl; + return 1; + } + + std::ifstream ifs(argv[1],std::ios::in); + std::ofstream ofs(argv[2],std::ios::out|std::ofstream::binary); + + std::string str; + unsigned int nv; + unsigned int np; + unsigned int ne; + + ifs >> str; + + if (str != "OFF") + { + std::cerr << "no OFF comment at begin"<< std::endl; + return 1; + } + + ifs >> nv; + ifs >> np; + ifs >> ne; + + unsigned int nv_be = changeEndian(nv); + unsigned int np_be = changeEndian(np); + unsigned int ne_be = changeEndian(ne); + + + ofs << "OFF BINARY"<< std::endl; + ofs.write(reinterpret_cast(&nv_be),4); + ofs.write(reinterpret_cast(&np_be),4); + ofs.write(reinterpret_cast(&ne_be),4); + + float* vertices = new float[3*nv]; + + for (unsigned int i=0; i> vertices[3*i] >> vertices[3*i+1] >> vertices[3*i+2]; + } + + unsigned int* ptr = reinterpret_cast(vertices); + for (unsigned int i=0; i<3*nv;++i) + { + *ptr = changeEndian(*ptr); + ptr++; + } + + + ofs.write(reinterpret_cast(vertices),4*3*nv); + + delete[] vertices; + + std::vector prim; + prim.reserve(8*1024*1024); + + for (unsigned int i=0; i> nb; + prim.push_back(nb); + for (unsigned int j=0; j> ind; + prim.push_back(ind); + } + } + + ptr = reinterpret_cast(&(prim[0])); + for (unsigned int i=0; i(&(prim[0])),4*prim.size()); + + ofs.close(); + ifs.close(); + + return 0; +} From 8f4898a2498493dd7855c19b35b7d20b306f2243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Fri, 12 Feb 2016 18:10:33 +0100 Subject: [PATCH 104/402] added license. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/tests/cmap/cmap1_test.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/cgogn/core/tests/cmap/cmap1_test.cpp b/cgogn/core/tests/cmap/cmap1_test.cpp index b6fafd2f..5814f24f 100644 --- a/cgogn/core/tests/cmap/cmap1_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_test.cpp @@ -1,3 +1,26 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + #include #include From 53c7bbc181f59102b7d2cf8d35705734cadb763d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Fri, 12 Feb 2016 18:11:35 +0100 Subject: [PATCH 105/402] added license (bis) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/tests/cmap/cmap1_topo_test.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/cgogn/core/tests/cmap/cmap1_topo_test.cpp b/cgogn/core/tests/cmap/cmap1_topo_test.cpp index 97343dfc..2ba68290 100644 --- a/cgogn/core/tests/cmap/cmap1_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_topo_test.cpp @@ -1,3 +1,26 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + #include #include From 14ca1d0d614aa4315cdd87e1cd6edb11f1920854 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Mon, 15 Feb 2016 18:27:35 +0100 Subject: [PATCH 106/402] Merge PR of Etienne + new foreach_incident_cell() iterator --- cgogn/core/basic/cell.h | 5 +- cgogn/core/cmap/cmap0.h | 50 +++++- cgogn/core/cmap/cmap1.h | 166 +++++++++-------- cgogn/core/cmap/cmap2.h | 304 ++++++++++++++++++-------------- cgogn/core/cmap/cmap3.h | 2 + cgogn/core/examples/map/map.cpp | 8 +- cgogn/geometry/algos/normal.h | 6 +- 7 files changed, 305 insertions(+), 236 deletions(-) diff --git a/cgogn/core/basic/cell.h b/cgogn/core/basic/cell.h index cce25ae7..61b92b18 100644 --- a/cgogn/core/basic/cell.h +++ b/cgogn/core/basic/cell.h @@ -68,7 +68,6 @@ inline std::string orbit_name(Orbit orbit) case Orbit::PHI21_PHI31: return "cgogn::Orbit::PHI21_PHI31"; break; default: cgogn_assert_not_reached("This orbit does not exist"); return "UNKNOWN"; break; } -// return "UNKNOWN"; } /** @@ -96,7 +95,7 @@ class Cell {} /** - * \brief Creates a new Cell with a dart. + * \brief Creates a new Cell with a dart. * \param[in] d dart to convert to a cell of a given orbit */ inline Cell(Dart d) : dart(d) @@ -115,7 +114,7 @@ class Cell /** * \brief Cast operator. - * \return the dart + * \return the dart */ inline operator Dart() const { return dart; } diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index e61b0ffd..b2720add 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -47,8 +47,14 @@ class CMap0_T : public MapBase static const Orbit DART = Orbit::DART; static const Orbit VERTEX = Orbit::DART; + static const Orbit EDGE = Orbit::DART; + static const Orbit FACE = Orbit::DART; + static const Orbit VOLUME = Orbit::DART; typedef Cell Vertex; + typedef Cell Edge; + typedef Cell Face; + typedef Cell Volume; template using ChunkArray = typename Inherit::template ChunkArray; @@ -59,6 +65,12 @@ class CMap0_T : public MapBase using AttributeHandler = typename Inherit::template AttributeHandler; template using VertexAttributeHandler = AttributeHandler; + template + using EdgeAttributeHandler = AttributeHandler; + template + using FaceAttributeHandler = AttributeHandler; + template + using VolumeAttributeHandler = AttributeHandler; using DartMarker = typename cgogn::DartMarker; using DartMarkerStore = typename cgogn::DartMarkerStore; @@ -79,22 +91,42 @@ class CMap0_T : public MapBase Self& operator=(Self const&) = delete; Self& operator=(Self &&) = delete; + /******************************************************************************* + * Low-level topological operations + *******************************************************************************/ + protected: + + /*! + * \brief Add a Dart in the map (i.e. add a line in the topology container) + * @return the new Dart (i.e. the index of the added line) + */ inline Dart add_dart_internal() { - CGOGN_CHECK_CONCRETE_TYPE; return Dart(this->add_topology_element()); } + /******************************************************************************* + * High-level embedded operations + *******************************************************************************/ + public: - Vertex add_vertex() + + /*! + * \brief Add an embedded Dart in the map. + * @return the new inserted Dart + * If a DART attribute has been added to the Map, + * the inserted Dart is embedded on a new attribute element. + */ + Dart add_dart() { - const Vertex v(this->add_dart()); + CGOGN_CHECK_CONCRETE_TYPE; + const Dart d = this->add_dart_internal(); if (this->template is_orbit_embedded()) - this->template set_embedding(v.dart, this->template add_attribute_element()); + this->template set_embedding(d, this->template add_attribute_element()); - return v; + return d; } protected: @@ -103,6 +135,12 @@ class CMap0_T : public MapBase * Orbits traversal *******************************************************************************/ + template + inline void foreach_dart_of_DART(Dart d, const FUNC& f) const + { + f(d); + } + template inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const { @@ -110,7 +148,7 @@ class CMap0_T : public MapBase "Orbit not supported in a CMap1"); switch(ORBIT) { - case Orbit::DART: f(c.dart); break; + case Orbit::DART: this->foreach_dart_of_DART(c, f); break; case Orbit::PHI1: case Orbit::PHI2: case Orbit::PHI1_PHI2: diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 1474283b..2d2050b1 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -24,7 +24,7 @@ #ifndef CORE_CMAP_CMAP1_H_ #define CORE_CMAP_CMAP1_H_ -#include +#include #include #include @@ -32,7 +32,7 @@ namespace cgogn { template -class CMap1_T : public MapBase +class CMap1_T : public CMap0_T { public: @@ -40,10 +40,11 @@ class CMap1_T : public MapBase typedef MAP_TRAITS MapTraits; typedef MAP_TYPE MapType; - typedef MapBase Inherit; + typedef CMap0_T Inherit; typedef CMap1_T Self; friend typename Self::Inherit; + friend typename Inherit::Inherit; template friend class DartMarker_T; template @@ -53,10 +54,12 @@ class CMap1_T : public MapBase static const Orbit VERTEX = Orbit::DART; static const Orbit EDGE = Orbit::DART; static const Orbit FACE = Orbit::PHI1; + static const Orbit VOLUME = Orbit::PHI1; - typedef Cell Vertex; - typedef Cell Edge; - typedef Cell Face; + typedef Cell Vertex; + typedef Cell Edge; + typedef Cell Face; + typedef Cell Volume; template using ChunkArray = typename Inherit::template ChunkArray; @@ -71,6 +74,8 @@ class CMap1_T : public MapBase using EdgeAttributeHandler = AttributeHandler; template using FaceAttributeHandler = AttributeHandler; + template + using VolumeAttributeHandler = AttributeHandler; using DartMarker = typename cgogn::DartMarker; using DartMarkerStore = typename cgogn::DartMarkerStore; @@ -110,6 +115,19 @@ class CMap1_T : public MapBase protected: + /*! + * \brief Add a Dart in the map (i.e. add a line in the topology container) + * @return the new Dart (i.e. the index of the added line) + * The dart is defined as a fixed point for PHI1. + */ + inline Dart add_dart_internal() + { + Dart d = Inherit::add_dart_internal(); + (*phi1_)[d.index] = d; + (*phi_1_)[d.index] = d; + return d; + } + /*! * \brief Link two darts with the phi1 permutation what either merge or split their orbit(s). * @param d: the first dart @@ -176,39 +194,33 @@ class CMap1_T : public MapBase return (*phi_1_)[d.index]; } -protected: - - /*! - * \brief add a Dart in the map - * @return the new Dart - */ - inline Dart add_dart_internal() - { - unsigned int di = this->add_topology_element(); - Dart d(di); - (*phi1_)[di] = d; - (*phi_1_)[di] = d; - return d; - } - /******************************************************************************* * High-level topological operations *******************************************************************************/ protected: - inline Dart add_face_topo(unsigned int nb_edges) + /*! + * \brief Add a face in the map. + * \param size : the number of darts in the built face + * \return A dart of the built face + */ + inline Dart add_face_topo(unsigned int size) { - cgogn_message_assert(nb_edges > 0u, "Cannot create a face with no edge"); + cgogn_message_assert(size > 0u, "Cannot create an empty face"); - Dart d = this->add_dart(); - for (unsigned int i = 1u; i < nb_edges; ++i) + Dart d = this->add_dart_internal(); + for (unsigned int i = 1u; i < size; ++i) cut_edge_topo(d); return d; } - inline void delete_face_topo(Dart d) + /*! + * \brief Remove a face from the map. + * \param d : a dart of the face to remove + */ + inline void remove_face_topo(Dart d) { Dart e = phi1(d); while(e != d) @@ -222,24 +234,20 @@ class CMap1_T : public MapBase } /** - * \brief cut_edge - * @param d - * @return + * \brief Cut an edge. + * \param d : a dart of the edge to cut + * \return the inserted new dart + * The edge of d is cut by inserting a new dart after d in the PHI orbit. */ inline Dart cut_edge_topo(Dart d) { - Dart e = this->add_dart(); // Create a new dart e - phi1_sew(d, e); // Insert e between d and phi1(d) + Dart e = this->add_dart_internal(); // Create a new dart e + phi1_sew(d, e); // Insert e between d and phi1(d) return e; } - inline void split_face_topo(Dart d, Dart e) - { - cgogn_assert(d != e && this->same_cell(Face(d), Face(e))); - phi1_sew(phi_1(d), phi_1(e)); - } /** - * \brief remove edge d from its face and delete it + * \brief Remove edge d from its face and delete it * @param d : the edge to collapse * the edge preceeding d in the face is linked to the successor of d */ @@ -253,31 +261,21 @@ class CMap1_T : public MapBase inline void reverse_face_topo(Dart d) { - // Dart e is the first edge of the new face - Dart e = phi1(d); - - // Only one edge: nothing to do - if (e == d) return; + Dart e = phi1(d); // Dart e is the first edge of the new face - // Only two edges: nothing to do - if (phi1(e) == d) return; + if (e == d) return; // Only one edge: nothing to do + if (phi1(e) == d) return; // Only two edges: nothing to do - // Detach e from the face of d - phi1_unsew(d); + phi1_unsew(d); // Detach e from the face of d - // While the face of d contains more than two edges Dart dNext = phi1(d); - while (dNext != d) + while (dNext != d) // While the face of d contains more than two edges { - // Unsew the edge after d - phi1_unsew(d); - // Sew it after e (thus in reverse order) - phi1_sew(e, dNext); + phi1_unsew(d); // Unsew the edge after d + phi1_sew(e, dNext); // Sew it after e (thus in reverse order) dNext = phi1(d); } - - // Sew the last edge - phi1_sew(e, d); + phi1_sew(e, d); // Sew the last edge } /******************************************************************************* @@ -286,16 +284,16 @@ class CMap1_T : public MapBase public: - /** - * \brief add_face - * @param nb_edges - * @return + /*! + * \brief Add a face in the map. + * \param size : the number of darts in the built face + * \return A dart of the built face */ - Face add_face(unsigned int nb_edges) + Face add_face(unsigned int size) { - cgogn_message_assert(nb_edges > 0, "Cannot create a face with no edge"); + cgogn_message_assert(size > 0, "Cannot create an empty face"); - return this->to_concrete()->add_face_update_emb(this->add_face_topo(nb_edges)); + return this->to_concrete()->add_face_update_emb(this->add_face_topo(size)); } inline unsigned int degree(Face f) const @@ -326,12 +324,6 @@ class CMap1_T : public MapBase * Orbits traversal *******************************************************************************/ - template - inline void foreach_dart_of_DART(Dart d, const FUNC& f) const - { - f(d); - } - template inline void foreach_dart_of_PHI1(Dart d, const FUNC& f) const { @@ -351,7 +343,7 @@ class CMap1_T : public MapBase switch (ORBIT) { - case Orbit::DART: foreach_dart_of_DART(c, f); break; + case Orbit::DART: this->foreach_dart_of_DART(c, f); break; case Orbit::PHI1: foreach_dart_of_PHI1(c, f); break; case Orbit::PHI2: case Orbit::PHI1_PHI2: @@ -386,7 +378,7 @@ class CMap1_T : public MapBase switch (ORBIT) { - case Orbit::DART: foreach_dart_of_DART(c, f); break; + case Orbit::DART: this->foreach_dart_of_DART(c, f); break; case Orbit::PHI1: foreach_dart_of_PHI1_until(c, f); break; case Orbit::PHI2: case Orbit::PHI1_PHI2: @@ -422,21 +414,25 @@ class CMap1_T : public MapBase * Adjacence traversal *******************************************************************************/ - template - inline void foreach_adjacent_vertex_through_edge(Vertex v, const FUNC& f) const - { - static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); - f(Vertex(phi1(v.dart))); - f(Vertex(phi_1(v.dart))); - } - - template - inline void foreach_adjacent_edge_through_vertex(Edge e, const FUNC& f) const - { - static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); - f(Edge(phi1(e.dart))); - f(Edge(phi_1(e.dart))); - } +// To remove + +// template +// inline void foreach_adjacent_vertex_through_edge(Vertex v, const FUNC& f) const +// { +// static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); +// f(Vertex(phi1(v.dart))); +// f(Vertex(phi_1(v.dart))); +// } + +// To remove + +// template +// inline void foreach_adjacent_edge_through_vertex(Edge e, const FUNC& f) const +// { +// static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); +// f(Edge(phi1(e.dart))); +// f(Edge(phi_1(e.dart))); +// } }; template diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index a6b4310f..6e163c10 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -48,6 +48,7 @@ class CMap2_T : public CMap1_T friend typename Self::Inherit; friend typename Inherit::Inherit; + friend typename Inherit::Inherit::Inherit; friend class CMap2Builder_T; template friend class DartMarker_T; @@ -115,6 +116,18 @@ class CMap2_T : public CMap1_T * Low-level topological operations *******************************************************************************/ + /** + * \brief Add a Dart in the map (i.e. add a line in the topology container) + * @return the new Dart (i.e. the index of the added line) + * The dart is defined as a fixed point for PHI2. + */ + inline Dart add_dart_internal() + { + Dart d = Inherit::add_dart_internal(); + (*phi2_)[d.index] = d; + return d; + } + /** * \brief Link dart d with dart e by the phi2 involution * @param d,e the darts to link @@ -158,19 +171,79 @@ class CMap2_T : public CMap1_T return (*phi2_)[d.index]; } + /******************************************************************************* + * High-level topological operations + *******************************************************************************/ + protected: + inline Dart cut_edge_topo(Dart d) + { + Dart e = phi2(d); // Get the adjacent 1D-edge + + phi2_unsew(d); // Unsew the initial 2D-edge, + // separating its two 1D-edges + Dart nd = Inherit::cut_edge_topo(d); + Dart ne = Inherit::cut_edge_topo(e); // Cut the two adjacent 1D-edges + + phi2_sew(d, ne); // Sew the new 1D-edges + phi2_sew(e, nd); // To build the new 2D-edges + + return nd; + } + /** - * \brief add a Dart in the map - * @return the new Dart - */ - inline Dart add_dart_internal() + * @brief Split the face of d and e by inserting an edge between the vertex of d and e + * @param d : first vertex + * @param e : second vertex + * Darts d and e should belong to the same face and be distinct from each other. + * An edge made of two new darts is inserted between the two given vertices. + */ + inline void split_face_topo(Dart d, Dart e) { - Dart d = Inherit::add_dart_internal(); - (*phi2_)[d.index] = d; - return d; + cgogn_message_assert(d != e, "split_face: d and e should be distinct"); + cgogn_message_assert(this->same_cell(Face(d), Face(e)), "split_face: d and e should belong to the same face"); + + Dart dd = this->phi_1(d); + Dart ee = this->phi_1(e); + Dart nd = Inherit::cut_edge_topo(dd); // cut the edge before d (insert a new dart before d) + Dart ne = Inherit::cut_edge_topo(ee); // cut the edge before e (insert a new dart before e) + this->phi1_sew(dd, ee); // subdivide phi1 cycle at the inserted darts + phi2_sew(nd, ne); // build the new 2D-edge from the inserted darts + } + + inline void close_hole_topo(Dart d) + { + cgogn_message_assert(phi2(d) == d, "CMap2: close hole called on a dart that is not a phi2 fix point"); + + Dart first = this->add_dart_internal(); // First edge of the face that will fill the hole + phi2_sew(d, first); // phi2-link the new edge to the hole + + Dart d_next = d; // Turn around the hole + Dart d_phi1; // to complete the face + do + { + do + { + d_phi1 = this->phi1(d_next); // Search and put in d_next + d_next = phi2(d_phi1); // the next dart of the hole + } while (d_next != d_phi1 && d_phi1 != d); + + if (d_phi1 != d) + { + Dart next = this->add_dart_internal(); // Add a new edge there and link it to the face + this->phi1_sew(first, next); // the edge is linked to the face + phi2_sew(d_next, next); // the face is linked to the hole + } + } while (d_phi1 != d); } + /******************************************************************************* + * High-level embedded operations + *******************************************************************************/ + +protected: + /** * @brief close_map closes the map so that there are no phi2 fix points */ @@ -222,74 +295,6 @@ class CMap2_T : public CMap1_T } } - - /******************************************************************************* - * High-level topological operations - *******************************************************************************/ - -public: - - Face add_face(unsigned int nb_edges) - { - cgogn_message_assert(nb_edges > 0, "Cannot create a face with no edge"); - - Dart d = Inherit::add_face_topo(nb_edges); - Dart b = Inherit::add_face_topo(nb_edges); - - Dart it = d; - do - { - phi2_sew(it, b); - it = this->phi1(it); - b = this->phi_1(b); - } while (it != d); - - return this->to_concrete()->add_face_update_emb(d); - } - - inline Vertex cut_edge(Edge e) - { - const Dart e2 = phi2(e); - const Dart nd = cut_edge_topo(e); - - return this->to_concrete()->cut_edge_update_emb(e.dart, e2, nd); - } - - /** - * @brief Split the face of d and e by inserting an edge between the vertex of d and e - * @param d : first vertex - * @param e : second vertex - * Darts d and e should belong to the same face and be distinct from each other. - * An edge made of two new darts is inserted between the two given vertices. - */ - inline void split_face(Dart d, Dart e) - { - split_face_topo(d,e); - this->to_concrete()->split_face_update_emb(d,e); - } - - inline unsigned int degree(Face f) const - { - return Inherit::degree(f); - } - -protected: - - inline Dart cut_edge_topo(Dart d) - { - Dart e = phi2(d); // Get the adjacent 1D-edge - - phi2_unsew(d); // Unsew the initial 2D-edge, - // separating its two 1D-edges - Dart nd = Inherit::cut_edge_topo(d); - Dart ne = Inherit::cut_edge_topo(e); // Cut the two adjacent 1D-edges - - phi2_sew(d, ne); // Sew the new 1D-edges - phi2_sew(e, nd); // To build the new 2D-edges - - return nd; - } - inline Vertex cut_edge_update_emb(Dart e, Dart e2, Dart nd) { CGOGN_CHECK_CONCRETE_TYPE; @@ -329,18 +334,6 @@ class CMap2_T : public CMap1_T return v; } - inline void split_face_topo(Dart d, Dart e) - { - cgogn_message_assert(d != e, "split_face: d and e should be distinct"); - cgogn_message_assert(this->same_cell(Face(d), Face(e)), "split_face: d and e should belong to the same face"); - - Dart nd = Inherit::cut_edge_topo(this->phi_1(d)); // cut the edge before d (insert a new dart before d) - Dart ne = Inherit::cut_edge_topo(this->phi_1(e)); // cut the edge before e (insert a new dart before e) - - Inherit::split_face_topo(nd, ne); // subdivide phi1 cycle at the inserted darts - phi2_sew(nd, ne); // build the new 2D-edge from the inserted darts - } - inline void split_face_update_emb(Dart d, Dart e) { CGOGN_CHECK_CONCRETE_TYPE; @@ -414,30 +407,50 @@ class CMap2_T : public CMap1_T return f; } - inline void close_hole_topo(Dart d) +public: + + Face add_face(unsigned int nb_edges) { - cgogn_message_assert(phi2(d) == d, "CMap2: close hole called on a dart that is not a phi2 fix point"); + cgogn_message_assert(nb_edges > 0, "Cannot create a face with no edge"); - Dart first = this->add_dart(); // First edge of the face that will fill the hole - phi2_sew(d, first); // phi2-link the new edge to the hole + Dart d = Inherit::add_face_topo(nb_edges); + Dart b = Inherit::add_face_topo(nb_edges); - Dart d_next = d; // Turn around the hole - Dart d_phi1; // to complete the face + Dart it = d; do { - do - { - d_phi1 = this->phi1(d_next); // Search and put in d_next - d_next = phi2(d_phi1); // the next dart of the hole - } while (d_next != d_phi1 && d_phi1 != d); + phi2_sew(it, b); + it = this->phi1(it); + b = this->phi_1(b); + } while (it != d); - if (d_phi1 != d) - { - Dart next = this->add_dart(); // Add a new edge there and link it to the face - this->phi1_sew(first, next); // the edge is linked to the face - phi2_sew(d_next, next); // the face is linked to the hole - } - } while (d_phi1 != d); + return this->to_concrete()->add_face_update_emb(d); + } + + inline Vertex cut_edge(Edge e) + { + const Dart e2 = phi2(e); + const Dart nd = cut_edge_topo(e); + + return this->to_concrete()->cut_edge_update_emb(e.dart, e2, nd); + } + + /** + * @brief Split the face of d and e by inserting an edge between the vertex of d and e + * @param d : first vertex + * @param e : second vertex + * Darts d and e should belong to the same face and be distinct from each other. + * An edge made of two new darts is inserted between the two given vertices. + */ + inline void split_face(Dart d, Dart e) + { + split_face_topo(d,e); + this->to_concrete()->split_face_update_emb(d,e); + } + + inline unsigned int degree(Face f) const + { + return Inherit::degree(f); } /******************************************************************************* @@ -473,31 +486,31 @@ class CMap2_T : public CMap1_T // For every face added to the list for(unsigned int i = 0; i < visited_faces->size(); ++i) { - if (!marker.is_marked((*visited_faces)[i])) // Face has not been visited yet + Dart e = (*visited_faces)[i]; + if (!marker.is_marked(e)) // Face has not been visited yet { // mark visited darts (current face) // and add non visited adjacent faces to the list of face - Dart e = (*visited_faces)[i]; + Dart it = e; do { - f(e); // apply the function to the darts of the face - marker.mark(e); // Mark - Dart adj = phi2(e); // Get adjacent face + f(it); // apply the function to the darts of the face + marker.mark(it); // Mark + Dart adj = phi2(it); // Get adjacent face if (!marker.is_marked(adj)) visited_faces->push_back(adj); // Add it - e = this->phi1(e); - } while (e != (*visited_faces)[i]); + it = this->phi1(it); + } while (it != e); } } - cgogn::get_dart_buffers()->release_buffer(visited_faces); } template inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const { - static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || - ORBIT == Orbit::PHI2 || ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21, + static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || ORBIT == Orbit::PHI2 || + ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21, "Orbit not supported in a CMap2"); switch (ORBIT) @@ -544,37 +557,39 @@ class CMap2_T : public CMap1_T // For every face added to the list for(unsigned int i = 0; i < visited_faces->size(); ++i) { - if (!marker.is_marked((*visited_faces)[i])) // Face has not been visited yet + Dart e = (*visited_faces)[i]; + if (!marker.is_marked(e)) // Face has not been visited yet { // mark visited darts (current face) // and add non visited adjacent faces to the list of face - Dart e = (*visited_faces)[i]; + Dart it = e; do { - if (!f(e)) // apply the function to the darts of the face + if (!f(it)) // apply the function to the darts of the face { cgogn::get_dart_buffers()->release_buffer(visited_faces); return; } - marker.mark(e); // Mark - Dart adj = phi2(e); // Get adjacent face + marker.mark(it); // Mark + Dart adj = phi2(it); // Get adjacent face if (!marker.is_marked(adj)) visited_faces->push_back(adj); // Add it - e = this->phi1(e); - } while (e != (*visited_faces)[i]); + it = this->phi1(it); + } while (it != e); } } - cgogn::get_dart_buffers()->release_buffer(visited_faces); } template inline void foreach_dart_of_orbit_until(Cell c, const FUNC& f) const { - static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || - ORBIT == Orbit::PHI2 || ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21, + static_assert(check_func_return_type(FUNC, bool), + "Wrong function return type"); + + static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || ORBIT == Orbit::PHI2 || + ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21, "Orbit not supported in a CMap2"); - static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); switch (ORBIT) { @@ -596,20 +611,37 @@ class CMap2_T : public CMap1_T * Incidence traversal *******************************************************************************/ - template - inline void foreach_incident_edge(Vertex v, const FUNC& f) const + template + inline void foreach_incident_cell(Cell v, const FUNC& f) const { - static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); - foreach_dart_of_orbit(v, f); - } + static_assert(check_func_parameter_type(FUNC, Cell), + "Wrong function cell parameter type"); - template - inline void foreach_incident_face(Vertex v, const FUNC& f) const - { - static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); - foreach_dart_of_orbit(v, f); + DartMarkerStore marker(*this); + foreach_dart_of_orbit(v, [&] (Dart d) + { + if (!marker.is_marked(d)) + { + marker.template mark_orbit(d); + f(d); + } + }); } +// template +// inline void foreach_incident_edge(Vertex v, const FUNC& f) const +// { +// static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); +// foreach_dart_of_orbit(v, f); +// } + +// template +// inline void foreach_incident_face(Vertex v, const FUNC& f) const +// { +// static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); +// foreach_dart_of_orbit(v, f); +// } + template inline void foreach_incident_vertex(Edge e, const FUNC& f) const { diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 1e0dd450..7651d8dd 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -49,12 +49,14 @@ class CMap3_T : public CMap2_T friend typename Self::Inherit; friend typename Inherit::Inherit; friend typename Inherit::Inherit::Inherit; + friend typename Inherit::Inherit::Inherit::Inherit; template friend class DartMarker_T; template friend class DartMarkerStore; friend class CMap3Builder_T; + static const Orbit DART = Orbit::DART; static const Orbit VERTEX = Orbit::PHI21_PHI31; static const Orbit EDGE = Orbit::PHI2_PHI3; static const Orbit FACE = Orbit::PHI1_PHI3; diff --git a/cgogn/core/examples/map/map.cpp b/cgogn/core/examples/map/map.cpp index a2dd0851..f39c8528 100644 --- a/cgogn/core/examples/map/map.cpp +++ b/cgogn/core/examples/map/map.cpp @@ -107,10 +107,10 @@ int test1(MAP& map) }); std::cout << "End Vertices" << std::endl; - map.foreach_adjacent_vertex_through_edge(d1, [&] (typename MAP::Vertex v) - { - ah[v] = 4.0f; - }); +// map.foreach_adjacent_vertex_through_edge(d1, [&] (typename MAP::Vertex v) +// { +// ah[v] = 4.0f; +// }); // get ChunkArrayContainer -> get ChunkArray -> fill // typename MAP::template ChunkArrayContainer& container = map.get_attribute_container(MAP::VERTEX); diff --git a/cgogn/geometry/algos/normal.h b/cgogn/geometry/algos/normal.h index 2a94734c..016672cb 100644 --- a/cgogn/geometry/algos/normal.h +++ b/cgogn/geometry/algos/normal.h @@ -82,7 +82,8 @@ inline VEC3 vertex_normal(const MAP& map, Cell v, const typename M VEC3 n{0,0,0}; const VEC3& p = position[v.dart]; - map.foreach_incident_face(v, [&] (Cell f) +// map.foreach_incident_face(v, [&] (Cell f) + map.foreach_incident_cell(v, [&] (Cell f) { VEC3 facen = face_normal(map, f, position); const VEC3& p1 = position[map.phi1(f.dart)]; @@ -103,7 +104,8 @@ inline VEC3 vertex_normal(const MAP& map, Cell v, const typename M VEC3 n{0,0,0}; const VEC3& p = position[v.dart]; - map.foreach_incident_face(v, [&] (Cell f) +// map.foreach_incident_face(v, [&] (Cell f) + map.foreach_incident_cell(v, [&] (Cell f) { VEC3 facen = fnormal[f]; const VEC3& p1 = position[map.phi1(f.dart)]; From ba8532aa3f333f0f21a2756f8790eaba57bd5e2b Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Tue, 16 Feb 2016 10:37:38 +0100 Subject: [PATCH 107/402] support of comment in off reading + speedup --- cgogn/io/surface_import.h | 162 ++++++++++++++++++++++---------------- 1 file changed, 92 insertions(+), 70 deletions(-) diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index 3c763291..e827d679 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -259,6 +259,31 @@ class SurfaceImport bool import_OFF(std::ifstream& fp) { std::string line; + line.reserve(512); + + auto read_double = [&fp,&line]() -> double + { + fp >> line; + while (line[0]=='#') + { + fp.ignore(std::numeric_limits::max(), '\n'); + fp >> line; + } + return std::stod(line); + }; + + auto read_uint = [&fp,&line]() -> unsigned int + { + fp >> line; + while (line[0]=='#') + { + fp.ignore(std::numeric_limits::max(), '\n'); + fp >> line; + } + return (unsigned int)(std::stoul(line)); + }; + + // read OFF header std::getline(fp, line); @@ -276,17 +301,9 @@ class SurfaceImport // read number of vertices, edges, faces - do - { - std::getline(fp, line); - } while (line.size() == 0); - { // limit scope of oss - std::stringstream oss(line); - - oss >> nb_vertices_; - oss >> nb_faces_; - oss >> nb_edges_; - } + nb_vertices_ = read_uint(); + nb_faces_ = read_uint(); + nb_edges_ = read_uint(); ChunkArray* position = vertex_attributes_.template add_attribute("position"); @@ -296,17 +313,10 @@ class SurfaceImport for (unsigned int i = 0; i < nb_vertices_; ++i) { - do - { - std::getline(fp, line); - } while (line.size() == 0); - - std::stringstream oss(line); - double x, y, z; - oss >> x; - oss >> y; - oss >> z; + double x = read_double(); + double y = read_double(); + double z = read_double(); VEC3 pos{x, y, z}; @@ -321,22 +331,14 @@ class SurfaceImport faces_vertex_indices_.reserve(nb_vertices_ * 8); for (unsigned int i = 0; i < nb_faces_; ++i) { - do - { - std::getline(fp, line); - } while (line.size() == 0); - - std::stringstream oss(line); - - unsigned short n; - oss >> n; + unsigned int n = read_uint(); faces_nb_edges_.push_back(n); for (unsigned int j = 0; j < n; ++j) { - unsigned int index; - oss >> index; + unsigned int index = read_uint(); faces_vertex_indices_.push_back(vertices_id[index]); } + } return true; @@ -351,9 +353,7 @@ class SurfaceImport template bool import_OFF_BIN(std::ifstream& fp) { - std::string line; - - char buffer1[12]; + char buffer1[12]; fp.read(buffer1,12); nb_vertices_= changeEndianness(*(reinterpret_cast(buffer1))); @@ -363,24 +363,34 @@ class SurfaceImport ChunkArray* position = vertex_attributes_.template add_attribute("position"); - // read vertices position - float* buff_pos = new float[3*nb_vertices_]; - fp.read(reinterpret_cast(buff_pos),12*nb_vertices_); - - //endian - unsigned int* ptr = reinterpret_cast(buff_pos); - for (unsigned int i=0; i< 3*nb_vertices_;++i) - { - *ptr = changeEndianness(*ptr); - ++ptr; - } + static const unsigned int BUFFER_SZ = 1024*1024; + float* buff_pos = new float[3*BUFFER_SZ]; std::vector vertices_id; vertices_id.reserve(nb_vertices_); - for (unsigned int i = 0; i < nb_vertices_; ++i) + unsigned j = BUFFER_SZ; + for (unsigned int i = 0; i < nb_vertices_; ++i,++j) { - VEC3 pos{buff_pos[3*i], buff_pos[3*i+1], buff_pos[3*i+2]}; + if (j == BUFFER_SZ) + { + j = 0; + // read from file into buffer + if (i+BUFFER_SZ < nb_vertices_) + fp.read(reinterpret_cast(buff_pos),3*sizeof(float)*BUFFER_SZ); + else + fp.read(reinterpret_cast(buff_pos),3*sizeof(float)*(nb_vertices_-i)); + + //endian + unsigned int* ptr = reinterpret_cast(buff_pos); + for (unsigned int i=0; i< 3*BUFFER_SZ;++i) + { + *ptr = changeEndianness(*ptr); + ++ptr; + } + } + + VEC3 pos{buff_pos[3*j], buff_pos[3*j+1], buff_pos[3*j+2]}; unsigned int vertex_id = vertex_attributes_.template insert_lines<1>(); (*position)[vertex_id] = pos; @@ -391,36 +401,48 @@ class SurfaceImport delete[] buff_pos; // read faces (vertex indices) - int current_pos = fp.tellg(); - - fp.seekg (0, fp.end); - int length_file = fp.tellg(); - fp.seekg (current_pos, fp.beg); - - unsigned int nb_buff_ind = (length_file - current_pos)/4; - - unsigned int* buff_ind = new unsigned int[nb_buff_ind]; - - fp.read(reinterpret_cast(buff_ind),nb_buff_ind*4); - - ptr = buff_ind; - for (unsigned int i=0; i< nb_buff_ind;++i) - { - *ptr = changeEndianness(*ptr); - ++ptr; - } - - unsigned int* ind_ptr = buff_ind; + unsigned int* buff_ind = new unsigned int[BUFFER_SZ]; faces_nb_edges_.reserve(nb_faces_); faces_vertex_indices_.reserve(nb_vertices_ * 8); + + unsigned int* ptr = buff_ind; + unsigned int nb_read = BUFFER_SZ; for (unsigned int i = 0; i < nb_faces_; ++i) { - unsigned int n = *ind_ptr++; + if (nb_read == BUFFER_SZ) + { + fp.read(reinterpret_cast(buff_ind),BUFFER_SZ*sizeof(unsigned int)); + ptr = buff_ind; + for (unsigned int i=0; i< BUFFER_SZ;++i) + { + *ptr = changeEndianness(*ptr); + ++ptr; + } + ptr = buff_ind; + nb_read =0; + } + + unsigned int n = *ptr++; + nb_read++; + faces_nb_edges_.push_back(n); for (unsigned int j = 0; j < n; ++j) { - unsigned int index = *ind_ptr++; + if (nb_read == BUFFER_SZ) + { + fp.read(reinterpret_cast(buff_ind),BUFFER_SZ*sizeof(unsigned int)); + ptr = buff_ind; + for (unsigned int i=0; i< BUFFER_SZ;++i) + { + *ptr = changeEndianness(*ptr); + ++ptr; + } + ptr = buff_ind; + nb_read=0; + } + unsigned int index = *ptr++; + nb_read++; faces_vertex_indices_.push_back(vertices_id[index]); } } From 795eaea8f73dafbdf69998c499d8edf788b2c285 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Tue, 16 Feb 2016 10:48:40 +0100 Subject: [PATCH 108/402] using local functions in import off --- cgogn/io/surface_import.h | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index e827d679..fff6e8eb 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -261,6 +261,7 @@ class SurfaceImport std::string line; line.reserve(512); + // local function for reading double with comment ignoring auto read_double = [&fp,&line]() -> double { fp >> line; @@ -272,6 +273,7 @@ class SurfaceImport return std::stod(line); }; + // local function for reading int with comment ignoring auto read_uint = [&fp,&line]() -> unsigned int { fp >> line; @@ -294,6 +296,7 @@ class SurfaceImport return false; } + // check if binary file if (line.rfind("BINARY") != std::string::npos) { return import_OFF_BIN(fp); @@ -344,15 +347,16 @@ class SurfaceImport return true; } - inline unsigned int changeEndianness(unsigned int x) - { - return (x>>24) | ((x<<8) & 0x00FF0000) | ((x>>8) & 0x0000FF00) | (x<<24); - } - - template bool import_OFF_BIN(std::ifstream& fp) { + + // local function for little/big endian conversion + auto changeEndianness = [](unsigned int x) -> unsigned int + { + return (x>>24) | ((x<<8) & 0x00FF0000) | ((x>>8) & 0x0000FF00) | (x<<24); + }; + char buffer1[12]; fp.read(buffer1,12); From c5a95630d78a55aba2c2781e3c47dbcf91c1eee6 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Tue, 16 Feb 2016 16:29:00 +0100 Subject: [PATCH 109/402] CMap2.h : cleaning embedded operators + some documentation --- cgogn/core/cmap/cmap0.h | 2 +- cgogn/core/cmap/cmap1.h | 101 +++--- cgogn/core/cmap/cmap2.h | 349 ++++++++++--------- cgogn/geometry/algos/normal.h | 4 +- cgogn/multiresolution/cph/ihcmap2_adaptive.h | 14 +- 5 files changed, 249 insertions(+), 221 deletions(-) diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index b2720add..c16eef35 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -107,7 +107,7 @@ class CMap0_T : public MapBase } /******************************************************************************* - * High-level embedded operations + * High-level embedded and topological operations *******************************************************************************/ public: diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 2d2050b1..5a4c03f6 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -195,7 +195,7 @@ class CMap1_T : public CMap0_T } /******************************************************************************* - * High-level topological operations + * High-level embedded and topological operations *******************************************************************************/ protected: @@ -216,6 +216,36 @@ class CMap1_T : public CMap0_T return d; } +public: + + /*! + * \brief Add an embedded face in the map. + * \param size : the number of darts in the built face + * \return A dart of the built face. If the map has DART or FACE attributes, + * the inserted darts are automatically embedded on new attribute elements. + */ + Face add_face(unsigned int size) + { + CGOGN_CHECK_CONCRETE_TYPE; + + Face f(add_face_topo(size)); + + if (this->template is_orbit_embedded()) + { + foreach_dart_of_orbit(f, [this](Dart d) + { + this->template set_orbit_embedding(d, this->template add_attribute_element()); + }); + } + + if (this->template is_orbit_embedded()) + this->set_orbit_embedding(f, this->template add_attribute_element()); + + return f; + } + +protected: + /*! * \brief Remove a face from the map. * \param d : a dart of the face to remove @@ -235,9 +265,9 @@ class CMap1_T : public CMap0_T /** * \brief Cut an edge. - * \param d : a dart of the edge to cut + * \param d : the dart that represents the edge to cut * \return the inserted new dart - * The edge of d is cut by inserting a new dart after d in the PHI orbit. + * The edge of d is cut by inserting a new dart after d in the Phi1 orbit. */ inline Dart cut_edge_topo(Dart d) { @@ -278,52 +308,17 @@ class CMap1_T : public CMap0_T phi1_sew(e, d); // Sew the last edge } - /******************************************************************************* - * High-level embedded operations - *******************************************************************************/ - -public: - - /*! - * \brief Add a face in the map. - * \param size : the number of darts in the built face - * \return A dart of the built face - */ - Face add_face(unsigned int size) - { - cgogn_message_assert(size > 0, "Cannot create an empty face"); - - return this->to_concrete()->add_face_update_emb(this->add_face_topo(size)); - } - inline unsigned int degree(Face f) const { return this->nb_darts(f); } -protected: - - Face add_face_update_emb(Face f) - { - CGOGN_CHECK_CONCRETE_TYPE; - if (this->template is_orbit_embedded()) - { - foreach_dart_of_orbit(f, [this](Dart d) - { - this->template set_orbit_embedding(d, this->template add_attribute_element()); - }); - } - - if (this->template is_orbit_embedded()) - this->set_orbit_embedding(f, this->template add_attribute_element()); - - return f; - } - /******************************************************************************* * Orbits traversal *******************************************************************************/ +protected: + template inline void foreach_dart_of_PHI1(Dart d, const FUNC& f) const { @@ -396,19 +391,21 @@ class CMap1_T : public CMap0_T * Incidence traversal *******************************************************************************/ - template - inline void foreach_incident_vertex(Face f, const FUNC& func) const - { - static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); - foreach_dart_of_orbit(f, func); - } +// To remove : on a pas la notion de Vertex ou de Edge ici ... - template - inline void foreach_incident_edge(Face f, const FUNC& func) const - { - static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); - foreach_dart_of_orbit(f, func); - } +// template +// inline void foreach_incident_vertex(Face f, const FUNC& func) const +// { +// static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); +// foreach_dart_of_orbit(f, func); +// } + +// template +// inline void foreach_incident_edge(Face f, const FUNC& func) const +// { +// static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); +// foreach_dart_of_orbit(f, func); +// } /******************************************************************************* * Adjacence traversal diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 6e163c10..2479a7db 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -172,17 +172,23 @@ class CMap2_T : public CMap1_T } /******************************************************************************* - * High-level topological operations + * High-level embedded and topological operations *******************************************************************************/ protected: + /** + * \brief Cut an edge. + * \param d : A dart that represents the edge to cut + * \return A dart of the inserted vertex + * The edge of d is cut by inserting a new vertex. + * The returned dart is the dart of the inserted vertex that belongs to the face of d. + */ inline Dart cut_edge_topo(Dart d) { Dart e = phi2(d); // Get the adjacent 1D-edge - phi2_unsew(d); // Unsew the initial 2D-edge, - // separating its two 1D-edges + phi2_unsew(d); // Unsew the 2D-edge separating its two 1D-edges Dart nd = Inherit::cut_edge_topo(d); Dart ne = Inherit::cut_edge_topo(e); // Cut the two adjacent 1D-edges @@ -192,153 +198,100 @@ class CMap2_T : public CMap1_T return nd; } - /** - * @brief Split the face of d and e by inserting an edge between the vertex of d and e - * @param d : first vertex - * @param e : second vertex - * Darts d and e should belong to the same face and be distinct from each other. - * An edge made of two new darts is inserted between the two given vertices. - */ - inline void split_face_topo(Dart d, Dart e) - { - cgogn_message_assert(d != e, "split_face: d and e should be distinct"); - cgogn_message_assert(this->same_cell(Face(d), Face(e)), "split_face: d and e should belong to the same face"); - - Dart dd = this->phi_1(d); - Dart ee = this->phi_1(e); - Dart nd = Inherit::cut_edge_topo(dd); // cut the edge before d (insert a new dart before d) - Dart ne = Inherit::cut_edge_topo(ee); // cut the edge before e (insert a new dart before e) - this->phi1_sew(dd, ee); // subdivide phi1 cycle at the inserted darts - phi2_sew(nd, ne); // build the new 2D-edge from the inserted darts - } - - inline void close_hole_topo(Dart d) - { - cgogn_message_assert(phi2(d) == d, "CMap2: close hole called on a dart that is not a phi2 fix point"); - - Dart first = this->add_dart_internal(); // First edge of the face that will fill the hole - phi2_sew(d, first); // phi2-link the new edge to the hole - - Dart d_next = d; // Turn around the hole - Dart d_phi1; // to complete the face - do - { - do - { - d_phi1 = this->phi1(d_next); // Search and put in d_next - d_next = phi2(d_phi1); // the next dart of the hole - } while (d_next != d_phi1 && d_phi1 != d); - - if (d_phi1 != d) - { - Dart next = this->add_dart_internal(); // Add a new edge there and link it to the face - this->phi1_sew(first, next); // the edge is linked to the face - phi2_sew(d_next, next); // the face is linked to the hole - } - } while (d_phi1 != d); - } - - /******************************************************************************* - * High-level embedded operations - *******************************************************************************/ - -protected: +public: /** - * @brief close_map closes the map so that there are no phi2 fix points + * \brief Cut an embedded edge. + * \param d : A dart that represents the edge to cut + * \return A dart of the inserted vertex + * The edge of d is cut by inserting a new vertex. + * The returned dart is the dart of the inserted vertex that belongs to the face of d. + * If the map has DART, VERTEX, EDGE, FACE or VOLUME attributes, + * the inserted darts are automatically embedded on new attribute elements. + * Actually a VERTEX attribute is created, if needed, for the inserted vertex. */ - void close_map() - { - CGOGN_CHECK_CONCRETE_TYPE; - - for (Dart d : *this) - { - if (phi2(d) == d) - { - close_hole_topo(d); - const Dart new_face = phi2(d); - - if (this->template is_orbit_embedded()) - { - foreach_dart_of_orbit(new_face, [this] (Dart fd) - { - this->template set_orbit_embedding(fd, this->template add_attribute_element()); - }); - } - if (this->template is_orbit_embedded()) - { - foreach_dart_of_orbit(new_face, [this] (Dart fd) - { - this->template set_embedding(fd, this->template get_embedding(this->phi1(phi2(fd)))); - }); - } - if (this->template is_orbit_embedded()) - { - foreach_dart_of_orbit(new_face, [this] (Dart fd) - { - this->template set_embedding(fd, this->template get_embedding(phi2(fd))); - }); - } - if (this->template is_orbit_embedded()) - { - this->template set_orbit_embedding(new_face, this->template add_attribute_element()); - } - if (this->template is_orbit_embedded()) - { - const unsigned int idx = this->template get_embedding(d); - foreach_dart_of_orbit(new_face, [this, idx] (Dart fd) - { - this->template set_embedding(fd, idx); - }); - } - } - } - } - - inline Vertex cut_edge_update_emb(Dart e, Dart e2, Dart nd) + inline Vertex cut_edge(Edge e) { CGOGN_CHECK_CONCRETE_TYPE; - const Dart ne = phi2(e); - const Vertex v(nd); + const Dart ne = cut_edge_topo(e); + const Dart nf = phi2(e); if(this->template is_orbit_embedded()) { - this->template set_embedding(nd, this->template add_attribute_element()); this->template set_embedding(ne, this->template add_attribute_element()); + this->template set_embedding(nf, this->template add_attribute_element()); } if (this->template is_orbit_embedded()) { - this->set_orbit_embedding(v, this->template add_attribute_element()); + this->template set_orbit_embedding(ne, this->template add_attribute_element()); } if (this->template is_orbit_embedded()) { - this->template set_embedding(ne, this->template get_embedding(e)); - this->set_orbit_embedding(Edge(nd), this->template add_attribute_element()); + this->template set_embedding(nf, this->template get_embedding(e)); + this->template set_orbit_embedding(ne, this->template add_attribute_element()); } if (this->template is_orbit_embedded()) { - this->template set_embedding(nd, this->template get_embedding(e)); - this->template set_embedding(ne, this->template get_embedding(e2)); + this->template set_embedding(ne, this->template get_embedding(e.dart)); + this->template set_embedding(nf, this->template get_embedding(this->phi_1(nf))); } if (this->template is_orbit_embedded()) { - const unsigned int idx = this->template get_embedding(e); - this->template set_embedding(nd, idx); + const unsigned int idx = this->template get_embedding(e.dart); this->template set_embedding(ne, idx); + this->template set_embedding(nf, idx); } - return v; + return Vertex(ne); + } + +protected: + + /** + * \brief Split the face of d and e by inserting an edge between the vertex of d and e + * \param d : first vertex + * \param e : second vertex + * Darts d and e should belong to the same face and be distinct from each other. + * An edge made of two new darts is inserted between the two given vertices. + */ + inline void split_face_topo(Dart d, Dart e) + { + cgogn_message_assert(d != e, "split_face: d and e should be distinct"); + cgogn_message_assert(this->same_cell(Face(d), Face(e)), "split_face: d and e should belong to the same face"); + + Dart dd = this->phi_1(d); + Dart ee = this->phi_1(e); + Dart nd = Inherit::cut_edge_topo(dd); // cut the edge before d (insert a new dart before d) + Dart ne = Inherit::cut_edge_topo(ee); // cut the edge before e (insert a new dart before e) + this->phi1_sew(dd, ee); // subdivide phi1 cycle at the inserted darts + phi2_sew(nd, ne); // build the new 2D-edge from the inserted darts } - inline void split_face_update_emb(Dart d, Dart e) +public: + + /** + * \brief Split an enbedded face by inserting an edge between the vertices d and e + * \param d : first vertex + * \param e : second vertex + * The vertices d and e should belong to the same face and be distinct from each other. + * An edge made of two new darts is inserted between the two given vertices. + * If the map has DART, VERTEX, EDGE, FACE or VOLUME attributes, + * the inserted darts are automatically embedded on new attribute elements. + * Actually an EDGE attribute is created, if needed, for the inserted edge + * and a new FACE attribute is created for the subdived face that e belongs to. + * The FACE attribute of the subdived face that d belongs to is kept unchanged. + */ + inline void split_face(Vertex d, Vertex e) { CGOGN_CHECK_CONCRETE_TYPE; - const Dart nd = this->phi_1(e); - const Dart ne = this->phi_1(d); + + split_face_topo(d,e); + const Dart nd = this->phi_1(d); + const Dart ne = this->phi_1(e); if(this->template is_orbit_embedded()) { @@ -348,8 +301,8 @@ class CMap2_T : public CMap1_T if (this->template is_orbit_embedded()) { - this->template set_embedding(nd, this->template get_embedding(d)); - this->template set_embedding(ne, this->template get_embedding(e)); + this->template set_embedding(nd, this->template get_embedding(e)); + this->template set_embedding(ne, this->template get_embedding(d)); } if (this->template is_orbit_embedded()) @@ -359,24 +312,60 @@ class CMap2_T : public CMap1_T if (this->template is_orbit_embedded()) { - this->template set_embedding(ne, this->template get_embedding(d)); - this->template set_orbit_embedding(e, this->template add_attribute_element()); + this->template set_embedding(nd, this->template get_embedding(d.dart)); + this->template set_orbit_embedding(ne, this->template add_attribute_element()); } if (this->template is_orbit_embedded()) { - const unsigned int idx = this->template get_embedding(d); + const unsigned int idx = this->template get_embedding(d.dart); this->template set_orbit_embedding(nd, idx); this->template set_orbit_embedding(ne, idx); } } - inline Face add_face_update_emb(Face f) +protected: + + /*! + * \brief Add an embedded face in the map. + * \param size : the number of darts in the built face + * \return A dart of the built face. + */ + Dart add_face_topo(unsigned int size) + { + Dart d = Inherit::add_face_topo(size); + Dart e = Inherit::add_face_topo(size); + + Dart it = d; + do + { + phi2_sew(it, e); + it = this->phi1(it); + e = this->phi_1(e); + } while (it != d); + + return d; + } + +public: + + /*! + * \brief Add a face in the map. + * \param size : the number of edges in the built face + * \return A dart of the built face + * If the map has DART, VERTEX, EDGE, FACE or VOLUME attributes, + * the inserted darts are automatically embedded on new attribute elements. + * Actually a FACE attribute is created, if needed, for the new face. + */ + Face add_face(unsigned int size) { CGOGN_CHECK_CONCRETE_TYPE; + + Dart d = add_face_topo(size); + if (this->template is_orbit_embedded()) { - this->foreach_dart_of_orbit(f, [this] (Dart df) + this->foreach_dart_of_orbit(d, [this] (Dart df) { this->template set_orbit_embedding(df, this->template add_attribute_element()); }); @@ -384,70 +373,112 @@ class CMap2_T : public CMap1_T if (this->template is_orbit_embedded()) { - foreach_incident_vertex(f, [this] (Vertex v) + this->foreach_dart_of_orbit(d, [this] (Vertex v) { - this->set_orbit_embedding(v, this->template add_attribute_element()); + this->template set_orbit_embedding(v, this->template add_attribute_element()); }); } if (this->template is_orbit_embedded()) { - foreach_incident_edge(f, [this] (Edge e) + this->foreach_dart_of_orbit(d, [this] (Edge e) { - this->set_orbit_embedding(e, this->template add_attribute_element()); + this->template set_orbit_embedding(e, this->template add_attribute_element()); }); } if (this->template is_orbit_embedded()) - this->set_orbit_embedding(f, this->template add_attribute_element()); + this->template set_orbit_embedding(d, this->template add_attribute_element()); if (this->template is_orbit_embedded()) - this->set_orbit_embedding(Volume(f.dart), this->template add_attribute_element()); + this->template set_orbit_embedding(d, this->template add_attribute_element()); - return f; + return Face(d); } -public: +protected: - Face add_face(unsigned int nb_edges) + inline void close_hole_topo(Dart d) { - cgogn_message_assert(nb_edges > 0, "Cannot create a face with no edge"); + cgogn_message_assert(phi2(d) == d, "CMap2: close hole called on a dart that is not a phi2 fix point"); - Dart d = Inherit::add_face_topo(nb_edges); - Dart b = Inherit::add_face_topo(nb_edges); + Dart first = this->add_dart_internal(); // First edge of the face that will fill the hole + phi2_sew(d, first); // phi2-link the new edge to the hole - Dart it = d; + Dart d_next = d; // Turn around the hole + Dart d_phi1; // to complete the face do { - phi2_sew(it, b); - it = this->phi1(it); - b = this->phi_1(b); - } while (it != d); + do + { + d_phi1 = this->phi1(d_next); // Search and put in d_next + d_next = phi2(d_phi1); // the next dart of the hole + } while (d_next != d_phi1 && d_phi1 != d); - return this->to_concrete()->add_face_update_emb(d); + if (d_phi1 != d) + { + Dart next = this->add_dart_internal(); // Add a new edge there and link it to the face + this->phi1_sew(first, next); // the edge is linked to the face + phi2_sew(d_next, next); // the face is linked to the hole + } + } while (d_phi1 != d); } - inline Vertex cut_edge(Edge e) - { - const Dart e2 = phi2(e); - const Dart nd = cut_edge_topo(e); - - return this->to_concrete()->cut_edge_update_emb(e.dart, e2, nd); - } +protected: /** - * @brief Split the face of d and e by inserting an edge between the vertex of d and e - * @param d : first vertex - * @param e : second vertex - * Darts d and e should belong to the same face and be distinct from each other. - * An edge made of two new darts is inserted between the two given vertices. + * @brief close_map closes the map so that there are no phi2 fix points */ - inline void split_face(Dart d, Dart e) + void close_map() { - split_face_topo(d,e); - this->to_concrete()->split_face_update_emb(d,e); + CGOGN_CHECK_CONCRETE_TYPE; + + for (Dart d : *this) + { + if (phi2(d) == d) + { + close_hole_topo(d); + const Dart new_face = phi2(d); + + if (this->template is_orbit_embedded()) + { + foreach_dart_of_orbit(new_face, [this] (Dart fd) + { + this->template set_orbit_embedding(fd, this->template add_attribute_element()); + }); + } + if (this->template is_orbit_embedded()) + { + foreach_dart_of_orbit(new_face, [this] (Dart fd) + { + this->template set_embedding(fd, this->template get_embedding(this->phi1(phi2(fd)))); + }); + } + if (this->template is_orbit_embedded()) + { + foreach_dart_of_orbit(new_face, [this] (Dart fd) + { + this->template set_embedding(fd, this->template get_embedding(phi2(fd))); + }); + } + if (this->template is_orbit_embedded()) + { + this->template set_orbit_embedding(new_face, this->template add_attribute_element()); + } + if (this->template is_orbit_embedded()) + { + const unsigned int idx = this->template get_embedding(d); + foreach_dart_of_orbit(new_face, [this, idx] (Dart fd) + { + this->template set_embedding(fd, idx); + }); + } + } + } } +public: + inline unsigned int degree(Face f) const { return Inherit::degree(f); @@ -623,7 +654,7 @@ class CMap2_T : public CMap1_T if (!marker.is_marked(d)) { marker.template mark_orbit(d); - f(d); + f(Cell(d)); } }); } diff --git a/cgogn/geometry/algos/normal.h b/cgogn/geometry/algos/normal.h index 016672cb..c7e6445d 100644 --- a/cgogn/geometry/algos/normal.h +++ b/cgogn/geometry/algos/normal.h @@ -83,7 +83,7 @@ inline VEC3 vertex_normal(const MAP& map, Cell v, const typename M VEC3 n{0,0,0}; const VEC3& p = position[v.dart]; // map.foreach_incident_face(v, [&] (Cell f) - map.foreach_incident_cell(v, [&] (Cell f) + map.template foreach_incident_cell(v, [&] (Cell f) { VEC3 facen = face_normal(map, f, position); const VEC3& p1 = position[map.phi1(f.dart)]; @@ -105,7 +105,7 @@ inline VEC3 vertex_normal(const MAP& map, Cell v, const typename M VEC3 n{0,0,0}; const VEC3& p = position[v.dart]; // map.foreach_incident_face(v, [&] (Cell f) - map.foreach_incident_cell(v, [&] (Cell f) + map.template foreach_incident_cell(v, [&] (Cell f) { VEC3 facen = fnormal[f]; const VEC3& p1 = position[map.phi1(f.dart)]; diff --git a/cgogn/multiresolution/cph/ihcmap2_adaptive.h b/cgogn/multiresolution/cph/ihcmap2_adaptive.h index 3484e378..e3a032e5 100644 --- a/cgogn/multiresolution/cph/ihcmap2_adaptive.h +++ b/cgogn/multiresolution/cph/ihcmap2_adaptive.h @@ -354,7 +354,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T Inherit::set_current_level(eLevel + 1); - this->cut_edge(d); + this->cut_edge_topo(d); unsigned int eId = Inherit::get_edge_id(d); Inherit::set_edge_id(Inherit::phi1(d), eId); Inherit::set_edge_id(Inherit::phi1(dd), eId); @@ -435,7 +435,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T // (*vertexVertexFunctor)(e) ; e = Inherit::phi1(e); - this->split_face(dd,e); + this->split_face_topo(dd,e); unsigned int id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id); // set the edge id of the inserted @@ -445,7 +445,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T e = Inherit::phi1(dd); // (*vertexVertexFunctor)(e); e = Inherit::phi1(e); - this->split_face(dd,e); + this->split_face_topo(dd,e); id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id); Inherit::set_edge_id(Inherit::phi_1(e), id); @@ -454,7 +454,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T e = Inherit::phi1(dd); // (*vertexVertexFunctor)(e); e = Inherit::phi1(e); - this->split_face(dd,e); + this->split_face_topo(dd,e); id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id); Inherit::set_edge_id(Inherit::phi_1(e), id); @@ -465,10 +465,10 @@ class IHCMap2Adaptive_T : public IHCMap2_T Dart next = this->phi1(dd); // (*vertexVertexFunctor)(next); next = Inherit::phi1(next); - this->split_face(dd,next); // insert a first edge + this->split_face_topo(dd,next); // insert a first edge Dart ne = Inherit::phi2(Inherit::phi_1(dd)); Dart ne2 = Inherit::phi2(ne); - this->cut_edge(ne); // cut the new edge to insert the central vertex + this->cut_edge_topo(ne); // cut the new edge to insert the central vertex unsigned int id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(ne))); Inherit::set_edge_id(ne, id); @@ -484,7 +484,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T dd = Inherit::phi1(dd); while(dd != ne) // turn around the face and insert new edges { // linked to the central vertex - this->split_face(Inherit::phi1(ne), dd); + this->split_face_topo(Inherit::phi1(ne), dd); Dart nne = Inherit::phi2(Inherit::phi_1(dd)); id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(nne))); From b5aa1b5b2f90643e0cb5d24051dc3552c70bb450 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Tue, 16 Feb 2016 18:19:16 +0100 Subject: [PATCH 110/402] export off, off_bin & obj --- cgogn/core/cmap/attribute_handler.h | 9 + cgogn/core/container/chunk_array.h | 9 + cgogn/io/CMakeLists.txt | 1 + cgogn/io/map_export.h | 300 ++++++++++++++++++++++++++++ 4 files changed, 319 insertions(+) create mode 100644 cgogn/io/map_export.h diff --git a/cgogn/core/cmap/attribute_handler.h b/cgogn/core/cmap/attribute_handler.h index 8e3a436f..07131519 100644 --- a/cgogn/core/cmap/attribute_handler.h +++ b/cgogn/core/cmap/attribute_handler.h @@ -349,6 +349,15 @@ class AttributeHandler : public AttributeHandlerOrbit return chunk_array_; } + /** + * \brief getDataVector + * @return + */ + TChunkArray* get_data() + { + return chunk_array_; + } + /** * \brief operator [] * @param c diff --git a/cgogn/core/container/chunk_array.h b/cgogn/core/container/chunk_array.h index b68de742..a22570f1 100644 --- a/cgogn/core/container/chunk_array.h +++ b/cgogn/core/container/chunk_array.h @@ -381,6 +381,15 @@ class ChunkArray : public ChunkArrayGen cgogn_assert(i / CHUNKSIZE < table_data_.size()); table_data_[i / CHUNKSIZE][i % CHUNKSIZE] = v; } + + inline void set_all_values( const T& v) + { + for(T* chunk : table_data_) + { + for(unsigned int i=0; i +#include +#include +#include + + + +#include +//#include + + + +namespace cgogn +{ + +namespace io +{ + +//template +//void export_surface(cgogn::CMap2& cmap2, const std::string& filename); + +/** + * @brief export surface in off format + * @param map the map to export + * @param position the position attribute of vertices + * @param filename the name of file to save + * @return ok ? + */ +template +bool export_off(MAP& map, const typename MAP::template VertexAttributeHandler& position, const std::string& filename) +{ + + std::ofstream fp(filename.c_str(), std::ios::out); + if (!fp.good()) + { + std::cout << "Unable to open file " << filename << std::endl; + return false; + } + + fp << "OFF"<< std::endl; + fp << map.template nb_cells() << " "<< map.template nb_cells() << " 0"<< std::endl; // nb_edge unused ? + + // set precision for real output + fp<< std::setprecision(12); + + // two pass of traversal to avoid huge buffer (with same performance); + + // first pass to save positions & store contiguous indices + typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); + ids.get_data()->set_all_values(0xffffffff); + unsigned int count = 0; + map.template foreach_cell([&] (typename MAP::Face f) + { + map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) + { + if (ids[v]==0xffffffff) + { + ids[v] = count++; + const VEC3& P = position[v]; + fp << P[0] << " " << P[1] << " " << P[2] << std::endl; + } + }); + }); + + // second pass to save primitives + std::vector prim; + prim.reserve(20); + map.template foreach_cell([&] (typename MAP::Face f) + { + unsigned int valence = 0; + prim.clear(); + + map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) + { + prim.push_back(ids[v]); + ++valence; + }); + fp << valence; + for(unsigned int i: prim) + fp << " " << i; + fp << std::endl; + + }); + + map.remove_attribute(ids); + fp.close(); + return true; +} + + +/** + * @brief export surface in off format + * @param map the map to export + * @param position the position attribute of vertices + * @param filename the name of file to save + * @return ok ? + */ +template +bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandler& position, const std::string& filename) +{ + + // local function for little/big endian conversion + auto changeEndianness = [](unsigned int x) -> unsigned int + { + return (x>>24) | ((x<<8) & 0x00FF0000) | ((x>>8) & 0x0000FF00) | (x<<24); + }; + + + std::ofstream fp(filename.c_str(), std::ios::out|std::ofstream::binary); + if (!fp.good()) + { + std::cout << "Unable to open file " << filename << std::endl; + return false; + } + + fp << "OFF BINARY"<< std::endl; + + unsigned int nb_cells[3]; + nb_cells[0] = changeEndianness(map.template nb_cells()); + nb_cells[1] = changeEndianness(map.template nb_cells()); + nb_cells[2] = 0; + + fp.write(reinterpret_cast(nb_cells),3*sizeof(unsigned int)); + + // two pass of traversal to avoid huge buffer (with same performance); + + // first pass to save positions & store contiguous indices + typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); + ids.get_data()->set_all_values(0xffffffff); + unsigned int count = 0; + + static const unsigned int BUFFER_SZ = 1024*1024; + + std::vector buffer_pos; + buffer_pos.reserve(BUFFER_SZ+3); + + map.template foreach_cell([&] (typename MAP::Face f) + { + map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) + { + if (ids[v]==0xffffffff) + { + ids[v] = count++; + VEC3 P = position[v]; + // VEC3 can be double ! + float Pf[3]={float(P[0]),float(P[1]),float(P[2])}; + unsigned int* ui_vec = reinterpret_cast(Pf); + ui_vec[0] = changeEndianness(ui_vec[0]); + ui_vec[1] = changeEndianness(ui_vec[1]); + ui_vec[2] = changeEndianness(ui_vec[2]); + + buffer_pos.push_back(Pf[0]); + buffer_pos.push_back(Pf[1]); + buffer_pos.push_back(Pf[2]); + + if (buffer_pos.size() >= BUFFER_SZ) + { + fp.write(reinterpret_cast(&(buffer_pos[0])),buffer_pos.size()*sizeof(float)); + buffer_pos.clear(); + } + } + }); + }); + if (!buffer_pos.empty()) + { + fp.write(reinterpret_cast(&(buffer_pos[0])),buffer_pos.size()*sizeof(float)); + buffer_pos.clear(); + buffer_pos.shrink_to_fit(); + } + + // second pass to save primitives + std::vector buffer_prims; + buffer_prims.reserve(BUFFER_SZ+128);// + 128 to avoid re-allocations + + std::vector prim; + prim.reserve(20); + map.template foreach_cell([&] (typename MAP::Face f) + { + unsigned int valence = 0; + prim.clear(); + + map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) + { + prim.push_back(ids[v]); + ++valence; + }); + + buffer_prims.push_back(changeEndianness(valence)); + for(unsigned int i: prim) + buffer_prims.push_back(changeEndianness(i)); + + if (buffer_prims.size() >= BUFFER_SZ) + { + fp.write(reinterpret_cast(&(buffer_prims[0])),buffer_prims.size()*sizeof(unsigned int)); + buffer_prims.clear(); + } + }); + if (!buffer_prims.empty()) + { + fp.write(reinterpret_cast(&(buffer_prims[0])),buffer_prims.size()*sizeof(unsigned int)); + buffer_prims.clear(); + buffer_prims.shrink_to_fit(); + } + + map.remove_attribute(ids); + fp.close(); + return true; +} + + + +/** + * @brief export surface in obj format + * @param map the map to export + * @param position the position attribute of vertices + * @param filename the name of file to save + * @return ok ? + */ +template +bool export_obj(MAP& map, const typename MAP::template VertexAttributeHandler& position, const std::string& filename) +{ + std::ofstream fp(filename.c_str(), std::ios::out); + if (!fp.good()) + { + std::cout << "Unable to open file " << filename << std::endl; + return false; + } + + // set precision for float output + fp<< std::setprecision(12); + + // two passes of traversal to avoid huge buffer (with same performance); + // first pass to save positions & store contiguous indices (from 1 because of obj format) + typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); + ids.get_data()->set_all_values(0xffffffff); + unsigned int count = 1; + map.template foreach_cell([&] (typename MAP::Face f) + { + map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) + { + if (ids[v]==0xffffffff) + { + ids[v] = count++; + const VEC3& P = position[v]; + fp <<"v " << P[0] << " " << P[1] << " " << P[2] << std::endl; + } + }); + }); + + // second pass to save primitives + std::vector prim; + prim.reserve(20); + map.template foreach_cell([&] (typename MAP::Face f) + { + fp << "f"; + map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) + { + fp << " " << ids[v]; + }); + fp << std::endl; + }); + + map.remove_attribute(ids); + fp.close(); + return true; +} + + + +} // namespace io + +} // namespace cgogn + +#endif // IO_MAP_IMPORT_H_ From 1f9d39f3915c2241d0c317f6e7ba5d653c390a9f Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Tue, 16 Feb 2016 18:22:10 +0100 Subject: [PATCH 111/402] Foreach_incident_cell() sans test multiincidence --- cgogn/core/cmap/cmap2.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 2479a7db..975c6efe 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -648,14 +648,9 @@ class CMap2_T : public CMap1_T static_assert(check_func_parameter_type(FUNC, Cell), "Wrong function cell parameter type"); - DartMarkerStore marker(*this); foreach_dart_of_orbit(v, [&] (Dart d) { - if (!marker.is_marked(d)) - { - marker.template mark_orbit(d); f(Cell(d)); - } }); } From a796506ab38417dafbd31122a57b488619b541e7 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Tue, 16 Feb 2016 18:34:21 +0100 Subject: [PATCH 112/402] Declare only Cell types with clear and distinct ORBIT --- cgogn/core/cmap/cmap0.h | 17 +---------------- cgogn/core/cmap/cmap1.h | 12 +----------- cgogn/core/cmap/cmap2.h | 5 +++++ cgogn/core/examples/map/map.cpp | 4 ++-- cgogn/core/tests/cmap/cmap1_test.cpp | 8 -------- 5 files changed, 9 insertions(+), 37 deletions(-) diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index c16eef35..6fc5a525 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -46,15 +46,6 @@ class CMap0_T : public MapBase friend class DartMarker_T; static const Orbit DART = Orbit::DART; - static const Orbit VERTEX = Orbit::DART; - static const Orbit EDGE = Orbit::DART; - static const Orbit FACE = Orbit::DART; - static const Orbit VOLUME = Orbit::DART; - - typedef Cell Vertex; - typedef Cell Edge; - typedef Cell Face; - typedef Cell Volume; template using ChunkArray = typename Inherit::template ChunkArray; @@ -64,13 +55,7 @@ class CMap0_T : public MapBase template using AttributeHandler = typename Inherit::template AttributeHandler; template - using VertexAttributeHandler = AttributeHandler; - template - using EdgeAttributeHandler = AttributeHandler; - template - using FaceAttributeHandler = AttributeHandler; - template - using VolumeAttributeHandler = AttributeHandler; + using DartAttributeHandler = AttributeHandler; using DartMarker = typename cgogn::DartMarker; using DartMarkerStore = typename cgogn::DartMarkerStore; diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 5a4c03f6..a97714d3 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -51,15 +51,9 @@ class CMap1_T : public CMap0_T friend class DartMarkerStore; static const Orbit DART = Orbit::DART; - static const Orbit VERTEX = Orbit::DART; - static const Orbit EDGE = Orbit::DART; static const Orbit FACE = Orbit::PHI1; - static const Orbit VOLUME = Orbit::PHI1; - typedef Cell Vertex; - typedef Cell Edge; typedef Cell Face; - typedef Cell Volume; template using ChunkArray = typename Inherit::template ChunkArray; @@ -69,13 +63,9 @@ class CMap1_T : public CMap0_T template using AttributeHandler = typename Inherit::template AttributeHandler; template - using VertexAttributeHandler = AttributeHandler; - template - using EdgeAttributeHandler = AttributeHandler; + using DartAttributeHandler = AttributeHandler; template using FaceAttributeHandler = AttributeHandler; - template - using VolumeAttributeHandler = AttributeHandler; using DartMarker = typename cgogn::DartMarker; using DartMarkerStore = typename cgogn::DartMarkerStore; diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 975c6efe..893ea4e5 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -484,6 +484,11 @@ class CMap2_T : public CMap1_T return Inherit::degree(f); } + inline unsigned int degree(Vertex v) const + { + return this->nb_darts(v); + } + /******************************************************************************* * Orbits traversal *******************************************************************************/ diff --git a/cgogn/core/examples/map/map.cpp b/cgogn/core/examples/map/map.cpp index f39c8528..e8c143ea 100644 --- a/cgogn/core/examples/map/map.cpp +++ b/cgogn/core/examples/map/map.cpp @@ -135,10 +135,10 @@ int test1(MAP& map) int main() { - Map1 map1; +// Map1 map1; Map2 map2; // Map3 map3; - test1(map1); +// test1(map1); test1(map2); // test1(map3); diff --git a/cgogn/core/tests/cmap/cmap1_test.cpp b/cgogn/core/tests/cmap/cmap1_test.cpp index 5814f24f..d0b76daf 100644 --- a/cgogn/core/tests/cmap/cmap1_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_test.cpp @@ -36,8 +36,6 @@ class CMap1Test: public ::testing::Test public: typedef CMap1 myCMap1; - typedef myCMap1::Vertex Vertex; - typedef myCMap1::Edge Edge; typedef myCMap1::Face Face; protected: @@ -55,14 +53,8 @@ TEST_F(CMap1Test, addFace) // cmap_.cut_edge(Edge(f)); - EXPECT_TRUE(is_well_embedded(cmap_)); - EXPECT_TRUE(is_well_embedded(cmap_)); EXPECT_TRUE(is_well_embedded(cmap_)); - EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); - EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); - EXPECT_TRUE(is_container_well_referenced(cmap_)); - EXPECT_TRUE(is_container_well_referenced(cmap_)); EXPECT_TRUE(is_container_well_referenced(cmap_)); } From 8683fb42575063d0c9f043321d66d56bb6422ffe Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Wed, 17 Feb 2016 10:48:27 +0100 Subject: [PATCH 113/402] Replace ambigous add_dart_internal method with init_dart() --- cgogn/core/cmap/cmap0.h | 7 +++---- cgogn/core/cmap/cmap1.h | 11 +++++------ cgogn/core/cmap/cmap2.h | 31 +++++++++++++++++++------------ cgogn/core/cmap/cmap3.h | 5 ++--- cgogn/core/cmap/map_base.h | 8 +++++--- 5 files changed, 34 insertions(+), 28 deletions(-) diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index 6fc5a525..63ad4d5b 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -86,9 +86,8 @@ class CMap0_T : public MapBase * \brief Add a Dart in the map (i.e. add a line in the topology container) * @return the new Dart (i.e. the index of the added line) */ - inline Dart add_dart_internal() + inline void init_dart(Dart d) { - return Dart(this->add_topology_element()); } /******************************************************************************* @@ -103,10 +102,10 @@ class CMap0_T : public MapBase * If a DART attribute has been added to the Map, * the inserted Dart is embedded on a new attribute element. */ - Dart add_dart() + Dart add_embedded_dart() { CGOGN_CHECK_CONCRETE_TYPE; - const Dart d = this->add_dart_internal(); + const Dart d = this->add_dart(); if (this->template is_orbit_embedded()) this->template set_embedding(d, this->template add_attribute_element()); diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index a97714d3..39aff801 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -110,12 +110,11 @@ class CMap1_T : public CMap0_T * @return the new Dart (i.e. the index of the added line) * The dart is defined as a fixed point for PHI1. */ - inline Dart add_dart_internal() + inline void init_dart(Dart d) { - Dart d = Inherit::add_dart_internal(); + Inherit::init_dart(d); (*phi1_)[d.index] = d; (*phi_1_)[d.index] = d; - return d; } /*! @@ -199,7 +198,7 @@ class CMap1_T : public CMap0_T { cgogn_message_assert(size > 0u, "Cannot create an empty face"); - Dart d = this->add_dart_internal(); + Dart d = this->add_dart(); for (unsigned int i = 1u; i < size; ++i) cut_edge_topo(d); @@ -261,8 +260,8 @@ class CMap1_T : public CMap0_T */ inline Dart cut_edge_topo(Dart d) { - Dart e = this->add_dart_internal(); // Create a new dart e - phi1_sew(d, e); // Insert e between d and phi1(d) + Dart e = this->add_dart(); // Create a new dart e + phi1_sew(d, e); // Insert e between d and phi1(d) return e; } diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 893ea4e5..6d3eb73d 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -121,11 +121,10 @@ class CMap2_T : public CMap1_T * @return the new Dart (i.e. the index of the added line) * The dart is defined as a fixed point for PHI2. */ - inline Dart add_dart_internal() + inline void init_dart(Dart d) { - Dart d = Inherit::add_dart_internal(); + Inherit::init_dart(d); (*phi2_)[d.index] = d; - return d; } /** @@ -249,6 +248,14 @@ class CMap2_T : public CMap1_T return Vertex(ne); } +protected: + void merge_adjacent_edge(Dart d) { + Dart e = this->phi_1(this->phi2(d)); + cgogn_message_assert(d == this->phi_1(this->phi2(e)), + "merge_adjacent_edge: the degree of the vertex of d should be 2"); + + } + protected: /** @@ -402,24 +409,24 @@ class CMap2_T : public CMap1_T { cgogn_message_assert(phi2(d) == d, "CMap2: close hole called on a dart that is not a phi2 fix point"); - Dart first = this->add_dart_internal(); // First edge of the face that will fill the hole - phi2_sew(d, first); // phi2-link the new edge to the hole + Dart first = this->add_dart(); // First edge of the face that will fill the hole + phi2_sew(d, first); // phi2-link the new edge to the hole - Dart d_next = d; // Turn around the hole - Dart d_phi1; // to complete the face + Dart d_next = d; // Turn around the hole + Dart d_phi1; // to complete the face do { do { - d_phi1 = this->phi1(d_next); // Search and put in d_next - d_next = phi2(d_phi1); // the next dart of the hole + d_phi1 = this->phi1(d_next); // Search and put in d_next + d_next = phi2(d_phi1); // the next dart of the hole } while (d_next != d_phi1 && d_phi1 != d); if (d_phi1 != d) { - Dart next = this->add_dart_internal(); // Add a new edge there and link it to the face - this->phi1_sew(first, next); // the edge is linked to the face - phi2_sew(d_next, next); // the face is linked to the hole + Dart next = this->add_dart(); // Add a new edge there and link it to the face + this->phi1_sew(first, next); // the edge is linked to the face + phi2_sew(d_next, next); // the face is linked to the hole } } while (d_phi1 != d); } diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 7651d8dd..fa964f11 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -395,11 +395,10 @@ class CMap3_T : public CMap2_T * \brief add a Dart in the map * @return the new Dart */ - inline Dart add_dart_internal() + inline void init_dart(Dart d) { - Dart d = Inherit::add_dart_internal(); + Inherit::init_dart(d); (*phi3_)[d.index] = d; - return d; } public: diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index afb224f7..ab660b16 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -138,7 +138,9 @@ class MapBase : public MapBaseData inline Dart add_dart() { - return this->to_concrete()->add_dart_internal(); + Dart d(this->add_topology_element()); + this->to_concrete()->init_dart(d); + return d; } inline void remove_dart(Dart d) @@ -154,9 +156,9 @@ class MapBase : public MapBaseData { unsigned int idx = this->topology_.template insert_lines(); this->topology_.init_markers_of_line(idx); - for(unsigned int orbit = 0; orbit < NB_ORBITS; ++orbit) + for (unsigned int orbit = 0; orbit < NB_ORBITS; ++orbit) { - if(this->embeddings_[orbit]) + if (this->embeddings_[orbit]) (*this->embeddings_[orbit])[idx] = EMBNULL; } return idx; From 346c2f08a79ce9f6dd182106cc96a16790cc6f36 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Wed, 17 Feb 2016 10:56:52 +0100 Subject: [PATCH 114/402] init_dart for CPH --- cgogn/multiresolution/cph/ihcmap2.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/cgogn/multiresolution/cph/ihcmap2.h b/cgogn/multiresolution/cph/ihcmap2.h index ef9211fc..48660f13 100644 --- a/cgogn/multiresolution/cph/ihcmap2.h +++ b/cgogn/multiresolution/cph/ihcmap2.h @@ -194,10 +194,8 @@ class IHCMap2_T : public CMap2_T, public CPH2, public CPH2 From 66376fb5e0e7af499a3fcba96e5a44adcc05ac82 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Wed, 17 Feb 2016 11:00:33 +0100 Subject: [PATCH 115/402] init_dart for CPH (corrected) --- cgogn/multiresolution/cph/ihcmap2.h | 2 ++ cgogn/multiresolution/cph/ihcmap3.h | 6 ++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cgogn/multiresolution/cph/ihcmap2.h b/cgogn/multiresolution/cph/ihcmap2.h index 48660f13..14301cdf 100644 --- a/cgogn/multiresolution/cph/ihcmap2.h +++ b/cgogn/multiresolution/cph/ihcmap2.h @@ -196,6 +196,8 @@ class IHCMap2_T : public CMap2_T, public CPH2, public CPH3 * \brief add a Dart in the map * @return the new Dart */ - inline Dart add_dart_internal() + inline void init_dart(Dart d) { - Dart d = Inherit_CMAP::add_dart_internal(); + Inherit_CMAP::init_dart(d); Inherit_CPH::set_edge_id(d, 0); Inherit_CPH::set_face_id(d, 0); @@ -215,8 +215,6 @@ class IHCMap3_T :public CMap3_T, public CPH3 } // Inherit_CPH::inc_nb_darts(get_current_level()); - - return d ; } protected: From b8f89652c4a115d10f786812bd816bb44fe70e86 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Wed, 17 Feb 2016 11:39:37 +0100 Subject: [PATCH 116/402] embed DART orbit in init_dart() --- cgogn/core/cmap/cmap0.h | 26 +++++--------------------- cgogn/core/cmap/cmap1.h | 11 +---------- cgogn/core/cmap/cmap2.h | 30 +----------------------------- cgogn/core/cmap/cmap3.h | 8 -------- 4 files changed, 7 insertions(+), 68 deletions(-) diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index 63ad4d5b..3afaee91 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -83,36 +83,20 @@ class CMap0_T : public MapBase protected: /*! - * \brief Add a Dart in the map (i.e. add a line in the topology container) - * @return the new Dart (i.e. the index of the added line) + * \brief Init an newly added dart. + * If a DART attribute has been added to the Map, + * the inserted Dart is embedded on a new attribute element. */ inline void init_dart(Dart d) { + if (this->template is_orbit_embedded()) + this->template set_embedding(d, this->template add_attribute_element()); } /******************************************************************************* * High-level embedded and topological operations *******************************************************************************/ -public: - - /*! - * \brief Add an embedded Dart in the map. - * @return the new inserted Dart - * If a DART attribute has been added to the Map, - * the inserted Dart is embedded on a new attribute element. - */ - Dart add_embedded_dart() - { - CGOGN_CHECK_CONCRETE_TYPE; - const Dart d = this->add_dart(); - - if (this->template is_orbit_embedded()) - this->template set_embedding(d, this->template add_attribute_element()); - - return d; - } - protected: /******************************************************************************* diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 39aff801..ca42d27d 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -106,8 +106,7 @@ class CMap1_T : public CMap0_T protected: /*! - * \brief Add a Dart in the map (i.e. add a line in the topology container) - * @return the new Dart (i.e. the index of the added line) + * \brief Init an newly added dart. * The dart is defined as a fixed point for PHI1. */ inline void init_dart(Dart d) @@ -219,14 +218,6 @@ class CMap1_T : public CMap0_T Face f(add_face_topo(size)); - if (this->template is_orbit_embedded()) - { - foreach_dart_of_orbit(f, [this](Dart d) - { - this->template set_orbit_embedding(d, this->template add_attribute_element()); - }); - } - if (this->template is_orbit_embedded()) this->set_orbit_embedding(f, this->template add_attribute_element()); diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 6d3eb73d..9361116a 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -117,8 +117,7 @@ class CMap2_T : public CMap1_T *******************************************************************************/ /** - * \brief Add a Dart in the map (i.e. add a line in the topology container) - * @return the new Dart (i.e. the index of the added line) + * \brief Init an newly added dart. * The dart is defined as a fixed point for PHI2. */ inline void init_dart(Dart d) @@ -216,12 +215,6 @@ class CMap2_T : public CMap1_T const Dart ne = cut_edge_topo(e); const Dart nf = phi2(e); - if(this->template is_orbit_embedded()) - { - this->template set_embedding(ne, this->template add_attribute_element()); - this->template set_embedding(nf, this->template add_attribute_element()); - } - if (this->template is_orbit_embedded()) { this->template set_orbit_embedding(ne, this->template add_attribute_element()); @@ -300,12 +293,6 @@ class CMap2_T : public CMap1_T const Dart nd = this->phi_1(d); const Dart ne = this->phi_1(e); - if(this->template is_orbit_embedded()) - { - this->template set_embedding(nd, this->template add_attribute_element()); - this->template set_embedding(ne, this->template add_attribute_element()); - } - if (this->template is_orbit_embedded()) { this->template set_embedding(nd, this->template get_embedding(e)); @@ -370,14 +357,6 @@ class CMap2_T : public CMap1_T Dart d = add_face_topo(size); - if (this->template is_orbit_embedded()) - { - this->foreach_dart_of_orbit(d, [this] (Dart df) - { - this->template set_orbit_embedding(df, this->template add_attribute_element()); - }); - } - if (this->template is_orbit_embedded()) { this->foreach_dart_of_orbit(d, [this] (Vertex v) @@ -447,13 +426,6 @@ class CMap2_T : public CMap1_T close_hole_topo(d); const Dart new_face = phi2(d); - if (this->template is_orbit_embedded()) - { - foreach_dart_of_orbit(new_face, [this] (Dart fd) - { - this->template set_orbit_embedding(fd, this->template add_attribute_element()); - }); - } if (this->template is_orbit_embedded()) { foreach_dart_of_orbit(new_face, [this] (Dart fd) diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index fa964f11..20974628 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -294,14 +294,6 @@ class CMap3_T : public CMap2_T close_hole_topo(d); const Dart new_volume = phi3(d); - if (this->template is_orbit_embedded()) - { - foreach_dart_of_orbit(new_volume, [this] (Dart wd) - { - this->template set_orbit_embedding(wd, this->template add_attribute_element()); - }); - } - if (this->template is_orbit_embedded()) // cmap2 vertices { From 99988a1a6ef9809a735b91230c8859fe599ebb03 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Wed, 17 Feb 2016 17:48:07 +0100 Subject: [PATCH 117/402] cleaning of CPH and IHCMap --- cgogn/core/cmap/cmap2.h | 13 +- cgogn/core/cmap/cmap3.h | 96 ++++----- cgogn/multiresolution/cph/cph2.h | 22 +-- cgogn/multiresolution/cph/cph3.h | 13 +- cgogn/multiresolution/cph/cph_base.h | 66 ++++--- cgogn/multiresolution/cph/ihcmap2.h | 197 ++++++++++--------- cgogn/multiresolution/cph/ihcmap2_adaptive.h | 40 +++- cgogn/multiresolution/cph/ihcmap2_regular.h | 19 ++ cgogn/multiresolution/cph/ihcmap3.h | 6 +- cgogn/multiresolution/examples/cph/cph2.cpp | 50 ++--- 10 files changed, 286 insertions(+), 236 deletions(-) diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 9361116a..feefd7e9 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -116,6 +116,8 @@ class CMap2_T : public CMap1_T * Low-level topological operations *******************************************************************************/ +protected: + /** * \brief Init an newly added dart. * The dart is defined as a fixed point for PHI2. @@ -141,7 +143,7 @@ class CMap2_T : public CMap1_T } /** - * \brief Remove the phi2 link of the current dart and its linked dart + * \brief Remove the phi2 link between the current dart and its linked dart * @param d the dart to unlink * - Before: d->e and e->d * - After: d->d and e->e @@ -242,11 +244,16 @@ class CMap2_T : public CMap1_T } protected: - void merge_adjacent_edge(Dart d) { + void merge_adjacent_edges_topo(Dart d) { Dart e = this->phi_1(this->phi2(d)); cgogn_message_assert(d == this->phi_1(this->phi2(e)), "merge_adjacent_edge: the degree of the vertex of d should be 2"); +// TODO + } + void merge_adjacent_faces_topo(Dart d) { + Dart e = this->phi2(d); +// TODO } protected: @@ -832,8 +839,6 @@ extern template class CGOGN_CORE_API CellMarkerStore, Or extern template class CGOGN_CORE_API CellMarkerStore, Orbit::PHI1_PHI2>; #endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_MAP_MAP2_CPP_)) - - } // namespace cgogn #endif // CORE_CMAP_CMAP2_H_ diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 20974628..c0a8ab01 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -98,10 +98,37 @@ class CMap3_T : public CMap2_T phi3_ = this->topology_.template add_attribute("phi3"); } +public: + + CMap3_T() : Inherit() + { + init(); + } + + ~CMap3_T() override + {} + + CMap3_T(Self const&) = delete; + CMap3_T(Self &&) = delete; + Self& operator=(Self const&) = delete; + Self& operator=(Self &&) = delete; + /******************************************************************************* * Low-level topological operations *******************************************************************************/ +protected: + + /** + * \brief Init an newly added dart. + * The dart is defined as a fixed point for PHI3. + */ + inline void init_dart(Dart d) + { + Inherit::init_dart(d); + (*phi3_)[d.index] = d; + } + /** * \brief Link dart d with dart e by an involution * @param d,e the darts to link @@ -117,7 +144,7 @@ class CMap3_T : public CMap2_T } /** - * \brief Unlink the current dart by an involution + * \brief Remove the phi3 link between the current dart and its linked dart * @param d the dart to unlink * - Before: d->e and e->d * - After: d->d and e->e @@ -129,6 +156,28 @@ class CMap3_T : public CMap2_T (*phi3_)[e.index] = e; } + /******************************************************************************* + * Basic topological operations + *******************************************************************************/ + +public: + + /** + * \brief phi3 + * @param d + * @return phi3(d) + */ + inline Dart phi3(Dart d) const + { + return (*phi3_)[d.index]; + } + + /******************************************************************************* + * High-level embedded and topological operations + *******************************************************************************/ + +protected: + /** * @brief create_pyramid_topo : create a pyramid whose base is n-sided * @param n, the number of edges of the base @@ -354,51 +403,6 @@ class CMap3_T : public CMap2_T public: - CMap3_T() : Inherit() - { - init(); - } - - ~CMap3_T() override - {} - - CMap3_T(Self const&) = delete; - CMap3_T(Self &&) = delete; - Self& operator=(Self const&) = delete; - Self& operator=(Self &&) = delete; - - /******************************************************************************* - * Basic topological operations - *******************************************************************************/ - - /** - * \brief phi3 - * @param d - * @return phi3(d) - */ - inline Dart phi3(Dart d) const - { - return (*phi3_)[d.index]; - } - -protected: - - /** - * \brief add a Dart in the map - * @return the new Dart - */ - inline void init_dart(Dart d) - { - Inherit::init_dart(d); - (*phi3_)[d.index] = d; - } - -public: - - /******************************************************************************* - * High-level topological operations - *******************************************************************************/ - inline unsigned int degree(Face f) const { return Inherit::degree(typename Inherit::Face(f.dart)); diff --git a/cgogn/multiresolution/cph/cph2.h b/cgogn/multiresolution/cph/cph2.h index 718aef17..9bd8527f 100644 --- a/cgogn/multiresolution/cph/cph2.h +++ b/cgogn/multiresolution/cph/cph2.h @@ -34,6 +34,7 @@ class CPH2 : public CPHBase { public: + typedef CPH2 Self; typedef CPHBase Inherit; @@ -43,17 +44,20 @@ class CPH2 : public CPHBase using ChunkArrayContainer = typename Inherit::template ChunkArrayContainer; protected: + ChunkArray* edge_id_; public: + CPH2(ChunkArrayContainer& topology): Inherit(topology) { - init(); + edge_id_ = topology.template add_attribute("edgeId"); } ~CPH2() override { - this->topo_.remove_attribute(edge_id_); + // TODO : check the way the destructors free memory in the class hierarchy + // this->topo_->remove_attribute(edge_id_); } CPH2(Self const&) = delete; @@ -61,14 +65,6 @@ class CPH2 : public CPHBase Self& operator=(Self const&) = delete; Self& operator=(Self &&) = delete; - -protected: - inline void init() - { - edge_id_ = this->topo_.template add_attribute("edgeId"); - } - -public: /*************************************************** * EDGE ID MANAGEMENT * ***************************************************/ @@ -101,8 +97,7 @@ class CPH2 : public CPHBase else return 1u; } - - //else if(id == 3) + // else if(id == 3) return 0u; } @@ -112,8 +107,7 @@ class CPH2 : public CPHBase if(e_id == 0u) return 1u; - - //else if(e_id == 1) + // else if(e_id == 1) return 0u; } diff --git a/cgogn/multiresolution/cph/cph3.h b/cgogn/multiresolution/cph/cph3.h index c2d4dcdb..2577c69b 100644 --- a/cgogn/multiresolution/cph/cph3.h +++ b/cgogn/multiresolution/cph/cph3.h @@ -47,12 +47,13 @@ class CPH3 : public CPH2 public: CPH3(ChunkArrayContainer& topology): Inherit(topology) { - init(); + face_id_ = topology.template add_attribute("faceId"); } ~CPH3() override { - this->topo_.remove_attribute(face_id_); + // TODO : check the way the destructors free memory in the class hierarchy + // this->topo_.remove_attribute(face_id_); } CPH3(Self const&) = delete; @@ -60,16 +61,10 @@ class CPH3 : public CPH2 Self& operator=(Self const&) = delete; Self& operator=(Self &&) = delete; -protected: - void init() - { - face_id_ = this->topo_.template add_attribute("faceId"); - } - -public: /*************************************************** * FACE ID MANAGEMENT * ***************************************************/ + inline unsigned int get_face_id(Dart d) const { return (*face_id_)[d.index] ; diff --git a/cgogn/multiresolution/cph/cph_base.h b/cgogn/multiresolution/cph/cph_base.h index 5e55993a..675748b1 100644 --- a/cgogn/multiresolution/cph/cph_base.h +++ b/cgogn/multiresolution/cph/cph_base.h @@ -39,7 +39,8 @@ class CPHBase { public: - using Self = CPHBase; + + typedef CPHBase Self; template using ChunkArray = cgogn::ChunkArray; @@ -47,26 +48,35 @@ class CPHBase using ChunkArrayContainer = cgogn::ChunkArrayContainer; protected: + unsigned int current_level_; unsigned int maximum_level_; - ChunkArray* dart_level_; + /*! + * \brief Store the current number of darts per resolution level. + * This information is used to detect that a level of resolution + * becomes empty (contains no more dart) and that the maximum_level + * of the hierarchy should be decremented. + */ + std::vector nb_darts_per_level_; - std::vector nb_darts_per_level; - - ChunkArrayContainer& topo_; + ChunkArray* dart_level_; public: + CPHBase(ChunkArrayContainer& topology): - topo_(topology), - current_level_(0) + current_level_(0u), + maximum_level_(0u) { - init(); + nb_darts_per_level_.reserve(32u); + nb_darts_per_level_.push_back(0); + dart_level_ = topology.template add_attribute("dartLevel") ; } virtual ~CPHBase() { - topo_.remove_attribute(dart_level_); + // TODO : check the way the destructors free memory in the class hierarchy + // topo_->remove_attribute(dart_level_); } CPHBase(Self const&) = delete; @@ -74,13 +84,6 @@ class CPHBase Self& operator=(Self const&) = delete; Self& operator=(Self &&) = delete; -public: - - void init() - { - dart_level_ = topo_.template add_attribute("dartLevel") ; - } - /*************************************************** * LEVELS MANAGEMENT * ***************************************************/ @@ -117,28 +120,33 @@ class CPHBase inline void inc_current_level() { - set_current_level(get_current_level() + 1); + current_level_++; + + while (nb_darts_per_level_.size() < current_level_+1u) + nb_darts_per_level_.push_back(0); + + if (current_level_ > maximum_level_) + maximum_level_ = current_level_; } inline void dec_current_level() { - set_current_level(get_current_level() - 1); + cgogn_message_assert(current_level_ > 0u, "dec_current_level : already at minimal resolution level"); + + if (current_level_ == maximum_level_) { + if (nb_darts_per_level_[current_level_] == 0u) { + maximum_level_--; + nb_darts_per_level_.pop_back(); + } + } + current_level_--; } - inline void inc_nb_darts(unsigned int level) + inline void inc_nb_darts() { - cgogn_message_assert(level < get_maximum_level(), "inc_nb_darts : already at maximum resolution level"); - nb_darts_per_level[level]++; + nb_darts_per_level_[current_level_]++; } - /*************************************************** - * NB DARTS PER LEVEL * - ***************************************************/ - - inline void new_level_darts() - { - nb_darts_per_level.push_back(0); - } }; diff --git a/cgogn/multiresolution/cph/ihcmap2.h b/cgogn/multiresolution/cph/ihcmap2.h index 14301cdf..78621398 100644 --- a/cgogn/multiresolution/cph/ihcmap2.h +++ b/cgogn/multiresolution/cph/ihcmap2.h @@ -26,7 +26,6 @@ #include #include -//#include namespace cgogn { @@ -53,30 +52,36 @@ class ContainerCPHBrowser : public ContainerBrowser virtual ~ContainerCPHBrowser() {} }; -template -class IHCMap2_T : public CMap2_T, public CPH2 // Can't use virtual inheritance because of the use of the CRTP +template +class IHCMap2_T : public CMap2_T, public CPH2 { public: - typedef CMap2_T Inherit_CMAP; - typedef CPH2 Inherit_CPH; - typedef IHCMap2_T Self; + static const int PRIM_SIZE = 1; + + typedef MAP_TRAITS MapTraits; + typedef MAP_TYPE MapType; + typedef CMap2_T Inherit_CMAP; + typedef CPH2 Inherit_CPH; + typedef IHCMap2_T Self; friend typename Self::Inherit_CMAP; - // friend typename Inherit::Inherit; + friend typename Inherit_CMAP::Inherit; + friend typename Inherit_CMAP::Inherit::Inherit; + friend typename Inherit_CMAP::Inherit::Inherit::Inherit; friend class DartMarker_T; - static const Orbit DART = Orbit::DART; + static const Orbit DART = Inherit_CMAP::DART; static const Orbit VERTEX = Inherit_CMAP::VERTEX; static const Orbit EDGE = Inherit_CMAP::EDGE; static const Orbit FACE = Inherit_CMAP::FACE; static const Orbit VOLUME = Inherit_CMAP::VOLUME; - using Vertex = typename Inherit_CMAP::Vertex; - using Edge = typename Inherit_CMAP::Edge; - using Face = typename Inherit_CMAP::Face; - using Volume = typename Inherit_CMAP::Volume; + typedef Cell Vertex; + typedef Cell Edge; + typedef Cell Face; + typedef Cell Volume; template using ChunkArray = typename Inherit_CMAP::template ChunkArray; @@ -96,26 +101,24 @@ class IHCMap2_T : public CMap2_T, public CPH2 using VolumeAttributeHandler = AttributeHandler; -// template -// using VertexAttributeHandlerCPH = AttributeHandlerCPH; - using DartMarker = typename cgogn::DartMarker; using DartMarkerStore = typename cgogn::DartMarkerStore; ChunkArray* next_level_cell[NB_ORBITS]; protected: + ContainerCPHBrowser, Self>* cph_browser; inline void init() { - cph_browser = new ContainerCPHBrowser, Self>(this->topology_, this); + cph_browser = new ContainerCPHBrowser, Self>( + this->topology_, this); this->topology_.set_current_browser(cph_browser); - - // Inherit_CPH::new_level_darts(); } public: + IHCMap2_T() : Inherit_CMAP(), Inherit_CPH(this->topology_) { init(); @@ -129,14 +132,35 @@ class IHCMap2_T : public CMap2_T, public CPH2, public CPH2 Inherit_CPH::get_maximum_level()) - { - Inherit_CPH::set_maximum_level(Inherit_CPH::get_current_level()); - // Inherit_CPH::new_level_darts(); - } - - // Inherit_CPH::inc_nb_darts(get_current_level()); - } + /******************************************************************************* + * High-level embedded and topological operations + *******************************************************************************/ // template // inline unsigned int get_embedding_cph(Cell c) const @@ -233,17 +240,55 @@ class IHCMap2_T : public CMap2_T, public CPH2add_face_topo(size); + + if (this->template is_orbit_embedded()) + { + this->foreach_dart_of_orbit(d, [this] (Vertex v) + { + this->template set_orbit_embedding(v, this->template add_attribute_element()); + }); + } + + if (this->template is_orbit_embedded()) + cgogn_assert_not_reached("Not implemented"); + + if (this->template is_orbit_embedded()) + cgogn_assert_not_reached("Not implemented"); + + if (this->template is_orbit_embedded()) + cgogn_assert_not_reached("Not implemented"); + + return Face(d); + } + + inline unsigned int face_degree(Dart d) + { + unsigned int count = 0 ; + Dart it = d ; + do + { + ++count ; + it = phi1(it) ; + } while (it != d) ; + return count ; + } /******************************************************************************* * Orbits traversal *******************************************************************************/ - template - inline void foreach_dart_of_DART(Dart d, const FUNC& f) const - { - f(d); - } +protected: template inline void foreach_dart_of_PHI1(Dart d, const FUNC& f) const @@ -265,17 +310,6 @@ class IHCMap2_T : public CMap2_T, public CPH2 - inline void foreach_dart_of_PHI21(Dart d, const FUNC& f) const - { - Dart it = d; - do - { - f(it); - it = Inherit_CMAP::phi2(Inherit_CMAP::phi_1(it)); - } while (it != d); - } - template void foreach_dart_of_PHI1_PHI2(Dart d, const FUNC& f) const { @@ -287,20 +321,21 @@ class IHCMap2_T : public CMap2_T, public CPH2size(); ++i) { - if (!marker.is_marked((*visited_faces)[i])) // Face has not been visited yet + Dart e = (*visited_faces)[i] ; + if (!marker.is_marked(e)) // Face has not been visited yet { // mark visited darts (current face) // and add non visited adjacent faces to the list of face - Dart e = (*visited_faces)[i] ; + Dart it = e; do { - f(e); // apply the function to the darts of the face - marker.mark(e); // Mark - Dart adj = phi2(e); // Get adjacent face + f(it); // apply the function to the darts of the face + marker.mark(it); // Mark + Dart adj = phi2(it); // Get adjacent face if (!marker.is_marked(adj)) visited_faces->push_back(adj); // Add it - e = phi1(e); - } while (e != (*visited_faces)[i]); + it = phi1(it); + } while (it != e); } } @@ -316,44 +351,17 @@ class IHCMap2_T : public CMap2_T, public CPH2foreach_dart_of_DART(c, f); break; case Orbit::PHI1: foreach_dart_of_PHI1(c, f); break; case Orbit::PHI2: foreach_dart_of_PHI2(c, f); break; case Orbit::PHI1_PHI2: foreach_dart_of_PHI1_PHI2(c, f); break; - case Orbit::PHI21: foreach_dart_of_PHI21(c, f); break; + case Orbit::PHI21: this->foreach_dart_of_PHI21(c, f); break; case Orbit::PHI2_PHI3: case Orbit::PHI1_PHI3: default: cgogn_assert_not_reached("Cells of this dimension are not handled"); break; } } -public: - - inline unsigned int face_degree(Dart d) - { - unsigned int count = 0 ; - Dart it = d ; - do - { - ++count ; - it = phi1(it) ; - } while (it != d) ; - return count ; - } - -// template -// inline AttributeHandlerCPH add_attribute(const std::string& attribute_name = "") -// { -// static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - -// } - -// template -// inline bool remove_attribute(AttributeHandlerCPH& ah) -// { -// static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - -// } }; template @@ -369,9 +377,6 @@ using IHCMap2 = IHCMap2_T>; extern template class CGOGN_MULTIRESOLUTION_API IHCMap2_T>; #endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(MULTIRESOLUTION_CPH_IHCMAP2_CPP_)) - - } // namespace cgogn #endif // MULTIRESOLUTION_CPH_IHCMAP2_H_ - diff --git a/cgogn/multiresolution/cph/ihcmap2_adaptive.h b/cgogn/multiresolution/cph/ihcmap2_adaptive.h index e3a032e5..c1d147c1 100644 --- a/cgogn/multiresolution/cph/ihcmap2_adaptive.h +++ b/cgogn/multiresolution/cph/ihcmap2_adaptive.h @@ -33,10 +33,18 @@ template class IHCMap2Adaptive_T : public IHCMap2_T { public: - using MapType = MAP_TYPE; - using Inherit = IHCMap2_T; - using Self = IHCMap2Adaptive_T; - friend class Inherit::Inherit_CMAP; + + static const int PRIM_SIZE = 1; + + typedef MAP_TRAITS MapTraits; + typedef MAP_TYPE MapType; + typedef IHCMap2_T Inherit; + typedef IHCMap2Adaptive_T Self; + + friend typename Inherit::Inherit_CMAP; + friend typename Inherit::Inherit_CMAP::Inherit; + friend typename Inherit::Inherit_CMAP::Inherit::Inherit; + friend typename Inherit::Inherit_CMAP::Inherit::Inherit::Inherit; using Vertex = typename Inherit::Vertex; using Edge = typename Inherit::Edge; @@ -54,11 +62,27 @@ class IHCMap2Adaptive_T : public IHCMap2_T Self& operator=(const Self&) = delete; Self& operator=(Self&&) = delete; -public: + /******************************************************************************* + * Low-level topological operations + *******************************************************************************/ + +protected: + + /** + * \brief Init an newly added dart. + * The dart is added to the current level of resolution + */ + inline void init_dart(Dart d) + { + Inherit::init_dart(d); + } + /*************************************************** * CELLS INFORMATION * ***************************************************/ +public: + /** * Return the level of the edge of d in the current level map * \details The level of an edge is the maximum of the levels of @@ -388,7 +412,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T // unsigned int dl = Inherit::get_dart_level(e); // Inherit::set_dart_level(Inherit::phi1(e), dl); // Inherit::collapseEdge(e); - this->uncut_edge(d); + this->merge_adjacent_edges_topo(d); Inherit::set_current_level(cur); } @@ -531,7 +555,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T Inherit::set_current_level(cur + 1); Dart innerEdge = Inherit::phi1(fit); Inherit::set_current_level(Inherit::get_maximum_level()); - this->merge_faces(innerEdge); + this->merge_adjacent_faces_topo(innerEdge); Inherit::set_current_level(cur); fit = this->phi1(fit); } while(fit != d); @@ -541,7 +565,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T Inherit::set_current_level(cur + 1); Dart centralV = Inherit::phi1(Inherit::phi1(d)); Inherit::set_current_level(Inherit::get_maximum_level()); - this->delete_vertex(centralV); +// TODO this->delete_vertex(centralV); Inherit::set_current_level(cur); } diff --git a/cgogn/multiresolution/cph/ihcmap2_regular.h b/cgogn/multiresolution/cph/ihcmap2_regular.h index 71743e23..42a9ebf5 100644 --- a/cgogn/multiresolution/cph/ihcmap2_regular.h +++ b/cgogn/multiresolution/cph/ihcmap2_regular.h @@ -36,7 +36,11 @@ class IHCMap2Regular_T : public IHCMap2_T using MapType = MAP_TYPE; using Inherit = IHCMap2_T; using Self = IHCMap2Regular_T; + friend typename Inherit::Inherit_CMAP; + friend typename Inherit::Inherit_CMAP::Inherit; + friend typename Inherit::Inherit_CMAP::Inherit::Inherit; + friend typename Inherit::Inherit_CMAP::Inherit::Inherit::Inherit; using Vertex = typename Inherit::Vertex; using Edge = typename Inherit::Edge; @@ -52,6 +56,21 @@ class IHCMap2Regular_T : public IHCMap2_T Self& operator=(Self&&) = delete; inline ~IHCMap2Regular_T() = default; + /******************************************************************************* + * Low-level topological operations + *******************************************************************************/ + +protected: + + /** + * \brief Init an newly added dart. + * The dart is added to the current level of resolution + */ + inline void init_dart(Dart d) + { + Inherit::init_dart(d); + } + public: inline void add_triangular_level() diff --git a/cgogn/multiresolution/cph/ihcmap3.h b/cgogn/multiresolution/cph/ihcmap3.h index 18b7b9a1..2409aeb3 100644 --- a/cgogn/multiresolution/cph/ihcmap3.h +++ b/cgogn/multiresolution/cph/ihcmap3.h @@ -108,8 +108,6 @@ class IHCMap3_T :public CMap3_T, public CPH3 { cph_browser = new ContainerCPHBrowser, Self>(this->topology_, this); this->topology_.set_current_browser(cph_browser); - - // Inherit_CPH::new_level_darts(); } public: @@ -203,6 +201,7 @@ class IHCMap3_T :public CMap3_T, public CPH3 { Inherit_CMAP::init_dart(d); + Inherit_CPH::inc_nb_darts(); Inherit_CPH::set_edge_id(d, 0); Inherit_CPH::set_face_id(d, 0); Inherit_CPH::set_dart_level(d, Inherit_CPH::get_current_level()); @@ -211,10 +210,7 @@ class IHCMap3_T :public CMap3_T, public CPH3 if(Inherit_CPH::get_current_level() > Inherit_CPH::get_maximum_level()) { Inherit_CPH::set_maximum_level(Inherit_CPH::get_current_level()); - // Inherit_CPH::new_level_darts(); } - - // Inherit_CPH::inc_nb_darts(get_current_level()); } protected: diff --git a/cgogn/multiresolution/examples/cph/cph2.cpp b/cgogn/multiresolution/examples/cph/cph2.cpp index b1808b2e..17b261b1 100644 --- a/cgogn/multiresolution/examples/cph/cph2.cpp +++ b/cgogn/multiresolution/examples/cph/cph2.cpp @@ -17,11 +17,11 @@ using VertexAttributeHandler = IHMap2::VertexAttributeHandler; int main() -{ - IHMap2 map; - VertexAttributeHandler position = map.get_attribute("position"); +{ + IHMap2 map; + VertexAttributeHandler position = map.get_attribute("position"); - LerpTriQuadMRAnalysis lerp(map, position); + LerpTriQuadMRAnalysis lerp(map, position); map.add_face(4); std::cout << "before add level Faces :" << std::endl; @@ -32,32 +32,32 @@ int main() std::cout << "End Faces" << std::endl; - { - lerp.add_level(); - lerp.synthesis(); + { + lerp.add_level(); + lerp.synthesis(); - std::cout << "after add level Faces :" << std::endl; - map.template foreach_cell([&] (IHMap2::Face f) - { - std::cout << f << " | " << map.get_dart_level(f.dart) << std::endl; - }); - std::cout << "End Faces" << std::endl; + std::cout << "after add level Faces :" << std::endl; + map.template foreach_cell([&] (IHMap2::Face f) + { + std::cout << f << " | " << map.get_dart_level(f.dart) << std::endl; + }); + std::cout << "End Faces" << std::endl; - unsigned int cur = map.get_current_level(); + unsigned int cur = map.get_current_level(); - std::cout << "current level = " << cur << std::endl; - map.set_current_level(cur - 1); + std::cout << "current level = " << cur << std::endl; + map.set_current_level(cur - 1); - std::cout << "after add level Faces :" << std::endl; - map.template foreach_cell([&] (IHMap2::Face f) - { - std::cout << f << " | " << map.get_dart_level(f.dart) << std::endl; - }); - std::cout << "End Vertices" << std::endl; - } + std::cout << "after add level Faces :" << std::endl; + map.template foreach_cell([&] (IHMap2::Face f) + { + std::cout << f << " | " << map.get_dart_level(f.dart) << std::endl; + }); + std::cout << "End Vertices" << std::endl; + } - /* + /* { map.add_mixed_level(); @@ -106,7 +106,7 @@ int main() }); std::cout << "End Vertices" << std::endl; } - */ + */ return 0; } From 07433cf26b9bfb69dcdf46d1044f098c4b20ad39 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Wed, 17 Feb 2016 18:00:40 +0100 Subject: [PATCH 118/402] clean CMap1 test --- cgogn/core/tests/cmap/cmap1_test.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cgogn/core/tests/cmap/cmap1_test.cpp b/cgogn/core/tests/cmap/cmap1_test.cpp index d0b76daf..3c5c2d13 100644 --- a/cgogn/core/tests/cmap/cmap1_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_test.cpp @@ -53,9 +53,9 @@ TEST_F(CMap1Test, addFace) // cmap_.cut_edge(Edge(f)); - EXPECT_TRUE(is_well_embedded(cmap_)); - EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); - EXPECT_TRUE(is_container_well_referenced(cmap_)); +// EXPECT_TRUE(is_well_embedded(cmap_)); +// EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); +// EXPECT_TRUE(is_container_well_referenced(cmap_)); } From d81d88967a38e99ec2283b321ba57cdee3081d5d Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Thu, 18 Feb 2016 17:40:37 +0100 Subject: [PATCH 119/402] ear triangulation --- cgogn/core/cmap/cmap1.h | 6 + cgogn/geometry/CMakeLists.txt | 1 + cgogn/geometry/algos/ear_triangulation.h | 454 +++++++++++++++++++++ cgogn/geometry/tests/algos/algos_test.cpp | 78 ++++ cgogn/io/map_export.h | 206 +++++++++- cgogn/rendering/examples/simple_viewer.cpp | 8 +- cgogn/rendering/map_render.h | 39 +- 7 files changed, 756 insertions(+), 36 deletions(-) create mode 100644 cgogn/geometry/algos/ear_triangulation.h diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 44730aa5..748a2600 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -328,6 +328,12 @@ class CMap1_T : public MapBase return this->nb_darts(f); } + inline bool is_triangle(Face f) + { + return (f.dart == phi1(phi1(phi1(f.dart)))); + } + + protected: /******************************************************************************* diff --git a/cgogn/geometry/CMakeLists.txt b/cgogn/geometry/CMakeLists.txt index fa482db4..63713b62 100644 --- a/cgogn/geometry/CMakeLists.txt +++ b/cgogn/geometry/CMakeLists.txt @@ -8,6 +8,7 @@ set(HEADER_FILES algos/area.h algos/centroid.h algos/normal.h + algos/ear_triangulation.h functions/area.h functions/normal.h functions/orientation.h diff --git a/cgogn/geometry/algos/ear_triangulation.h b/cgogn/geometry/algos/ear_triangulation.h new file mode 100644 index 00000000..d63d762b --- /dev/null +++ b/cgogn/geometry/algos/ear_triangulation.h @@ -0,0 +1,454 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef GEOMETRY_ALGOS_EAR_TRIANGULATION_H_ +#define GEOMETRY_ALGOS_EAR_TRIANGULATION_H_ + +#include + + +#include + +namespace cgogn +{ + +namespace geometry +{ + + +template +class EarTriangulation +{ + + using Vertex = typename MAP::Vertex; + using Face = typename MAP::Face; + using Scalar = typename VEC3::Scalar; + + // forward declaration + class VertexPoly; + + // multiset typedef for simple writing + typedef std::multiset VPMS; + + class VertexPoly + { + public: + int id; + Vertex vert_; + Scalar value_; + Scalar length_; + VertexPoly* prev_; + VertexPoly* next_; + typename VPMS::iterator ear_; + + VertexPoly(Vertex ve, Scalar va, Scalar l, VertexPoly* p = NULL) : vert_(ve), value_(va), length_(l), prev_(p), next_(NULL) + { + if (prev_ != NULL) + prev_->next_ = this; + } + + + static void close(VertexPoly* first, VertexPoly* last) + { + last->next_ = first; + first->prev_ = last; + } + + static VertexPoly* erase(VertexPoly* vp) + { + VertexPoly* tmp = vp->prev_; + tmp->next_ = vp->next_; + vp->next_->prev_ = tmp; + delete vp; + return tmp; + } + }; + + + /// normal to polygon (for orientation of angles) + VEC3 normalPoly_; + + /// ref on map + MAP& map_; + + /// ref on position attribute + const typename MAP::template VertexAttributeHandler& positions_; + + /// map of ears + VPMS ears_; + + /// is current polygin convex + bool convex_; + + /// number off vertices + unsigned int nb_verts_; + + /// initial face + Face face_; + + + inline static bool cmp_VP(VertexPoly* lhs, VertexPoly* rhs) + { + if (std::abs(lhs->value_ - rhs->value_)<0.2f) + return lhs->length_ < rhs->length_; + return lhs->value_ < rhs->value_; + } + + bool in_triangle(const VEC3& P, const VEC3& normal, const VEC3& Ta, const VEC3& Tb, const VEC3& Tc) + { + auto triple_positive = [] (const VEC3& U, const VEC3& V, const VEC3& W) -> bool + { return U.dot(V.cross(W)) >= Scalar(0); }; + + if (triple_positive(P-Ta, Tb-Ta, normal)) + return false; + + if (triple_positive(P-Tb, Tc-Tb, normal)) + return false; + + if (triple_positive(P-Tc, Ta-Tc, normal)) + return false; + + return true; + } + + void recompute_2_ears(VertexPoly* vp) + { + VertexPoly* vprev = vp->prev_; + VertexPoly* vp2 = vp->next_; + VertexPoly* vnext = vp2->next_; + const VEC3& Ta = positions_[vp->vert_]; + const VEC3& Tb = positions_[vp2->vert_]; + const VEC3& Tc = positions_[vprev->vert_]; + const VEC3& Td = positions_[vnext->vert_]; + + // compute angle + VEC3 v1 = Tb - Ta; + VEC3 v2 = Tc - Ta; + VEC3 v3 = Td - Tb; + + v1.normalize(); + v2.normalize(); + v3.normalize(); + + Scalar dotpr1 = Scalar(std::acos(v1.dot(v2)) / (M_PI/2.0)); + Scalar dotpr2 = Scalar(std::acos(-(v1.dot(v3))) / (M_PI/2.0)); + + +// if (!convex_) // if convex no need to test if vertex is an ear (yes) + { + VEC3 nv1 = v1.cross(v2); + VEC3 nv2 = v1.cross(v3); + + if (nv1.dot(normalPoly_) < 0.0) + dotpr1 = 10.0f - dotpr1;// not an ears (concave) + if (nv2.dot(normalPoly_) < 0.0) + dotpr2 = 10.0f - dotpr2;// not an ears (concave) + + bool finished = (dotpr1>=5.0f) && (dotpr2>=5.0f); + for (typename VPMS::reverse_iterator it = ears_.rbegin(); (!finished)&&(it != ears_.rend())&&((*it)->value_ > 5.0f); ++it) + { + Vertex id = (*it)->vert_; + const VEC3& P = positions_[id]; + + if ((dotpr1 < 5.0f) && (id.dart != vprev->vert_.dart)) + if (in_triangle(P, normalPoly_,Tb,Tc,Ta)) + dotpr1 = 5.0f;// not an ears ! + + if ((dotpr2 < 5.0f) && (id.dart != vnext->vert_.dart) ) + if (in_triangle(P, normalPoly_,Td,Ta,Tb)) + dotpr2 = 5.0f;// not an ears ! + + finished = ((dotpr1 >= 5.0f)&&(dotpr2 >= 5.0f)); + } + } + + vp->value_ = dotpr1; + vp->length_ = Scalar((Tb-Tc).squaredNorm()); + vp->ear_ = ears_.insert(vp); + vp2->value_ = dotpr2; + vp->length_ = Scalar((Td-Ta).squaredNorm()); + vp2->ear_ = ears_.insert(vp2); + } + + Scalar compute_ear_angle(const VEC3& P1, const VEC3& P2, const VEC3& P3) + { + VEC3 v1 = P1-P2; + VEC3 v2 = P3-P2; + v1.normalize(); + v2.normalize(); + + Scalar dotpr = Scalar(std::acos(v1.dot(v2)) / (M_PI/2.0) ); + + VEC3 vn = v1.cross(v2); + if (vn.dot(normalPoly_) > 0.0f) + dotpr = 10.0f - dotpr; // not an ears (concave, store at the end for optimized use for intersections) + + return dotpr; + } + + + bool compute_ear_intersection(VertexPoly* vp) + { + VertexPoly* endV = vp->prev_; + VertexPoly* curr = vp->next_; + const VEC3& Ta = positions_[vp->vert_]; + const VEC3& Tb = positions_[curr->vert_]; + const VEC3& Tc = positions_[endV->vert_]; + curr = curr->next_; + + while (curr != endV) + { + if (in_triangle(positions_[curr->vert_], normalPoly_,Tb,Tc,Ta)) + { + vp->value_ = 5.0f;// not an ears ! + return false; + } + curr = curr->next_; + } + return true; + } + + +public: + + /** + * @brief EarTriangulation constructor + * @param map ref on map + * @param f the face to tringulate + * @param position attribute of position to use + */ + EarTriangulation(MAP& map, Cell f, const typename MAP::template VertexAttributeHandler& position): + map_(map), + positions_(position), + ears_(cmp_VP) + { + if (map_.is_triangle(f)) + { + face_ = f; + nb_verts_ = 3; + return; + } + + // compute normals for orientation + normalPoly_ = geometry::face_normal(map_,f,position); + + // first pass create polygon in chained list with angle computation + VertexPoly* vpp = NULL; + VertexPoly* prem = NULL; + nb_verts_ = 0; + unsigned int nbe = 0; + Vertex a = f.dart; + Vertex b = Vertex(map_.phi1(a)); + Vertex c = Vertex(map_.phi1(b)); + do + { + const VEC3& P1 = position[a]; + const VEC3& P2 = position[b]; + const VEC3& P3 = position[c]; + + Scalar val = compute_ear_angle(P1, P2, P3); + VertexPoly* vp = new VertexPoly(b, val, Scalar((P3-P1).squaredNorm()), vpp); + + if (vp->value_ < 5.0f) + nbe++; + if (vpp == NULL) + prem = vp; + vpp = vp; + a = b; + b = c; + c = map_.phi1(c); + nb_verts_++; + } while (a.dart != f.dart); + + VertexPoly::close(prem, vpp); + + convex_ = (nbe == nb_verts_); + if (convex_) + { + // second pass with no test of intersections with polygons + vpp = prem; + for (unsigned int i = 0; i < nb_verts_; ++i) + { + vpp->ear_ = ears_.insert(vpp); + vpp = vpp->next_; + } + } + else + { + // second pass test intersections with polygons + vpp = prem; + for (unsigned int i = 0; i < nb_verts_; ++i) + { + if (vpp->value_ < 5.0f) + compute_ear_intersection(vpp); + vpp->ear_ = ears_.insert(vpp); + vpp = vpp->next_; + } + } + } + + /** + * @brief compute table of vertices indices (embeddings) of triangulation + * @param table_indices + */ + void compute_indices(std::vector& table_indices) + { + table_indices.reserve((nb_verts_-2)*3); + + if (nb_verts_ ==3) + { + map_.template foreach_incident_vertex(face_, [&] (Vertex v) + { + table_indices.push_back(map_.get_embedding(v)); + }); + return; + } + + while (nb_verts_ > 3) + { + // take best (and valid!) ear + typename VPMS::iterator be_it = ears_.begin(); // best ear + VertexPoly* be = *be_it; + + table_indices.push_back(map_.get_embedding(be->vert_)); + table_indices.push_back(map_.get_embedding(be->next_->vert_)); + table_indices.push_back(map_.get_embedding(be->prev_->vert_)); + nb_verts_--; + + if (nb_verts_ > 3) // do not recompute if only one triangle left + { + //remove ears and two sided ears + ears_.erase(be_it); // from map of ears + ears_.erase(be->next_->ear_); + ears_.erase(be->prev_->ear_); + be = VertexPoly::erase(be); // and remove ear vertex from polygon + recompute_2_ears(be); + convex_ = convex_ && (*(ears_.rbegin()))->value_ < 5.0f; // ? + } + else // finish (no need to update ears) + { + // remove ear from polygon + be = VertexPoly::erase(be); + // last triangle + table_indices.push_back(map_.get_embedding(be->vert_)); + table_indices.push_back(map_.get_embedding(be->next_->vert_)); + table_indices.push_back(map_.get_embedding(be->prev_->vert_)); + // release memory of last triangle in polygon + delete be->next_; + delete be->prev_; + delete be; + } + } + } + + /** + * @brief triangulate the face + */ + void triangulate() + { + while (nb_verts_ > 3) + { + // take best (and valid!) ear + typename VPMS::iterator be_it = ears_.begin(); // best ear + VertexPoly* be = *be_it; + + map_.split_face(be->prev_->vert_, be->next_->vert_); + nb_verts_--; + + if (nb_verts_ > 3) // do not recompute if only one triangle left + { + //remove ears and two sided ears + ears_.erase(be_it); // from map of ears + ears_.erase(be->next_->ear_); + ears_.erase(be->prev_->ear_); + // replace dart to be in remaining poly + be ->prev_->vert_ = Vertex(map_.phi2(map_.phi_1(be ->prev_->vert_.dart))); + be = VertexPoly::erase(be); // and remove ear vertex from polygon + recompute_2_ears(be); + convex_ = convex_ && (*(ears_.rbegin()))->value_ < 5.0f; // ?? + } + else // finish (no need to update ears) + { + // release memory of last triangle in polygon + delete be->next_; + delete be->prev_; + delete be; + } + } + } +}; + +/** + * @brief compute ear triangulation + * @param map + * @param f face + * @param position + * @param table_indices table of indices (vertex embedding) to fill (append) + */ +template +static void compute_ear_triangulation(MAP& map, Cell f, const typename MAP::template VertexAttributeHandler& position, std::vector& table_indices) +{ + EarTriangulation tri(map, f, position); + tri.compute_indices(table_indices); +} + +/** + * @brief apply ear triangulation to a face (face is cut + * @param map + * @param f + * @param position + */ +template +static void apply_ear_triangulation(MAP& map, Cell f, const typename MAP::template VertexAttributeHandler& position) +{ + EarTriangulation tri(map, f, position); + tri.triangulate(); +} + +/** + * @brief apply ear triangulation to a face (face is cut + * @param map + * @param f + * @param position + */ +template +static void apply_ear_triangulations(MAP& map, const typename MAP::template VertexAttributeHandler& position) +{ + map.template foreach_cell([&] (typename MAP::Face f) + { + if (!map.is_triangle(f)) + { + EarTriangulation tri(map, f, position); + tri.triangulate(); + } + }); + +} + + + +} // namespace geometry + +} // namespace cgogn + +#endif // GEOMETRY_ALGOS_EAR_TRIANGULATION_H_ diff --git a/cgogn/geometry/tests/algos/algos_test.cpp b/cgogn/geometry/tests/algos/algos_test.cpp index 029d96fa..c7f21526 100644 --- a/cgogn/geometry/tests/algos/algos_test.cpp +++ b/cgogn/geometry/tests/algos/algos_test.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -187,3 +188,80 @@ TEST(Algos_TEST, QuadNormal) EXPECT_TRUE(cgogn::almost_equal_relative(cross[2], 0.)); } } + + +TEST(Algos_TEST, EarTriangulation) +{ + // with array + { + CMap2 map; + VertexAttributeHandler vertex_position = map.add_attribute("position"); + + CMap2::Face f = map.add_face(5); + cgogn::Dart d = f.dart; + + vertex_position[CMap2::Vertex(d)] = StdArray(0,0,0); + d = map.phi1(d); + vertex_position[CMap2::Vertex(d)] = StdArray(10,0,0); + d = map.phi1(d); + vertex_position[CMap2::Vertex(d)] = StdArray(10,10,0); + d = map.phi1(d); + vertex_position[CMap2::Vertex(d)] = StdArray(5,5,0); + d = map.phi1(d); + vertex_position[CMap2::Vertex(d)] = StdArray(0,10,0); + + std::vector indices; + cgogn::geometry::compute_ear_triangulation(map,f,vertex_position,indices); + EXPECT_TRUE(indices.size() == 9); + + double area = 0.0; + for (size_t i=0; i(map,f,vertex_position); + EXPECT_TRUE(map.nb_cells()==4); + EXPECT_TRUE(map.nb_cells()==7); + } + // with Eigen + { + CMap2 map; + VertexAttributeHandler vertex_position = map.add_attribute("position"); + + CMap2::Face f = map.add_face(5); + cgogn::Dart d = f.dart; + + vertex_position[CMap2::Vertex(d)] = EigenVec3d(0,0,0); + d = map.phi1(d); + vertex_position[CMap2::Vertex(d)] = EigenVec3d(10,0,0); + d = map.phi1(d); + vertex_position[CMap2::Vertex(d)] = EigenVec3d(10,10,0); + d = map.phi1(d); + vertex_position[CMap2::Vertex(d)] = EigenVec3d(5,5,0); + d = map.phi1(d); + vertex_position[CMap2::Vertex(d)] = EigenVec3d(0,10,0); + + std::vector indices; + cgogn::geometry::compute_ear_triangulation(map,f,vertex_position,indices); + EXPECT_TRUE(indices.size() == 9); + + double area = 0.0; + for (size_t i=0; i(map,f,vertex_position); + EXPECT_TRUE(map.nb_cells()==4); + EXPECT_TRUE(map.nb_cells()==7); + } +} diff --git a/cgogn/io/map_export.h b/cgogn/io/map_export.h index 18ab3b6b..093e0bb1 100644 --- a/cgogn/io/map_export.h +++ b/cgogn/io/map_export.h @@ -28,12 +28,12 @@ #include #include #include +#include +#include +#include -#include -//#include - namespace cgogn @@ -73,13 +73,13 @@ bool export_off(MAP& map, const typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); - ids.get_data()->set_all_values(0xffffffff); + ids.get_data()->set_all_values(UINT_MAX); unsigned int count = 0; map.template foreach_cell([&] (typename MAP::Face f) { map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) { - if (ids[v]==0xffffffff) + if (ids[v]==UINT_MAX) { ids[v] = count++; const VEC3& P = position[v]; @@ -152,7 +152,7 @@ bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandle // first pass to save positions & store contiguous indices typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); - ids.get_data()->set_all_values(0xffffffff); + ids.get_data()->set_all_values(UINT_MAX); unsigned int count = 0; static const unsigned int BUFFER_SZ = 1024*1024; @@ -164,7 +164,7 @@ bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandle { map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) { - if (ids[v]==0xffffffff) + if (ids[v]==UINT_MAX) { ids[v] = count++; VEC3 P = position[v]; @@ -236,7 +236,7 @@ bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandle /** - * @brief export surface in obj format + * @brief export surface in obj format (positions only) * @param map the map to export * @param position the position attribute of vertices * @param filename the name of file to save @@ -255,16 +255,18 @@ bool export_obj(MAP& map, const typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); - ids.get_data()->set_all_values(0xffffffff); + ids.get_data()->set_all_values(UINT_MAX); unsigned int count = 1; map.template foreach_cell([&] (typename MAP::Face f) { map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) { - if (ids[v]==0xffffffff) + if (ids[v]==UINT_MAX) { ids[v] = count++; const VEC3& P = position[v]; @@ -273,6 +275,7 @@ bool export_obj(MAP& map, const typename MAP::template VertexAttributeHandler prim; prim.reserve(20); @@ -293,6 +296,189 @@ bool export_obj(MAP& map, const typename MAP::template VertexAttributeHandler +bool export_obj(MAP& map, const typename MAP::template VertexAttributeHandler& position, const typename MAP::template VertexAttributeHandler& normal, const std::string& filename) +{ + std::ofstream fp(filename.c_str(), std::ios::out); + if (!fp.good()) + { + std::cout << "Unable to open file " << filename << std::endl; + return false; + } + + // set precision for float output + fp<< std::setprecision(12); + + fp << std::endl << "# vertices" << std::endl; + // two passes of traversal to avoid huge buffer (with same performance); + // first pass to save positions & store contiguous indices (from 1 because of obj format) + typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); + ids.get_data()->set_all_values(UINT_MAX); + unsigned int count = 1; + std::vector indices; + indices.reserve(map.template nb_cells()); + map.template foreach_cell([&] (typename MAP::Face f) + { + map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) + { + if (ids[v]==UINT_MAX) + { + indices.push_back(map.template get_embedding(v)); + ids[v] = count++; + const VEC3& P = position[v]; + fp <<"v " << P[0] << " " << P[1] << " " << P[2] << std::endl; + } + }); + }); + + fp << std::endl << "# normals" << std::endl; + // save normals + for (unsigned int i: indices) + { + const VEC3& N = normal[i]; + fp <<"vn " << N[0] << " " << N[1] << " " << N[2] << std::endl; + } + + fp << std::endl << "# faces" << std::endl; + // second pass to save primitives + std::vector prim; + prim.reserve(20); + map.template foreach_cell([&] (typename MAP::Face f) + { + fp << "f"; + map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) + { + fp << " " << ids[v] << "//" << ids[v]; + }); + fp << std::endl; + }); + + map.remove_attribute(ids); + fp.close(); + return true; +} + + + +template +bool export_stl_ascii(MAP& map, const typename MAP::template VertexAttributeHandler& position, const std::string& filename) +{ + std::ofstream fp(filename.c_str(), std::ios::out); + if (!fp.good()) + { + std::cout << "Unable to open file " << filename << std::endl; + return false; + } + + // set precision for float output + fp<< std::setprecision(12); + + fp << "solid" << filename << std::endl; + + map.template foreach_cell([&] (typename MAP::Face f) + { + std::vector table_indices; + table_indices.reserve(768); + + if (map.is_triangle(f)) + { + VEC3 N = geometry::face_normal(map,f,position); + fp << "facet normal "<< N[0] << " "<< N[1]<< " " << N[2]<< std::endl; + fp << " outer loop"<< std::endl; + map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) + { + const VEC3& P = position[v]; + fp <<" vertex " << P[0] << " " << P[1] << " " << P[2] << std::endl; + }); + fp << " endloop"<< std::endl; + fp << "endfacet"<< std::endl; + } + else + { + cgogn::geometry::compute_ear_triangulation(map,f,position,table_indices); + for(unsigned int i=0; i +//bool export_stl_bin(MAP& map, const typename MAP::template VertexAttributeHandler& position, const std::string& filename) +//{ +// std::ofstream fp(filename.c_str(), std::ios::out|std::ofstream::binary); +// if (!fp.good()) +// { +// std::cout << "Unable to open file " << filename << std::endl; +// return false; +// } + +// unsigned int header[21]; +// header[20] = map.template nb_cells(); + +// map.template foreach_cell([&] (typename MAP::Face f) +// { +// VEC3 N = geometry::face_normal(map,f,position); + + +// fp << "facet normal "<< N[0] << " "<< N[1]<< " " << N[2]<< std::endl; +// fp << " outer loop"<< std::endl; +// map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) +// { +// const VEC3& P = position[v]; +// fp <<" vertex " << P[0] << " " << P[1] << " " << P[2] << std::endl; +// }); +// fp << " endloop"<< std::endl; +// fp << "endfacet"<< std::endl; +// }); +// fp << "endfacet"<< std::endl; + +// fp << "endsolid" << filename << std::endl; + +// fp.close(); +// return true; +//} + +//UINT8[80] – Header +//UINT32 – Number of triangles + +//foreach triangle +//REAL32[3] – Normal vector +//REAL32[3] – Vertex 1 +//REAL32[3] – Vertex 2 +//REAL32[3] – Vertex 3 +//UINT16 – Attribute byte count +//end + + + + + } // namespace io } // namespace cgogn diff --git a/cgogn/rendering/examples/simple_viewer.cpp b/cgogn/rendering/examples/simple_viewer.cpp index b8d30db4..cd083ada 100644 --- a/cgogn/rendering/examples/simple_viewer.cpp +++ b/cgogn/rendering/examples/simple_viewer.cpp @@ -39,6 +39,8 @@ #include #include +#include + #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) using Map2 = cgogn::CMap2; @@ -175,9 +177,9 @@ void Viewer::init() render_ = new cgogn::rendering::MapRender(); - render_->init_primitives(map_, cgogn::rendering::POINTS); - render_->init_primitives(map_, cgogn::rendering::LINES); - render_->init_primitives(map_, cgogn::rendering::TRIANGLES); + render_->init_primitives(map_, cgogn::rendering::POINTS, vertex_position_); + render_->init_primitives(map_, cgogn::rendering::LINES, vertex_position_); + render_->init_primitives(map_, cgogn::rendering::TRIANGLES, vertex_position_); shader1_ = new cgogn::rendering::ShaderSimpleColor; shader1_->add_vao(); diff --git a/cgogn/rendering/map_render.h b/cgogn/rendering/map_render.h index 3cdb6bdf..0ea0f23a 100644 --- a/cgogn/rendering/map_render.h +++ b/cgogn/rendering/map_render.h @@ -29,6 +29,7 @@ #include #include // impossible to include directly attribute_handler.h ! +#include namespace cgogn { @@ -92,37 +93,29 @@ class MapRender }); } - template - void init_triangles(MAP& m, std::vector& table_indices) +// template + template + void init_triangles(MAP& m, std::vector& table_indices, const typename MAP::template VertexAttributeHandler& position) { // reserve more ? // table_indices.reserve(m.get_nb_darts()/3); m.template foreach_cell([&] (typename MAP::Face f) { - Dart d = f; - Dart d1 = m.phi1(d); - Dart d2 = m.phi1(d1); - unsigned int d_e = m.template get_embedding(d); - unsigned int d1_e = m.template get_embedding(d1); - unsigned int d2_e; - do + if (m.is_triangle(f)) { - d2_e = m.template get_embedding(d2); - - table_indices.push_back(d_e); - table_indices.push_back(d1_e); - table_indices.push_back(d2_e); - - d1 = d2; - d2 = m.phi1(d1); - d1_e = d2_e; - - } while (d2 != d); + table_indices.push_back(m.template get_embedding(f.dart)); + table_indices.push_back(m.template get_embedding(m.phi1(f.dart))); + table_indices.push_back(m.template get_embedding(m.phi1(m.phi1(f.dart)))); + } + else + { + cgogn::geometry::compute_ear_triangulation(m,f,position,table_indices); + } }); } - template - void init_primitives(MAP& m, DrawingType prim) + template + void init_primitives(MAP& m, DrawingType prim, const typename MAP::template VertexAttributeHandler& position) { std::vector table_indices; @@ -135,7 +128,7 @@ class MapRender init_lines(m, table_indices); break; case TRIANGLES: - init_triangles(m, table_indices); + init_triangles(m, table_indices, position); break; default: break; From 5075a607b4b4579ddd253e703b3005c5dcd9feb6 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Thu, 18 Feb 2016 17:53:33 +0100 Subject: [PATCH 120/402] More cleaning + Last try for generic foreach_incident_XXX() --- cgogn/core/cmap/cmap0.h | 49 +-- cgogn/core/cmap/cmap1.h | 49 ++- cgogn/core/cmap/cmap2.h | 369 ++++++++++++------- cgogn/core/cmap/cmap3.h | 52 ++- cgogn/core/cmap/map_base.h | 44 ++- cgogn/core/cmap/map_base_data.h | 4 +- cgogn/multiresolution/CMakeLists.txt | 6 +- cgogn/multiresolution/cph/cph2.h | 2 - cgogn/multiresolution/cph/cph3.h | 2 - cgogn/multiresolution/cph/ihcmap2.h | 25 +- cgogn/multiresolution/cph/ihcmap2_adaptive.h | 19 +- cgogn/multiresolution/cph/ihcmap2_regular.h | 25 +- 12 files changed, 381 insertions(+), 265 deletions(-) diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index 3afaee91..f7b881d2 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -25,7 +25,6 @@ #define CORE_CMAP_CMAP0_H_ #include -#include namespace cgogn { @@ -35,15 +34,14 @@ class CMap0_T : public MapBase { public: - static const int PRIM_SIZE = 1; - typedef MAP_TRAITS MapTraits; typedef MAP_TYPE MapType; typedef MapBase Inherit; typedef CMap0_T Self; - friend typename Self::Inherit; - friend class DartMarker_T; + friend class MapBase; + + static const int PRIM_SIZE = 1; static const Orbit DART = Orbit::DART; @@ -77,32 +75,34 @@ class CMap0_T : public MapBase Self& operator=(Self &&) = delete; /******************************************************************************* - * Low-level topological operations + * High-level embedded and topological operations *******************************************************************************/ -protected: +public: /*! - * \brief Init an newly added dart. - * If a DART attribute has been added to the Map, - * the inserted Dart is embedded on a new attribute element. - */ - inline void init_dart(Dart d) + * \brief Add an embedded vertex (or dart) in the map. + * \return The added dart. If the map has DART attributes, + * the inserted darts are automatically embedded on new attribute elements. + */ + Dart add_vertex() { + CGOGN_CHECK_CONCRETE_TYPE; + + Dart d = this->add_dart(); + if (this->template is_orbit_embedded()) - this->template set_embedding(d, this->template add_attribute_element()); + this->new_embedding(d); + + return d; } /******************************************************************************* - * High-level embedded and topological operations + * Orbits traversal *******************************************************************************/ protected: - /******************************************************************************* - * Orbits traversal - *******************************************************************************/ - template inline void foreach_dart_of_DART(Dart d, const FUNC& f) const { @@ -114,18 +114,7 @@ class CMap0_T : public MapBase { static_assert(ORBIT == Orbit::DART, "Orbit not supported in a CMap1"); - switch(ORBIT) - { - case Orbit::DART: this->foreach_dart_of_DART(c, f); break; - case Orbit::PHI1: - case Orbit::PHI2: - case Orbit::PHI1_PHI2: - case Orbit::PHI1_PHI3: - case Orbit::PHI2_PHI3: - case Orbit::PHI21: - case Orbit::PHI21_PHI31: - default: cgogn_assert_not_reached("This orbit is not handled"); break; - } + this->foreach_dart_of_DART(c, f); } }; diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index ca42d27d..994cc9eb 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -25,8 +25,6 @@ #define CORE_CMAP_CMAP1_H_ #include -#include -#include namespace cgogn { @@ -36,19 +34,16 @@ class CMap1_T : public CMap0_T { public: - static const int PRIM_SIZE = 1; - typedef MAP_TRAITS MapTraits; typedef MAP_TYPE MapType; typedef CMap0_T Inherit; typedef CMap1_T Self; - friend typename Self::Inherit; - friend typename Inherit::Inherit; - template - friend class DartMarker_T; - template - friend class DartMarkerStore; + friend class MapBase; + template friend class DartMarker_T; + template friend class DartMarkerStore; + + static const int PRIM_SIZE = 1; static const Orbit DART = Orbit::DART; static const Orbit FACE = Orbit::PHI1; @@ -111,7 +106,6 @@ class CMap1_T : public CMap0_T */ inline void init_dart(Dart d) { - Inherit::init_dart(d); (*phi1_)[d.index] = d; (*phi_1_)[d.index] = d; } @@ -193,7 +187,7 @@ class CMap1_T : public CMap0_T * \param size : the number of darts in the built face * \return A dart of the built face */ - inline Dart add_face_topo(unsigned int size) + inline Face add_face_topo(unsigned int size) { cgogn_message_assert(size > 0u, "Cannot create an empty face"); @@ -201,7 +195,7 @@ class CMap1_T : public CMap0_T for (unsigned int i = 1u; i < size; ++i) cut_edge_topo(d); - return d; + return Face(d); } public: @@ -216,10 +210,16 @@ class CMap1_T : public CMap0_T { CGOGN_CHECK_CONCRETE_TYPE; - Face f(add_face_topo(size)); + Face f = add_face_topo(size); + + if (this->template is_orbit_embedded()) + foreach_dart_of_PHI1(f.dart, [this] (Dart d) + { + this->template new_embedding(d); + }); if (this->template is_orbit_embedded()) - this->set_orbit_embedding(f, this->template add_attribute_element()); + this->new_orbit_embedding(f); return f; } @@ -288,6 +288,8 @@ class CMap1_T : public CMap0_T phi1_sew(e, d); // Sew the last edge } +public: + inline unsigned int degree(Face f) const { return this->nb_darts(f); @@ -371,6 +373,21 @@ class CMap1_T : public CMap0_T * Incidence traversal *******************************************************************************/ + template + inline void foreach_incident_cell(Cell c, const FUNC& f) const + { + static_assert(check_func_parameter_type(FUNC, Cell), + "Wrong function cell parameter type"); + + static_assert((ORBIT_IN == FACE && ORBIT_OUT == DART), + "Invalid incidence relation"); + + foreach_dart_of_orbit(c, [&] (Dart d) + { + f(Cell(d)); + }); + } + // To remove : on a pas la notion de Vertex ou de Edge ici ... // template @@ -432,8 +449,6 @@ extern template class CGOGN_CORE_API CellMarkerStore, Or extern template class CGOGN_CORE_API CellMarkerStore, Orbit::PHI1>; #endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_MAP_MAP1_CPP_)) - - } // namespace cgogn #endif // CORE_CMAP_CMAP1_H_ diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index feefd7e9..4b0a9fd4 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -39,21 +39,17 @@ class CMap2_T : public CMap1_T { public: - static const int PRIM_SIZE = 1; - typedef MAP_TRAITS MapTraits; typedef MAP_TYPE MapType; typedef CMap1_T Inherit; typedef CMap2_T Self; - friend typename Self::Inherit; - friend typename Inherit::Inherit; - friend typename Inherit::Inherit::Inherit; + friend class MapBase; friend class CMap2Builder_T; - template - friend class DartMarker_T; - template - friend class DartMarkerStore; + template friend class DartMarker_T; + template friend class DartMarkerStore; + + static const int PRIM_SIZE = 1; static const Orbit DART = Orbit::DART; static const Orbit VERTEX = Orbit::PHI21; @@ -119,9 +115,9 @@ class CMap2_T : public CMap1_T protected: /** - * \brief Init an newly added dart. - * The dart is defined as a fixed point for PHI2. - */ + * \brief Init an newly added dart. + * The dart is defined as a fixed point for PHI2. + */ inline void init_dart(Dart d) { Inherit::init_dart(d); @@ -215,31 +211,37 @@ class CMap2_T : public CMap1_T CGOGN_CHECK_CONCRETE_TYPE; const Dart ne = cut_edge_topo(e); - const Dart nf = phi2(e); + const Dart nf = this->phi1(phi2(e)); + + if (this->template is_orbit_embedded()) { + this->template new_embedding(ne); + this->template new_embedding(nf); + } if (this->template is_orbit_embedded()) { - this->template set_orbit_embedding(ne, this->template add_attribute_element()); + const unsigned int idx = this->template new_embedding(ne); + this->template set_embedding(nf, idx); } if (this->template is_orbit_embedded()) { - this->template set_embedding(nf, this->template get_embedding(e)); - this->template set_orbit_embedding(ne, this->template add_attribute_element()); + this->template copy_embedding(nf, e); + this->template new_orbit_embedding(ne); } if (this->template is_orbit_embedded()) { - this->template set_embedding(ne, this->template get_embedding(e.dart)); - this->template set_embedding(nf, this->template get_embedding(this->phi_1(nf))); + this->template copy_embedding(ne, e.dart); + this->template copy_embedding(nf, this->phi_1(nf)); } if (this->template is_orbit_embedded()) { - const unsigned int idx = this->template get_embedding(e.dart); - this->template set_embedding(ne, idx); + const unsigned int idx = this->template new_embedding(ne); this->template set_embedding(nf, idx); } + return Vertex(ne); } @@ -259,16 +261,16 @@ class CMap2_T : public CMap1_T protected: /** - * \brief Split the face of d and e by inserting an edge between the vertex of d and e + * \brief Cut the face of d and e by inserting an edge between the vertex of d and e * \param d : first vertex * \param e : second vertex * Darts d and e should belong to the same face and be distinct from each other. * An edge made of two new darts is inserted between the two given vertices. */ - inline void split_face_topo(Dart d, Dart e) + inline void cut_face_topo(Dart d, Dart e) { - cgogn_message_assert(d != e, "split_face: d and e should be distinct"); - cgogn_message_assert(this->same_cell(Face(d), Face(e)), "split_face: d and e should belong to the same face"); + cgogn_message_assert(d != e, "cut_face: d and e should be distinct"); + cgogn_message_assert(this->same_cell(Face(d), Face(e)), "cut_face: d and e should belong to the same face"); Dart dd = this->phi_1(d); Dart ee = this->phi_1(e); @@ -281,7 +283,7 @@ class CMap2_T : public CMap1_T public: /** - * \brief Split an enbedded face by inserting an edge between the vertices d and e + * \brief Cut an enbedded face by inserting an edge between the vertices d and e * \param d : first vertex * \param e : second vertex * The vertices d and e should belong to the same face and be distinct from each other. @@ -292,36 +294,40 @@ class CMap2_T : public CMap1_T * and a new FACE attribute is created for the subdived face that e belongs to. * The FACE attribute of the subdived face that d belongs to is kept unchanged. */ - inline void split_face(Vertex d, Vertex e) + inline void cut_face(Vertex d, Vertex e) { CGOGN_CHECK_CONCRETE_TYPE; - split_face_topo(d,e); + cut_face_topo(d,e); const Dart nd = this->phi_1(d); const Dart ne = this->phi_1(e); + if (this->template is_orbit_embedded()) { + this->template new_embedding(nd); + this->template new_embedding(ne); + } + if (this->template is_orbit_embedded()) { - this->template set_embedding(nd, this->template get_embedding(e)); - this->template set_embedding(ne, this->template get_embedding(d)); + this->template copy_embedding(nd, e); + this->template copy_embedding(ne, d); } if (this->template is_orbit_embedded()) { - this->template set_orbit_embedding(nd, this->template add_attribute_element()); + this->template new_orbit_embedding(nd); } if (this->template is_orbit_embedded()) { - this->template set_embedding(nd, this->template get_embedding(d.dart)); - this->template set_orbit_embedding(ne, this->template add_attribute_element()); + this->template copy_embedding(nd, d.dart); + this->template new_orbit_embedding(ne); } if (this->template is_orbit_embedded()) { - const unsigned int idx = this->template get_embedding(d.dart); - this->template set_orbit_embedding(nd, idx); - this->template set_orbit_embedding(ne, idx); + unsigned int idx = this->template copy_embedding(nd, d.dart); + this->template set_embedding(ne, idx); } } @@ -332,20 +338,21 @@ class CMap2_T : public CMap1_T * \param size : the number of darts in the built face * \return A dart of the built face. */ - Dart add_face_topo(unsigned int size) + Face add_face_topo(unsigned int size) { - Dart d = Inherit::add_face_topo(size); - Dart e = Inherit::add_face_topo(size); + const Face f = Inherit::add_face_topo(size); + const Face g = Inherit::add_face_topo(size); - Dart it = d; + Dart d = f.dart; + Dart e = g.dart; do { - phi2_sew(it, e); - it = this->phi1(it); + phi2_sew(d, e); + d = this->phi1(d); e = this->phi_1(e); - } while (it != d); + } while (d != f.dart); - return d; + return f; } public: @@ -362,31 +369,33 @@ class CMap2_T : public CMap1_T { CGOGN_CHECK_CONCRETE_TYPE; - Dart d = add_face_topo(size); + Face f = add_face_topo(size); + + if (this->template is_orbit_embedded()) + foreach_dart_of_orbit(f, [this] (Dart d) + { + this->template new_embedding(d); + }); if (this->template is_orbit_embedded()) - { - this->foreach_dart_of_orbit(d, [this] (Vertex v) + foreach_dart_of_orbit(f, [this] (Dart v) { - this->template set_orbit_embedding(v, this->template add_attribute_element()); + this->template new_embedding(v); }); - } if (this->template is_orbit_embedded()) - { - this->foreach_dart_of_orbit(d, [this] (Edge e) + foreach_dart_of_orbit(f, [this] (Dart e) { - this->template set_orbit_embedding(e, this->template add_attribute_element()); + this->template new_embedding(e); }); - } if (this->template is_orbit_embedded()) - this->template set_orbit_embedding(d, this->template add_attribute_element()); + this->template new_embedding(f.dart); if (this->template is_orbit_embedded()) - this->template set_orbit_embedding(d, this->template add_attribute_element()); + this->template new_orbit_embedding(f.dart); - return Face(d); + return f; } protected: @@ -431,30 +440,35 @@ class CMap2_T : public CMap1_T if (phi2(d) == d) { close_hole_topo(d); - const Dart new_face = phi2(d); + const Face new_face = phi2(d); + + if (this->template is_orbit_embedded()) + foreach_dart_of_orbit(new_face, [this] (Dart d) + { + this->template new_embedding(d); + }); if (this->template is_orbit_embedded()) - { - foreach_dart_of_orbit(new_face, [this] (Dart fd) + foreach_dart_of_orbit(new_face, [this] (Dart fd) { - this->template set_embedding(fd, this->template get_embedding(this->phi1(phi2(fd)))); + this->template copy_embedding(fd, this->phi1(phi2(fd))); }); - } + if (this->template is_orbit_embedded()) - { - foreach_dart_of_orbit(new_face, [this] (Dart fd) + foreach_dart_of_orbit(new_face, [this] (Dart fd) { - this->template set_embedding(fd, this->template get_embedding(phi2(fd))); + this->template copy_embedding(fd, phi2(fd)); }); - } + if (this->template is_orbit_embedded()) { - this->template set_orbit_embedding(new_face, this->template add_attribute_element()); + this->template new_orbit_embedding(new_face); } + if (this->template is_orbit_embedded()) { const unsigned int idx = this->template get_embedding(d); - foreach_dart_of_orbit(new_face, [this, idx] (Dart fd) + foreach_dart_of_orbit(new_face, [this, idx] (Dart fd) { this->template set_embedding(fd, idx); }); @@ -627,21 +641,100 @@ class CMap2_T : public CMap1_T } } -public: - /******************************************************************************* * Incidence traversal *******************************************************************************/ + public: + + template + inline void foreach_incident_cell(Cell c, const FUNC& f) const + { + static_assert(check_func_parameter_type(FUNC, Cell), + "Wrong function cell parameter type"); + + static_assert((ORBIT_IN == VERTEX && ORBIT_OUT == EDGE) || + (ORBIT_IN == VERTEX && ORBIT_OUT == FACE) || + (ORBIT_IN == EDGE && ORBIT_OUT == VERTEX) || + (ORBIT_IN == EDGE && ORBIT_OUT == FACE) || + (ORBIT_IN == FACE && ORBIT_OUT == VERTEX) || + (ORBIT_IN == FACE && ORBIT_OUT == EDGE) || + (ORBIT_IN == VOLUME && ORBIT_OUT == VERTEX) || + (ORBIT_IN == VOLUME && ORBIT_OUT == EDGE) || + (ORBIT_IN == VOLUME && ORBIT_OUT == FACE), + "Invalid incidence relation"); + + if (ORBIT_IN == VOLUME) { + DartMarkerStore marker(*this); + foreach_dart_of_orbit(c, [&] (Dart d) + { + if (!marker.is_marked(d)) + { + marker.template mark_orbit(d); + f(Cell(d)); + } + }); + } + else { + foreach_dart_of_orbit(c, [&] (Dart d) + { + f(Cell(d)); + }); + } + } + + template + inline void foreach_incident_vertex(Cell c, const FUNC& f) const + { + foreach_incident_cell(c, f); + } + + template + inline void foreach_incident_edge(Cell c, const FUNC& f) const + { + foreach_incident_cell(c, f); + } + + template + inline void foreach_incident_face(Cell c, const FUNC& f) const + { + foreach_incident_cell(c, f); + } + + template + inline void foreach_incident_volume(Cell c, const FUNC& f) const + { + foreach_incident_cell(c, f); + } + + /*! + * Idem + assure l'unicité en cas de multi-incidence + */ template - inline void foreach_incident_cell(Cell v, const FUNC& f) const + inline void foreach_unique_incident_cell(Cell c, const FUNC& f) const { static_assert(check_func_parameter_type(FUNC, Cell), "Wrong function cell parameter type"); - foreach_dart_of_orbit(v, [&] (Dart d) + static_assert((ORBIT_IN == VERTEX && ORBIT_OUT == EDGE) || + (ORBIT_IN == VERTEX && ORBIT_OUT == FACE) || + (ORBIT_IN == EDGE && ORBIT_OUT == VERTEX) || + (ORBIT_IN == EDGE && ORBIT_OUT == FACE) || + (ORBIT_IN == FACE && ORBIT_OUT == VERTEX) || + (ORBIT_IN == FACE && ORBIT_OUT == EDGE) || + (ORBIT_IN == VOLUME && ORBIT_OUT == VERTEX) || + (ORBIT_IN == VOLUME && ORBIT_OUT == EDGE) || + (ORBIT_IN == VOLUME && ORBIT_OUT == FACE), + "Invalid incidence relation"); + + DartMarkerStore marker(*this); + foreach_dart_of_orbit(c, [&] (Dart d) { + if (!marker.is_marked(d)) + { + marker.template mark_orbit(d); f(Cell(d)); + } }); } @@ -659,80 +752,80 @@ class CMap2_T : public CMap1_T // foreach_dart_of_orbit(v, f); // } - template - inline void foreach_incident_vertex(Edge e, const FUNC& f) const - { - static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); - f(e.dart); - f(phi2(e.dart)); - } +// template +// inline void foreach_incident_vertex(Edge e, const FUNC& f) const +// { +// static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); +// f(e.dart); +// f(phi2(e.dart)); +// } - template - inline void foreach_incident_face(Edge e, const FUNC& f) const - { - static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); - f(e.dart); - f(phi2(e.dart)); - } +// template +// inline void foreach_incident_face(Edge e, const FUNC& f) const +// { +// static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); +// f(e.dart); +// f(phi2(e.dart)); +// } - template - inline void foreach_incident_vertex(Face f, const FUNC& func) const - { - static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); - foreach_dart_of_orbit(f, func); - } +// template +// inline void foreach_incident_vertex(Face f, const FUNC& func) const +// { +// static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); +// foreach_dart_of_orbit(f, func); +// } - template - inline void foreach_incident_edge(Face f, const FUNC& func) const - { - static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); - foreach_dart_of_orbit(f, func); - } +// template +// inline void foreach_incident_edge(Face f, const FUNC& func) const +// { +// static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); +// foreach_dart_of_orbit(f, func); +// } - template - inline void foreach_incident_vertex(Volume v, const FUNC& f) const - { - static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); - DartMarkerStore marker(*this); - foreach_dart_of_orbit(v, [&] (Dart d) - { - if (!marker.is_marked(d)) - { - marker.template mark_orbit(d); - f(d); - } - }); - } +// template +// inline void foreach_incident_vertex(Volume v, const FUNC& f) const +// { +// static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); +// DartMarkerStore marker(*this); +// foreach_dart_of_orbit(v, [&] (Dart d) +// { +// if (!marker.is_marked(d)) +// { +// marker.template mark_orbit(d); +// f(d); +// } +// }); +// } - template - inline void foreach_incident_edge(Volume v, const FUNC& f) const - { - static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); - DartMarkerStore marker(*this); - foreach_dart_of_orbit(v, [&] (Dart d) - { - if (!marker.is_marked(d)) - { - marker.template mark_orbit(d); - f(d); - } - }); - } +// template +// inline void foreach_incident_edge(Volume v, const FUNC& f) const +// { +// static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); +// DartMarkerStore marker(*this); +// foreach_dart_of_orbit(v, [&] (Dart d) +// { +// if (!marker.is_marked(d)) +// { +// marker.template mark_orbit(d); +// f(d); +// } +// }); +// } - template - inline void foreach_incident_face(Volume v, const FUNC& f) const - { - static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); - DartMarkerStore marker(*this); - foreach_dart_of_orbit(v, [&] (Dart d) - { - if (!marker.is_marked(d)) - { - marker.template mark_orbit(d); - f(d); - } - }); - } +// template +// inline void foreach_incident_face(Volume v, const FUNC& f) const +// { +// static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); +// DartMarkerStore marker(*this); +// foreach_dart_of_orbit(v, [&] (Dart d) +// { +// if (!marker.is_marked(d)) +// { +// marker.template mark_orbit(d); +// f(d); +// } +// }); +// } /******************************************************************************* * Adjacence traversal diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index c0a8ab01..92547771 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -39,22 +39,17 @@ class CMap3_T : public CMap2_T { public: - static const int PRIM_SIZE = 1; - typedef MAP_TRAITS MapTraits; typedef MAP_TYPE MapType; typedef CMap2_T Inherit; typedef CMap3_T Self; - friend typename Self::Inherit; - friend typename Inherit::Inherit; - friend typename Inherit::Inherit::Inherit; - friend typename Inherit::Inherit::Inherit::Inherit; - template - friend class DartMarker_T; - template - friend class DartMarkerStore; + friend class MapBase; friend class CMap3Builder_T; + template friend class DartMarker_T; + template friend class DartMarkerStore; + + static const int PRIM_SIZE = 1; static const Orbit DART = Orbit::DART; static const Orbit VERTEX = Orbit::PHI21_PHI31; @@ -341,30 +336,31 @@ class CMap3_T : public CMap2_T { ++nb; close_hole_topo(d); - const Dart new_volume = phi3(d); + const Volume new_volume = phi3(d); - if (this->template is_orbit_embedded()) // cmap2 vertices - { + if (this->template is_orbit_embedded()) + foreach_dart_of_orbit(new_volume, [this] (Dart d) + { + this->template new_embedding(d); + }); - Inherit::foreach_incident_vertex(Volume(new_volume), [this] (Cell v) + if (this->template is_orbit_embedded()) + Inherit::foreach_incident_vertex(new_volume, [this] (Cell v) { - this->set_orbit_embedding(v, this->template add_attribute_element()); + this->new_orbit_embedding(v); }); - } - if (this->template is_orbit_embedded()) // cmap2 edges - { - Inherit::foreach_incident_edge(Volume(new_volume), [this] (Cell e) + if (this->template is_orbit_embedded()) + Inherit::foreach_incident_edge(new_volume, [this] (Cell e) { - this->set_orbit_embedding(e, this->template add_attribute_element()); + this->new_orbit_embedding(e); }); - } - if (this->template is_orbit_embedded()) // cmap2 faces + if (this->template is_orbit_embedded()) // cmap2 faces { - Inherit::foreach_incident_face(Volume(new_volume), [this] (Cell f) + Inherit::foreach_incident_face(new_volume, [this] (Cell f) { - this->set_orbit_embedding(f, this->template add_attribute_element()); + this->new_orbit_embedding(f); }); } @@ -372,7 +368,7 @@ class CMap3_T : public CMap2_T { foreach_dart_of_orbit(new_volume, [this] (Dart wd) { - this->template set_embedding(wd, this->template get_embedding(this->phi1(phi3(wd)))); + this->template copy_embedding(wd, this->phi1(phi3(wd))); }); } @@ -380,7 +376,7 @@ class CMap3_T : public CMap2_T { foreach_dart_of_orbit(new_volume, [this] (Dart wd) { - this->template set_embedding(wd, this->template get_embedding(phi3(wd))); + this->template copy_embedding(wd, phi3(wd)); }); } @@ -388,13 +384,13 @@ class CMap3_T : public CMap2_T { foreach_dart_of_orbit(new_volume, [this] (Dart wd) { - this->template set_embedding(wd, this->template get_embedding(phi3(wd))); + this->template copy_embedding(wd, phi3(wd)); }); } if (this->template is_orbit_embedded()) { - this->template set_orbit_embedding(new_volume, this->template add_attribute_element()); + this->template new_orbit_embedding(new_volume); } } } diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index ab660b16..6c618cde 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -182,7 +182,8 @@ class MapBase : public MapBaseData if(this->embeddings_[orbit]) { unsigned int emb = (*this->embeddings_[orbit])[index]; - this->attributes_[orbit].unref_line(emb); + if (emb != EMBNULL) + this->attributes_[orbit].unref_line(emb); } } } @@ -336,25 +337,52 @@ class MapBase : public MapBaseData this->embeddings_[ORBIT] = ca; // initialize all darts indices to EMBNULL for this ORBIT - foreach_dart([this] (Dart d) + foreach_dart([this,ca] (Dart d) { - (*this->embeddings_[ORBIT])[d.index] = EMBNULL; + (*ca)[d.index] = EMBNULL; }); // initialize the indices of the existing orbits foreach_cell([this] (Cell c) { - set_orbit_embedding(c, add_attribute_element()); + new_orbit_embedding(c); }); } template - inline void set_orbit_embedding(Cell c, unsigned int emb) + inline unsigned int new_embedding(Dart d) { + unsigned int emb = add_attribute_element(); + this->template set_embedding(d, emb); + return emb; + } + + template + inline unsigned int copy_embedding(Dart d, Dart e) + { + unsigned int emb = this->template get_embedding(e); + this->template set_embedding(d, emb); + return emb; + } + +// template +// inline void set_orbit_embedding(Cell c, unsigned int emb) +// { +// ConcreteMap* cmap = to_concrete(); +// cmap->foreach_dart_of_orbit(c, [cmap, emb] (Dart d) { +// cmap->template set_embedding(d, emb); +// }); +// } + + template + inline unsigned int new_orbit_embedding(Cell c) + { + unsigned int emb = add_attribute_element(); ConcreteMap* cmap = to_concrete(); cmap->foreach_dart_of_orbit(c, [cmap, emb] (Dart d) { cmap->template set_embedding(d, emb); }); + return emb; } public: @@ -374,8 +402,12 @@ class MapBase : public MapBaseData ConcreteMap* cmap = to_concrete(); foreach_cell([cmap, &counter] (Cell c) { + // Je ne comprends pas cet algo ?! (David) + // foreach_cell passe une seule fois par cellule ? => counter[c] est toujours nul + // En plus le brin c pourrait être n'importe quel brin de la cellule + // donc on peut passer plusieurs fois par la cellule, en comptant des brins distincts if (counter[c] > 0) - cmap->set_orbit_embedding(c, cmap->template add_attribute_element()); + cmap->new_orbit_embedding(c); counter[c]++; }); diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index fe6d000e..a3d8aa69 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -233,12 +233,12 @@ class MapBaseData : public MapGen this->mark_attributes_topology_[thread].push_back(ca); } -public: - /******************************************************************************* * Embedding (orbit indexing) management *******************************************************************************/ +public: + template inline bool is_orbit_embedded() const { diff --git a/cgogn/multiresolution/CMakeLists.txt b/cgogn/multiresolution/CMakeLists.txt index ec3c821f..da5f0ef3 100644 --- a/cgogn/multiresolution/CMakeLists.txt +++ b/cgogn/multiresolution/CMakeLists.txt @@ -17,8 +17,8 @@ set(HEADER_FILES mrcmap/mr_base.h mrcmap/mrcmap2.h - mra/mr_analysis.h - mra/lerp_triquad_mra.h +# mra/mr_analysis.h +# mra/lerp_triquad_mra.h ) set(SOURCE_FILES @@ -56,4 +56,4 @@ install(TARGETS ${PROJECT_NAME} ARCHIVE DESTINATION lib ) -add_subdirectory(examples) +#add_subdirectory(examples) diff --git a/cgogn/multiresolution/cph/cph2.h b/cgogn/multiresolution/cph/cph2.h index 9bd8527f..22d7e47e 100644 --- a/cgogn/multiresolution/cph/cph2.h +++ b/cgogn/multiresolution/cph/cph2.h @@ -56,8 +56,6 @@ class CPH2 : public CPHBase ~CPH2() override { - // TODO : check the way the destructors free memory in the class hierarchy - // this->topo_->remove_attribute(edge_id_); } CPH2(Self const&) = delete; diff --git a/cgogn/multiresolution/cph/cph3.h b/cgogn/multiresolution/cph/cph3.h index 2577c69b..487711c7 100644 --- a/cgogn/multiresolution/cph/cph3.h +++ b/cgogn/multiresolution/cph/cph3.h @@ -52,8 +52,6 @@ class CPH3 : public CPH2 ~CPH3() override { - // TODO : check the way the destructors free memory in the class hierarchy - // this->topo_.remove_attribute(face_id_); } CPH3(Self const&) = delete; diff --git a/cgogn/multiresolution/cph/ihcmap2.h b/cgogn/multiresolution/cph/ihcmap2.h index 78621398..a3e1aac8 100644 --- a/cgogn/multiresolution/cph/ihcmap2.h +++ b/cgogn/multiresolution/cph/ihcmap2.h @@ -65,12 +65,9 @@ class IHCMap2_T : public CMap2_T, public CPH2 typedef CPH2 Inherit_CPH; typedef IHCMap2_T Self; - friend typename Self::Inherit_CMAP; - friend typename Inherit_CMAP::Inherit; - friend typename Inherit_CMAP::Inherit::Inherit; - friend typename Inherit_CMAP::Inherit::Inherit::Inherit; - - friend class DartMarker_T; + friend class MapBase; + template friend class DartMarker_T; + template friend class DartMarkerStore; static const Orbit DART = Inherit_CMAP::DART; static const Orbit VERTEX = Inherit_CMAP::VERTEX; @@ -250,15 +247,19 @@ class IHCMap2_T : public CMap2_T, public CPH2 */ Face add_face(unsigned int size) { - Dart d = this->add_face_topo(size); + Face f = this->add_face_topo(size); + + if (this->template is_orbit_embedded()) + foreach_dart_of_orbit(f, [this] (Dart d) + { + this->template new_embedding(d); + }); if (this->template is_orbit_embedded()) - { - this->foreach_dart_of_orbit(d, [this] (Vertex v) + foreach_dart_of_orbit(f, [this] (Dart v) { - this->template set_orbit_embedding(v, this->template add_attribute_element()); + this->template new_embedding(v); }); - } if (this->template is_orbit_embedded()) cgogn_assert_not_reached("Not implemented"); @@ -269,7 +270,7 @@ class IHCMap2_T : public CMap2_T, public CPH2 if (this->template is_orbit_embedded()) cgogn_assert_not_reached("Not implemented"); - return Face(d); + return f; } inline unsigned int face_degree(Dart d) diff --git a/cgogn/multiresolution/cph/ihcmap2_adaptive.h b/cgogn/multiresolution/cph/ihcmap2_adaptive.h index c1d147c1..944548ef 100644 --- a/cgogn/multiresolution/cph/ihcmap2_adaptive.h +++ b/cgogn/multiresolution/cph/ihcmap2_adaptive.h @@ -41,10 +41,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T typedef IHCMap2_T Inherit; typedef IHCMap2Adaptive_T Self; - friend typename Inherit::Inherit_CMAP; - friend typename Inherit::Inherit_CMAP::Inherit; - friend typename Inherit::Inherit_CMAP::Inherit::Inherit; - friend typename Inherit::Inherit_CMAP::Inherit::Inherit::Inherit; + friend class MapBase; using Vertex = typename Inherit::Vertex; using Edge = typename Inherit::Edge; @@ -350,10 +347,10 @@ class IHCMap2Adaptive_T : public IHCMap2_T return Vertex(); } - inline void split_face_update_emb(Dart e, Dart e2) + inline void cut_face_update_emb(Dart e, Dart e2) { CGOGN_CHECK_CONCRETE_TYPE; - std::cerr << "IHCMap2Adaptive_T::split_face_update_emb method is not implemented yet." << std::endl; + std::cerr << "IHCMap2Adaptive_T::cut_face_update_emb method is not implemented yet." << std::endl; } /*************************************************** @@ -459,7 +456,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T // (*vertexVertexFunctor)(e) ; e = Inherit::phi1(e); - this->split_face_topo(dd,e); + this->cut_face_topo(dd,e); unsigned int id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id); // set the edge id of the inserted @@ -469,7 +466,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T e = Inherit::phi1(dd); // (*vertexVertexFunctor)(e); e = Inherit::phi1(e); - this->split_face_topo(dd,e); + this->cut_face_topo(dd,e); id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id); Inherit::set_edge_id(Inherit::phi_1(e), id); @@ -478,7 +475,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T e = Inherit::phi1(dd); // (*vertexVertexFunctor)(e); e = Inherit::phi1(e); - this->split_face_topo(dd,e); + this->cut_face_topo(dd,e); id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id); Inherit::set_edge_id(Inherit::phi_1(e), id); @@ -489,7 +486,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T Dart next = this->phi1(dd); // (*vertexVertexFunctor)(next); next = Inherit::phi1(next); - this->split_face_topo(dd,next); // insert a first edge + this->cut_face_topo(dd,next); // insert a first edge Dart ne = Inherit::phi2(Inherit::phi_1(dd)); Dart ne2 = Inherit::phi2(ne); this->cut_edge_topo(ne); // cut the new edge to insert the central vertex @@ -508,7 +505,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T dd = Inherit::phi1(dd); while(dd != ne) // turn around the face and insert new edges { // linked to the central vertex - this->split_face_topo(Inherit::phi1(ne), dd); + this->cut_face_topo(Inherit::phi1(ne), dd); Dart nne = Inherit::phi2(Inherit::phi_1(dd)); id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(nne))); diff --git a/cgogn/multiresolution/cph/ihcmap2_regular.h b/cgogn/multiresolution/cph/ihcmap2_regular.h index 42a9ebf5..a59def13 100644 --- a/cgogn/multiresolution/cph/ihcmap2_regular.h +++ b/cgogn/multiresolution/cph/ihcmap2_regular.h @@ -37,10 +37,7 @@ class IHCMap2Regular_T : public IHCMap2_T using Inherit = IHCMap2_T; using Self = IHCMap2Regular_T; - friend typename Inherit::Inherit_CMAP; - friend typename Inherit::Inherit_CMAP::Inherit; - friend typename Inherit::Inherit_CMAP::Inherit::Inherit; - friend typename Inherit::Inherit_CMAP::Inherit::Inherit::Inherit; + friend class MapBase; using Vertex = typename Inherit::Vertex; using Edge = typename Inherit::Edge; @@ -101,7 +98,7 @@ class IHCMap2Regular_T : public IHCMap2_T Dart dd = Inherit::phi1(old) ; Dart e = Inherit::phi1(Inherit::phi1(dd)) ; // insert a new edge - // Inherit::split_face(dd, e) ; + // Inherit::cut_face(dd, e) ; unsigned int id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id) ; // set the edge id of the inserted @@ -109,14 +106,14 @@ class IHCMap2Regular_T : public IHCMap2_T dd = e ; e = Inherit::phi1(Inherit::phi1(dd)) ; - // Inherit::split_face(dd, e) ; + // Inherit::cut_face(dd, e) ; id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id) ; Inherit::set_edge_id(Inherit::phi_1(e), id) ; dd = e ; e = Inherit::phi1(Inherit::phi1(dd)) ; - // Inherit::split_face(dd, e) ; + // Inherit::cut_face(dd, e) ; id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id) ; Inherit::set_edge_id(Inherit::phi_1(e), id) ; @@ -152,7 +149,7 @@ class IHCMap2Regular_T : public IHCMap2_T Dart dd = Inherit::phi1(old) ; Dart next = Inherit::phi1(Inherit::phi1(dd)) ; - // Inherit::split_face(dd, next) ; // insert a first edge + // Inherit::cut_face(dd, next) ; // insert a first edge Dart ne = Inherit::phi2(Inherit::phi_1(dd)) ; Dart ne2 = Inherit::phi2(ne) ; @@ -170,7 +167,7 @@ class IHCMap2Regular_T : public IHCMap2_T while(dd != ne) // turn around the face and insert new edges { // linked to the central vertex Dart tmp = Inherit::phi1(ne) ; - // Inherit::split_face(tmp, dd) ; + // Inherit::cut_face(tmp, dd) ; Dart nne = Inherit::phi2(Inherit::phi_1(dd)) ; @@ -219,7 +216,7 @@ class IHCMap2Regular_T : public IHCMap2_T Dart dd = Inherit::phi1(old) ; Dart e = Inherit::phi1(Inherit::phi1(dd)) ; // insert a new edge - // Inherit::split_face(dd, e) ; + // Inherit::cut_face(dd, e) ; unsigned int id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id) ; // set the edge id of the inserted @@ -227,14 +224,14 @@ class IHCMap2Regular_T : public IHCMap2_T dd = e ; e = Inherit::phi1(Inherit::phi1(dd)) ; - // Inherit::split_face(dd, e) ; + // Inherit::cut_face(dd, e) ; id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id) ; Inherit::set_edge_id(Inherit::phi_1(e), id) ; dd = e ; e = Inherit::phi1(Inherit::phi1(dd)) ; - // Inherit::split_face(dd, e) ; + // Inherit::cut_face(dd, e) ; id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id) ; Inherit::set_edge_id(Inherit::phi_1(e), id) ; @@ -243,7 +240,7 @@ class IHCMap2Regular_T : public IHCMap2_T { Dart dd = Inherit::phi1(old) ; Dart next = Inherit::phi1(Inherit::phi1(dd)) ; - // Inherit::split_face(dd, next) ; // insert a first edge + // Inherit::cut_face(dd, next) ; // insert a first edge Dart ne = Inherit::phi2(Inherit::phi_1(dd)) ; Dart ne2 = Inherit::phi2(ne) ; @@ -261,7 +258,7 @@ class IHCMap2Regular_T : public IHCMap2_T while(dd != ne) // turn around the face and insert new edges { // linked to the central vertex Dart tmp = Inherit::phi1(ne) ; - // Inherit::split_face(tmp, dd) ; + // Inherit::cut_face(tmp, dd) ; Dart nne = Inherit::phi2(Inherit::phi_1(dd)) ; From 9edc821402e5b25e3f92394b1f101f7d437727f8 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Fri, 19 Feb 2016 13:48:34 +0100 Subject: [PATCH 121/402] minor modifications in ear triangulation --- cgogn/geometry/algos/ear_triangulation.h | 15 ++++++++------- cgogn/geometry/tests/algos/algos_test.cpp | 10 +++++----- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/cgogn/geometry/algos/ear_triangulation.h b/cgogn/geometry/algos/ear_triangulation.h index d63d762b..f725baa7 100644 --- a/cgogn/geometry/algos/ear_triangulation.h +++ b/cgogn/geometry/algos/ear_triangulation.h @@ -154,7 +154,7 @@ class EarTriangulation Scalar dotpr2 = Scalar(std::acos(-(v1.dot(v3))) / (M_PI/2.0)); -// if (!convex_) // if convex no need to test if vertex is an ear (yes) + if (!convex_) // if convex no need to test if vertex is an ear (yes) { VEC3 nv1 = v1.cross(v2); VEC3 nv2 = v1.cross(v3); @@ -188,6 +188,9 @@ class EarTriangulation vp2->value_ = dotpr2; vp->length_ = Scalar((Td-Ta).squaredNorm()); vp2->ear_ = ears_.insert(vp2); + + // polygon if convex only if all vertices have convex angle (last have ...) + convex_ = (*(ears_.rbegin()))->value_ < 5.0f; } Scalar compute_ear_angle(const VEC3& P1, const VEC3& P2, const VEC3& P3) @@ -256,7 +259,7 @@ class EarTriangulation VertexPoly* vpp = NULL; VertexPoly* prem = NULL; nb_verts_ = 0; - unsigned int nbe = 0; + convex_ = true; Vertex a = f.dart; Vertex b = Vertex(map_.phi1(a)); Vertex c = Vertex(map_.phi1(b)); @@ -269,8 +272,9 @@ class EarTriangulation Scalar val = compute_ear_angle(P1, P2, P3); VertexPoly* vp = new VertexPoly(b, val, Scalar((P3-P1).squaredNorm()), vpp); - if (vp->value_ < 5.0f) - nbe++; + if (vp->value_ > 5.0f) // concav angle + convex_ = false; + if (vpp == NULL) prem = vp; vpp = vp; @@ -282,7 +286,6 @@ class EarTriangulation VertexPoly::close(prem, vpp); - convex_ = (nbe == nb_verts_); if (convex_) { // second pass with no test of intersections with polygons @@ -343,7 +346,6 @@ class EarTriangulation ears_.erase(be->prev_->ear_); be = VertexPoly::erase(be); // and remove ear vertex from polygon recompute_2_ears(be); - convex_ = convex_ && (*(ears_.rbegin()))->value_ < 5.0f; // ? } else // finish (no need to update ears) { @@ -385,7 +387,6 @@ class EarTriangulation be ->prev_->vert_ = Vertex(map_.phi2(map_.phi_1(be ->prev_->vert_.dart))); be = VertexPoly::erase(be); // and remove ear vertex from polygon recompute_2_ears(be); - convex_ = convex_ && (*(ears_.rbegin()))->value_ < 5.0f; // ?? } else // finish (no need to update ears) { diff --git a/cgogn/geometry/tests/algos/algos_test.cpp b/cgogn/geometry/tests/algos/algos_test.cpp index c7f21526..467d1f0f 100644 --- a/cgogn/geometry/tests/algos/algos_test.cpp +++ b/cgogn/geometry/tests/algos/algos_test.cpp @@ -200,15 +200,15 @@ TEST(Algos_TEST, EarTriangulation) CMap2::Face f = map.add_face(5); cgogn::Dart d = f.dart; - vertex_position[CMap2::Vertex(d)] = StdArray(0,0,0); + vertex_position[CMap2::Vertex(d)] = StdArray(0.0,0.0,0.0); d = map.phi1(d); - vertex_position[CMap2::Vertex(d)] = StdArray(10,0,0); + vertex_position[CMap2::Vertex(d)] = StdArray(10.0,0.0,0.0); d = map.phi1(d); - vertex_position[CMap2::Vertex(d)] = StdArray(10,10,0); + vertex_position[CMap2::Vertex(d)] = StdArray(10.0,10.0,0.0); d = map.phi1(d); - vertex_position[CMap2::Vertex(d)] = StdArray(5,5,0); + vertex_position[CMap2::Vertex(d)] = StdArray(5.0,5.0,0.0); d = map.phi1(d); - vertex_position[CMap2::Vertex(d)] = StdArray(0,10,0); + vertex_position[CMap2::Vertex(d)] = StdArray(0.0,10.0,0.0); std::vector indices; cgogn::geometry::compute_ear_triangulation(map,f,vertex_position,indices); From f01914c00795863d1e114bfe1d76e3aad9858839 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Fri, 19 Feb 2016 13:50:46 +0100 Subject: [PATCH 122/402] STL export --- cgogn/core/cmap/attribute_handler.h | 8 +- cgogn/io/map_export.h | 145 ++++++++++++++++++---------- 2 files changed, 99 insertions(+), 54 deletions(-) diff --git a/cgogn/core/cmap/attribute_handler.h b/cgogn/core/cmap/attribute_handler.h index 07131519..3fc6f8bd 100644 --- a/cgogn/core/cmap/attribute_handler.h +++ b/cgogn/core/cmap/attribute_handler.h @@ -350,12 +350,12 @@ class AttributeHandler : public AttributeHandlerOrbit } /** - * \brief getDataVector - * @return + * \brief affect a value to all elements of container (even holes) + * @param val value to affect */ - TChunkArray* get_data() + inline void set_all_container_values(const T& val) { - return chunk_array_; + chunk_array_->set_all_values(val); } /** diff --git a/cgogn/io/map_export.h b/cgogn/io/map_export.h index 093e0bb1..e1821a44 100644 --- a/cgogn/io/map_export.h +++ b/cgogn/io/map_export.h @@ -73,7 +73,7 @@ bool export_off(MAP& map, const typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); - ids.get_data()->set_all_values(UINT_MAX); + ids.set_all_container_values(UINT_MAX); unsigned int count = 0; map.template foreach_cell([&] (typename MAP::Face f) { @@ -152,7 +152,16 @@ bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandle // first pass to save positions & store contiguous indices typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); - ids.get_data()->set_all_values(UINT_MAX); + + std::chrono::time_point start, end; + start = std::chrono::system_clock::now(); + + ids.set_all_container_values(UINT_MAX); + + end = std::chrono::system_clock::now(); + std::chrono::duration elapsed_seconds = end - start; + std::cout << "set_all_container_values: " << elapsed_seconds.count() << "s\n"; + unsigned int count = 0; static const unsigned int BUFFER_SZ = 1024*1024; @@ -260,7 +269,7 @@ bool export_obj(MAP& map, const typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); - ids.get_data()->set_all_values(UINT_MAX); + ids.set_all_container_values(UINT_MAX); unsigned int count = 1; map.template foreach_cell([&] (typename MAP::Face f) { @@ -320,7 +329,7 @@ bool export_obj(MAP& map, const typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); - ids.get_data()->set_all_values(UINT_MAX); + ids.set_all_container_values(UINT_MAX); unsigned int count = 1; std::vector indices; indices.reserve(map.template nb_cells()); @@ -428,52 +437,88 @@ bool export_stl_ascii(MAP& map, const typename MAP::template VertexAttributeHand -//template -//bool export_stl_bin(MAP& map, const typename MAP::template VertexAttributeHandler& position, const std::string& filename) -//{ -// std::ofstream fp(filename.c_str(), std::ios::out|std::ofstream::binary); -// if (!fp.good()) -// { -// std::cout << "Unable to open file " << filename << std::endl; -// return false; -// } - -// unsigned int header[21]; -// header[20] = map.template nb_cells(); - -// map.template foreach_cell([&] (typename MAP::Face f) -// { -// VEC3 N = geometry::face_normal(map,f,position); - - -// fp << "facet normal "<< N[0] << " "<< N[1]<< " " << N[2]<< std::endl; -// fp << " outer loop"<< std::endl; -// map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) -// { -// const VEC3& P = position[v]; -// fp <<" vertex " << P[0] << " " << P[1] << " " << P[2] << std::endl; -// }); -// fp << " endloop"<< std::endl; -// fp << "endfacet"<< std::endl; -// }); -// fp << "endfacet"<< std::endl; - -// fp << "endsolid" << filename << std::endl; - -// fp.close(); -// return true; -//} - -//UINT8[80] – Header -//UINT32 – Number of triangles - -//foreach triangle -//REAL32[3] – Normal vector -//REAL32[3] – Vertex 1 -//REAL32[3] – Vertex 2 -//REAL32[3] – Vertex 3 -//UINT16 – Attribute byte count -//end +template +bool export_stl_bin(MAP& map, const typename MAP::template VertexAttributeHandler& position, const std::string& filename) +{ + + //UINT8[80] – Header + //UINT32 – Number of triangles + + //foreach triangle + //REAL32[3] – Normal vector + //REAL32[3] – Vertex 1 + //REAL32[3] – Vertex 2 + //REAL32[3] – Vertex 3 + //UINT16 – Attribute byte count + //end + + + std::ofstream fp(filename.c_str(), std::ios::out|std::ofstream::binary); + if (!fp.good()) + { + std::cout << "Unable to open file " << filename << std::endl; + return false; + } + + // header + nb triangles + unsigned int header[21]; + header[20] = map.template nb_cells(); + fp.write(reinterpret_cast(header),21*sizeof(unsigned int)); + + // buffer + std::array buffer_floats; // +1 for #@! ushort at end of each triangle + buffer_floats[12] = 0.0f; + + // local function for writing a triangle + auto write_tri = [&] (const VEC3& A, const VEC3& B, const VEC3& C) + { + VEC3 N = geometry::triangle_normal(A,B,C); + unsigned int i=0; + for (unsigned int j=0; j<3; ++j) + buffer_floats[i++]= float(N[j]); + for (unsigned int j=0; j<3; ++j) + buffer_floats[i++]= float(A[j]); + for (unsigned int j=0; j<3; ++j) + buffer_floats[i++]= float(B[j]); + for (unsigned int j=0; j<3; ++j) + buffer_floats[i++]= float(C[j]); + fp.write(reinterpret_cast(buffer_floats),12*sizeof(float)+2); // +2 for #@! ushort at end of each triangle + }; + + // indices for ear triangulation + std::vector table_indices; + table_indices.reserve(768); + + // write face cutted in triangle if necessary + map.template foreach_cell([&] (typename MAP::Face f) + { + if (map.is_triangle(f)) + { + Dart d = f.dart; + const VEC3& A = position[MAP::Vertex(d)]; + d = map.phi1(d); + const VEC3& B = position[MAP::Vertex(d)]; + d = map.phi1(d); + const VEC3& C = position[MAP::Vertex(d)]; + write_tri(A,B,C); + } + else + { + cgogn::geometry::compute_ear_triangulation(map,f,position,table_indices); + for(unsigned int i=0; i Date: Fri, 19 Feb 2016 14:41:30 +0100 Subject: [PATCH 123/402] debugging stl export, thanks to blender --- cgogn/io/map_export.h | 57 ++++++++++++++++++++++++++----------------- data/star_convex.off | 31 +++++++++++++++++++++++ 2 files changed, 66 insertions(+), 22 deletions(-) create mode 100644 data/star_convex.off diff --git a/cgogn/io/map_export.h b/cgogn/io/map_export.h index e1821a44..57f44d16 100644 --- a/cgogn/io/map_export.h +++ b/cgogn/io/map_export.h @@ -391,39 +391,40 @@ bool export_stl_ascii(MAP& map, const typename MAP::template VertexAttributeHand fp << "solid" << filename << std::endl; + std::vector table_indices; + table_indices.reserve(256); + map.template foreach_cell([&] (typename MAP::Face f) { - std::vector table_indices; - table_indices.reserve(768); - if (map.is_triangle(f)) { - VEC3 N = geometry::face_normal(map,f,position); + VEC3 N = geometry::face_normal(map,f,position); fp << "facet normal "<< N[0] << " "<< N[1]<< " " << N[2]<< std::endl; - fp << " outer loop"<< std::endl; + fp << "outer loop"<< std::endl; map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) { const VEC3& P = position[v]; - fp <<" vertex " << P[0] << " " << P[1] << " " << P[2] << std::endl; + fp <<"vertex " << P[0] << " " << P[1] << " " << P[2] << std::endl; }); - fp << " endloop"<< std::endl; + fp << "endloop"<< std::endl; fp << "endfacet"<< std::endl; } else { + table_indices.clear(); cgogn::geometry::compute_ear_triangulation(map,f,position,table_indices); for(unsigned int i=0; i(buffer_floats),12*sizeof(float)+2); // +2 for #@! ushort at end of each triangle + fp.write(reinterpret_cast(buffer_floats.data()),12*sizeof(float)+2); // +2 for #@! ushort at end of each triangle }; // indices for ear triangulation std::vector table_indices; table_indices.reserve(768); + unsigned int nb_tri = 0; + // write face cutted in triangle if necessary map.template foreach_cell([&] (typename MAP::Face f) { if (map.is_triangle(f)) { Dart d = f.dart; - const VEC3& A = position[MAP::Vertex(d)]; + const VEC3& A = position[typename MAP::Vertex(d)]; d = map.phi1(d); - const VEC3& B = position[MAP::Vertex(d)]; + const VEC3& B = position[typename MAP::Vertex(d)]; d = map.phi1(d); - const VEC3& C = position[MAP::Vertex(d)]; + const VEC3& C = position[typename MAP::Vertex(d)]; write_tri(A,B,C); + ++nb_tri; } else { + table_indices.clear(); cgogn::geometry::compute_ear_triangulation(map,f,position,table_indices); for(unsigned int i=0; i(&nb_tri),sizeof(unsigned int)); + } + fp.close(); return true; } diff --git a/data/star_convex.off b/data/star_convex.off new file mode 100644 index 00000000..3a77e3c9 --- /dev/null +++ b/data/star_convex.off @@ -0,0 +1,31 @@ +OFF +20 12 0 + +20.0 0.0 0.0 +8.09204 5.87528 0 +6.19246 19.0172 0 +-3.08108 9.51351 0 +-16.1653 11.7763 0 +-9.99999 0.0159265 0 +-16.2028 -11.7248 0 +-3.11137 -9.50365 0 +6.13185 -19.0368 0 +8.07329 -5.90102 0 +20.0 0.0 5.0 +8.09204 5.87528 5 +6.19246 19.0172 5 +-3.08108 9.51351 5 +-16.1653 11.7763 5 +-9.99999 0.0159265 5 +-16.2028 -11.7248 5 +-3.11137 -9.50365 5 +6.13185 -19.0368 5 +8.07329 -5.90102 5 + +10 10 11 12 13 14 15 16 17 18 19 +10 9 8 7 6 5 4 3 2 1 0 +6 0 1 2 12 11 10 +6 2 3 4 14 13 12 +6 4 5 6 16 15 14 +6 6 7 8 18 17 16 +6 8 9 0 10 19 18 From 89f8c63a5cb5369b209fd1fb217869f370d72654 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Fri, 19 Feb 2016 16:30:11 +0100 Subject: [PATCH 124/402] export ply (ascii & binary) --- cgogn/io/map_export.h | 202 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 201 insertions(+), 1 deletion(-) diff --git a/cgogn/io/map_export.h b/cgogn/io/map_export.h index 57f44d16..ed089dfd 100644 --- a/cgogn/io/map_export.h +++ b/cgogn/io/map_export.h @@ -55,7 +55,6 @@ namespace io template bool export_off(MAP& map, const typename MAP::template VertexAttributeHandler& position, const std::string& filename) { - std::ofstream fp(filename.c_str(), std::ios::out); if (!fp.good()) { @@ -533,6 +532,207 @@ bool export_stl_bin(MAP& map, const typename MAP::template VertexAttributeHandle } +template +std::string nameOfTypePly(const T& v) +{ + return "unknown"; +} + +template <> inline std::string nameOfTypePly(const char&) { return "int8"; } +template <> inline std::string nameOfTypePly(const short int&) { return "int16"; } +template <> inline std::string nameOfTypePly(const int&) { return "int"; } +template <> inline std::string nameOfTypePly(const unsigned int&) { return "uint"; } +template <> inline std::string nameOfTypePly(const unsigned char&) { return "uint8"; } +template <> inline std::string nameOfTypePly(const unsigned short int&) { return "uint16"; } +template <> inline std::string nameOfTypePly(const float&) { return "float"; } +template <> inline std::string nameOfTypePly(const double&) { return "float64"; } + +template +bool export_ply(MAP& map, const typename MAP::template VertexAttributeHandler& position, const std::string& filename) +{ + std::ofstream fp(filename.c_str(), std::ios::out); + if (!fp.good()) + { + std::cout << "Unable to open file " << filename << std::endl; + return false; + } + + fp << "ply" << std::endl ; + fp << "format ascii 1.0" << std::endl ; + fp << "comment File generated by the CGoGN library" << std::endl ; + fp << "comment See : http://cgogn.unistra.fr/" << std::endl ; + fp << "comment or contact : cgogn@unistra.fr" << std::endl ; + fp << "element vertex " << map.template nb_cells() << std::endl ; + fp << "property float x" << std::endl ; + fp << "property float y" << std::endl ; + fp << "property float z" << std::endl ; + fp << "element face " << map.template nb_cells() << std::endl ; + fp << "property list uint uint vertex_indices" << std::endl ; + fp << "end_header" << std::endl ; + + // set precision for real output + fp<< std::setprecision(12); + + // two pass of traversal to avoid huge buffer (with same performance); + + // first pass to save positions & store contiguous indices + typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); + ids.set_all_container_values(UINT_MAX); + unsigned int count = 0; + map.template foreach_cell([&] (typename MAP::Face f) + { + map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) + { + if (ids[v]==UINT_MAX) + { + ids[v] = count++; + const VEC3& P = position[v]; + fp << P[0] << " " << P[1] << " " << P[2] << std::endl; + } + }); + }); + + // second pass to save primitives + std::vector prim; + prim.reserve(20); + map.template foreach_cell([&] (typename MAP::Face f) + { + unsigned int valence = 0; + prim.clear(); + + map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) + { + prim.push_back(ids[v]); + ++valence; + }); + fp << valence; + for(unsigned int i: prim) + fp << " " << i; + fp << std::endl; + + }); + + map.remove_attribute(ids); + fp.close(); + return true; +} + + +template +bool export_ply_bin(MAP& map, const typename MAP::template VertexAttributeHandler& position, const std::string& filename) +{ + + // local function for little/big endian conversion + auto changeEndianness = [](unsigned int x) -> unsigned int + { + return (x>>24) | ((x<<8) & 0x00FF0000) | ((x>>8) & 0x0000FF00) | (x<<24); + }; + + + std::ofstream fp(filename.c_str(), std::ios::out|std::ofstream::binary); + if (!fp.good()) + { + std::cout << "Unable to open file " << filename << std::endl; + return false; + } + + fp << "ply" << std::endl ; + union + { + uint32_t i ; + char c[4] ; + } bint = {0x01020304} ; + if (bint.c[0] == 1) // big endian + fp << "format binary_big_endian 1.0" << std::endl ; + else + fp << "format binary_little_endian 1.0" << std::endl ; + fp << "comment File generated by the CGoGN library" << std::endl ; + fp << "comment See : http://cgogn.unistra.fr/" << std::endl ; + fp << "comment or contact : cgogn@unistra.fr" << std::endl ; + fp << "element vertex " << map.template nb_cells() << std::endl ; + fp << "property " << nameOfTypePly(position[0][0]) << " x" << std::endl ; + fp << "property " << nameOfTypePly(position[0][1]) << " y" << std::endl ; + fp << "property " << nameOfTypePly(position[0][2]) << " z" << std::endl ; + fp << "element face " << map.template nb_cells() << std::endl ; + fp << "property list uint uint vertex_indices" << std::endl ; + fp << "end_header" << std::endl ; + + // two pass of traversal to avoid huge buffer (with same performance); + + // first pass to save positions & store contiguous indices + typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); + + ids.set_all_container_values(UINT_MAX); + + unsigned int count = 0; + + static const unsigned int BUFFER_SZ = 1024*1024; + + std::vector buffer_pos; + buffer_pos.reserve(BUFFER_SZ); + + map.template foreach_cell([&] (typename MAP::Face f) + { + map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) + { + if (ids[v]==UINT_MAX) + { + ids[v] = count++; + buffer_pos.push_back(position[v]); + + if (buffer_pos.size() >= BUFFER_SZ) + { + fp.write(reinterpret_cast(&(buffer_pos[0])),buffer_pos.size()*sizeof(VEC3)); + buffer_pos.clear(); + } + } + }); + }); + if (!buffer_pos.empty()) + { + fp.write(reinterpret_cast(&(buffer_pos[0])),buffer_pos.size()*sizeof(VEC3)); + buffer_pos.clear(); + buffer_pos.shrink_to_fit(); + } + + // second pass to save primitives + std::vector buffer_prims; + buffer_prims.reserve(BUFFER_SZ+128);// + 128 to avoid re-allocations + + std::vector prim; + prim.reserve(20); + map.template foreach_cell([&] (typename MAP::Face f) + { + unsigned int valence = 0; + prim.clear(); + + map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) + { + prim.push_back(ids[v]); + ++valence; + }); + + buffer_prims.push_back(valence); + for(unsigned int i: prim) + buffer_prims.push_back(i); + + if (buffer_prims.size() >= BUFFER_SZ) + { + fp.write(reinterpret_cast(&(buffer_prims[0])), buffer_prims.size()*sizeof(unsigned int)); + buffer_prims.clear(); + } + }); + if (!buffer_prims.empty()) + { + fp.write(reinterpret_cast(&(buffer_prims[0])), buffer_prims.size()*sizeof(unsigned int)); + buffer_prims.clear(); + buffer_prims.shrink_to_fit(); + } + + map.remove_attribute(ids); + fp.close(); + return true; +} From 467f80eff29c9c9a25da5ac97d6f496a0b325848 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Fri, 19 Feb 2016 18:10:51 +0100 Subject: [PATCH 125/402] En cours: Clarification des types de cellules --- .../multithreading/bench_multithreading.cpp | 4 +- cgogn/core/CMakeLists.txt | 5 +- cgogn/core/basic/cell.h | 2 + cgogn/core/cmap/cmap0.cpp | 39 +++ cgogn/core/cmap/cmap0.h | 55 +++- cgogn/core/cmap/cmap1.cpp | 1 - cgogn/core/cmap/cmap1.h | 176 +++++------ cgogn/core/cmap/cmap2.h | 299 +++++++++--------- cgogn/core/cmap/cmap3.h | 20 +- cgogn/core/cmap/map_base.h | 16 +- cgogn/core/cmap/map_base_data.h | 6 +- cgogn/core/examples/map/map.cpp | 12 +- cgogn/core/tests/cmap/cmap1_test.cpp | 2 +- cgogn/core/tests/cmap/cmap1_topo_test.cpp | 10 +- cgogn/geometry/algos/normal.h | 4 +- cgogn/io/examples/cmap2_import.cpp | 12 +- cgogn/io/surface_import.h | 2 +- cgogn/multiresolution/cph/ihcmap2.h | 48 +-- cgogn/multiresolution/cph/ihcmap2_adaptive.h | 10 +- cgogn/multiresolution/cph/ihcmap2_regular.h | 8 +- 20 files changed, 403 insertions(+), 328 deletions(-) create mode 100644 cgogn/core/cmap/cmap0.cpp diff --git a/benchmarks/multithreading/bench_multithreading.cpp b/benchmarks/multithreading/bench_multithreading.cpp index 29649da3..ecaeee92 100644 --- a/benchmarks/multithreading/bench_multithreading.cpp +++ b/benchmarks/multithreading/bench_multithreading.cpp @@ -36,10 +36,10 @@ using Map2 = cgogn::CMap2; Map2 map; -const cgogn::Orbit VERTEX = Map2::VERTEX; +const cgogn::Orbit VERTEX = Map2::Vertex2::SELF_ORBIT; using Vertex = cgogn::Cell; -const cgogn::Orbit FACE = Map2::FACE; +const cgogn::Orbit FACE = Map2::Face2::SELF_ORBIT; using Face = cgogn::Cell; const unsigned int ITERATIONS = 1u; diff --git a/cgogn/core/CMakeLists.txt b/cgogn/core/CMakeLists.txt index f16daf12..a3de8ca8 100644 --- a/cgogn/core/CMakeLists.txt +++ b/cgogn/core/CMakeLists.txt @@ -45,8 +45,9 @@ set(SOURCE_FILES basic/dart_marker.cpp cmap/map_base_data.cpp - cmap/cmap1.cpp - cmap/cmap2.cpp + cmap/cmap0.cpp + cmap/cmap1.cpp + cmap/cmap2.cpp cmap/cmap3.cpp cmap/cmap2_builder.cpp cmap/cmap3_builder.cpp diff --git a/cgogn/core/basic/cell.h b/cgogn/core/basic/cell.h index 61b92b18..63eabdf3 100644 --- a/cgogn/core/basic/cell.h +++ b/cgogn/core/basic/cell.h @@ -83,6 +83,8 @@ class Cell { public: + static const Orbit SELF_ORBIT = ORBIT; + /** * \brief the dart representing this cell */ diff --git a/cgogn/core/cmap/cmap0.cpp b/cgogn/core/cmap/cmap0.cpp new file mode 100644 index 00000000..51c4b83a --- /dev/null +++ b/cgogn/core/cmap/cmap0.cpp @@ -0,0 +1,39 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#define CGOGN_CORE_DLL_EXPORT +#define CORE_MAP_MAP0_CPP_ + +#include + +namespace cgogn +{ + + template class CGOGN_CORE_API CMap0_T>; + template class CGOGN_CORE_API DartMarker>; + template class CGOGN_CORE_API DartMarkerStore>; + template class CGOGN_CORE_API DartMarkerNoUnmark>; + template class CGOGN_CORE_API CellMarker, Orbit::DART>; + template class CGOGN_CORE_API CellMarkerStore, Orbit::DART>; + +} // namespace cgogn diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index f7b881d2..e9ac6452 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -34,16 +34,22 @@ class CMap0_T : public MapBase { public: + static const int PRIM_SIZE = 1; + typedef MAP_TRAITS MapTraits; typedef MAP_TYPE MapType; typedef MapBase Inherit; typedef CMap0_T Self; friend class MapBase; + template friend class DartMarker_T; + template friend class DartMarkerStore; - static const int PRIM_SIZE = 1; +// static const Orbit VERTEX = Orbit::DART; - static const Orbit DART = Orbit::DART; + typedef Cell Vertex0; + + typedef Vertex0 Vertex; template using ChunkArray = typename Inherit::template ChunkArray; @@ -53,7 +59,7 @@ class CMap0_T : public MapBase template using AttributeHandler = typename Inherit::template AttributeHandler; template - using DartAttributeHandler = AttributeHandler; + using DartAttributeHandler = AttributeHandler; using DartMarker = typename cgogn::DartMarker; using DartMarkerStore = typename cgogn::DartMarkerStore; @@ -74,6 +80,19 @@ class CMap0_T : public MapBase Self& operator=(Self const&) = delete; Self& operator=(Self &&) = delete; + /******************************************************************************* + * Low-level topological operations + *******************************************************************************/ + +protected: + + /*! + * \brief Init an newly added dart. + */ + inline void init_dart(Dart d) + { + } + /******************************************************************************* * High-level embedded and topological operations *******************************************************************************/ @@ -85,16 +104,25 @@ class CMap0_T : public MapBase * \return The added dart. If the map has DART attributes, * the inserted darts are automatically embedded on new attribute elements. */ - Dart add_vertex() + inline Vertex0 add_vertex() { CGOGN_CHECK_CONCRETE_TYPE; - Dart d = this->add_dart(); + Vertex0 v(this->add_dart()); + + if (this->is_embedded(v)) this->new_embedding(v); + + return v; + } - if (this->template is_orbit_embedded()) - this->new_embedding(d); + /*! + * \brief Remove a vertex (or dart) from the map. + */ + inline void remove_vertex(Vertex0 d) + { + CGOGN_CHECK_CONCRETE_TYPE; - return d; + this->remove_dart(d.dart); } /******************************************************************************* @@ -113,7 +141,7 @@ class CMap0_T : public MapBase inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const { static_assert(ORBIT == Orbit::DART, - "Orbit not supported in a CMap1"); + "Orbit not supported in a CMap0"); this->foreach_dart_of_DART(c, f); } }; @@ -127,6 +155,15 @@ struct CMap0Type template using CMap0 = CMap0_T>; +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_MAP_MAP0_CPP_)) +extern template class CGOGN_CORE_API CMap0_T>; +extern template class CGOGN_CORE_API DartMarker>; +extern template class CGOGN_CORE_API DartMarkerStore>; +extern template class CGOGN_CORE_API DartMarkerNoUnmark>; +extern template class CGOGN_CORE_API CellMarker, Orbit::DART>; +extern template class CGOGN_CORE_API CellMarkerStore, Orbit::DART>; +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_MAP_MAP0_CPP_)) + } // namespace cgogn #endif // CORE_CMAP_CMAP0_H_ diff --git a/cgogn/core/cmap/cmap1.cpp b/cgogn/core/cmap/cmap1.cpp index ef8a8125..6f588f7a 100644 --- a/cgogn/core/cmap/cmap1.cpp +++ b/cgogn/core/cmap/cmap1.cpp @@ -29,7 +29,6 @@ namespace cgogn { -// template class CGOGN_CORE_API MapBaseData; template class CGOGN_CORE_API CMap1_T>; template class CGOGN_CORE_API DartMarker>; template class CGOGN_CORE_API DartMarkerStore>; diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 994cc9eb..110a60d5 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -34,6 +34,8 @@ class CMap1_T : public CMap0_T { public: + static const int PRIM_SIZE = 1; + typedef MAP_TRAITS MapTraits; typedef MAP_TYPE MapType; typedef CMap0_T Inherit; @@ -43,12 +45,14 @@ class CMap1_T : public CMap0_T template friend class DartMarker_T; template friend class DartMarkerStore; - static const int PRIM_SIZE = 1; +// static const Orbit DART = Orbit::DART; +// static const Orbit FACE = Orbit::PHI1; - static const Orbit DART = Orbit::DART; - static const Orbit FACE = Orbit::PHI1; + typedef Cell Vertex1; + typedef Cell Face1; - typedef Cell Face; + typedef Vertex1 Vertex; + typedef Face1 Face; template using ChunkArray = typename Inherit::template ChunkArray; @@ -58,9 +62,9 @@ class CMap1_T : public CMap0_T template using AttributeHandler = typename Inherit::template AttributeHandler; template - using DartAttributeHandler = AttributeHandler; + using DartAttributeHandler = AttributeHandler; template - using FaceAttributeHandler = AttributeHandler; + using FaceAttributeHandler = AttributeHandler; using DartMarker = typename cgogn::DartMarker; using DartMarkerStore = typename cgogn::DartMarkerStore; @@ -106,6 +110,7 @@ class CMap1_T : public CMap0_T */ inline void init_dart(Dart d) { + Inherit::init_dart(d); (*phi1_)[d.index] = d; (*phi_1_)[d.index] = d; } @@ -180,6 +185,58 @@ class CMap1_T : public CMap0_T * High-level embedded and topological operations *******************************************************************************/ +protected: + + /** + * \brief Split a vertex. + * \param d : a dart of the vertex + * \return A dart of inserted vertex + * A new vertex is inserted after v in the PHI1 orbit. + */ + inline Dart split_vertex_topo(Dart d) + { + Dart e = this->add_dart(); // Create a new dart e + phi1_sew(d, e); // Insert e between d and phi1(d) + return e; + } + +public: + + /** + * \brief Split a vertex. + * \param d : a vertex + * \return The inserted vertex + * A new vertex is inserted after v in the PHI1 orbit. + * If the map has DART or FACE attributes, the inserted darts + * are automatically embedded on new attribute elements. + */ + inline Vertex1 split_vertex(Vertex1 v) + { + CGOGN_CHECK_CONCRETE_TYPE; + + Vertex1 nv = split_vertex_topo(v); + + if (this->is_embedded(nv)) this->new_embedding(nv); + + if (this->is_embedded(Face1(nv))) this->copy_embedding(Face1(nv), Face1(v)); + + return nv; + } + + /** + * \brief Remove a vertex from its face and delete it. + * @param v : a vertex + * The vertex that preceeds v in the face is linked its successor. + */ + inline void remove_vertex(Vertex1 v) + { + CGOGN_CHECK_CONCRETE_TYPE; + + Dart e = phi_1(v); + if (e != v.dart) phi1_unsew(e); + this->remove_dart(v.dart); + } + protected: /*! @@ -187,15 +244,15 @@ class CMap1_T : public CMap0_T * \param size : the number of darts in the built face * \return A dart of the built face */ - inline Face add_face_topo(unsigned int size) + inline Dart add_face_topo(unsigned int size) { cgogn_message_assert(size > 0u, "Cannot create an empty face"); Dart d = this->add_dart(); for (unsigned int i = 1u; i < size; ++i) - cut_edge_topo(d); + split_vertex_topo(d); - return Face(d); + return d; } public: @@ -206,32 +263,30 @@ class CMap1_T : public CMap0_T * \return A dart of the built face. If the map has DART or FACE attributes, * the inserted darts are automatically embedded on new attribute elements. */ - Face add_face(unsigned int size) + Face1 add_face(unsigned int size) { CGOGN_CHECK_CONCRETE_TYPE; - Face f = add_face_topo(size); + Face1 f = add_face_topo(size); - if (this->template is_orbit_embedded()) - foreach_dart_of_PHI1(f.dart, [this] (Dart d) + if (this->is_embedded(Vertex1(f))) + foreach_dart_of_PHI1(f.dart, [this] (Vertex1 v) { - this->template new_embedding(d); + this->new_embedding(v); }); - if (this->template is_orbit_embedded()) - this->new_orbit_embedding(f); + if (this->is_embedded(f)) this->new_orbit_embedding(f); return f; } -protected: - /*! * \brief Remove a face from the map. * \param d : a dart of the face to remove */ - inline void remove_face_topo(Dart d) + inline void remove_face(Face1 f) { + Dart d = f.dart; Dart e = phi1(d); while(e != d) { @@ -243,31 +298,7 @@ class CMap1_T : public CMap0_T this->remove_dart(d); } - /** - * \brief Cut an edge. - * \param d : the dart that represents the edge to cut - * \return the inserted new dart - * The edge of d is cut by inserting a new dart after d in the Phi1 orbit. - */ - inline Dart cut_edge_topo(Dart d) - { - Dart e = this->add_dart(); // Create a new dart e - phi1_sew(d, e); // Insert e between d and phi1(d) - return e; - } - - /** - * \brief Remove edge d from its face and delete it - * @param d : the edge to collapse - * the edge preceeding d in the face is linked to the successor of d - */ - inline void collapse_edge_topo(Dart d) - { - Dart e = phi_1(d); - cgogn_message_assert(e != d,"phi1_unsew: Cannot collapse fixed point"); - phi1_unsew(e); - this->remove_dart(d); - } +protected: inline void reverse_face_topo(Dart d) { @@ -290,7 +321,7 @@ class CMap1_T : public CMap0_T public: - inline unsigned int degree(Face f) const + inline unsigned int degree(Face1 f) const { return this->nb_darts(f); } @@ -373,60 +404,13 @@ class CMap1_T : public CMap0_T * Incidence traversal *******************************************************************************/ - template - inline void foreach_incident_cell(Cell c, const FUNC& f) const + template + inline void foreach_incident_vertex(Face1 f, const FUNC& func) const { - static_assert(check_func_parameter_type(FUNC, Cell), + static_assert(check_func_parameter_type(FUNC, Vertex1), "Wrong function cell parameter type"); - - static_assert((ORBIT_IN == FACE && ORBIT_OUT == DART), - "Invalid incidence relation"); - - foreach_dart_of_orbit(c, [&] (Dart d) - { - f(Cell(d)); - }); + foreach_dart_of_orbit(f, func); } - -// To remove : on a pas la notion de Vertex ou de Edge ici ... - -// template -// inline void foreach_incident_vertex(Face f, const FUNC& func) const -// { -// static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); -// foreach_dart_of_orbit(f, func); -// } - -// template -// inline void foreach_incident_edge(Face f, const FUNC& func) const -// { -// static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); -// foreach_dart_of_orbit(f, func); -// } - - /******************************************************************************* - * Adjacence traversal - *******************************************************************************/ - -// To remove - -// template -// inline void foreach_adjacent_vertex_through_edge(Vertex v, const FUNC& f) const -// { -// static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); -// f(Vertex(phi1(v.dart))); -// f(Vertex(phi_1(v.dart))); -// } - -// To remove - -// template -// inline void foreach_adjacent_edge_through_vertex(Edge e, const FUNC& f) const -// { -// static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); -// f(Edge(phi1(e.dart))); -// f(Edge(phi_1(e.dart))); -// } }; template diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 4b0a9fd4..a7bc6b4b 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -51,16 +51,22 @@ class CMap2_T : public CMap1_T static const int PRIM_SIZE = 1; - static const Orbit DART = Orbit::DART; +// static const Orbit DART = Orbit::DART; static const Orbit VERTEX = Orbit::PHI21; static const Orbit EDGE = Orbit::PHI2; static const Orbit FACE = Orbit::PHI1; - static const Orbit VOLUME = Orbit::PHI1_PHI2; +// static const Orbit VOLUME = Orbit::PHI1_PHI2; - typedef Cell Vertex; - typedef Cell Edge; - typedef Cell Face; - typedef Cell Volume; + typedef Cell Vertex0; + typedef Cell Vertex2; + typedef Cell Edge2; + typedef Cell Face2; + typedef Cell Volume2; + + typedef Vertex2 Vertex; + typedef Edge2 Edge; + typedef Face2 Face; + typedef Volume2 Volume; template using ChunkArray = typename Inherit::template ChunkArray; @@ -70,13 +76,13 @@ class CMap2_T : public CMap1_T template using AttributeHandler = typename Inherit::template AttributeHandler; template - using VertexAttributeHandler = AttributeHandler; + using VertexAttributeHandler = AttributeHandler; template - using EdgeAttributeHandler = AttributeHandler; + using EdgeAttributeHandler = AttributeHandler; template - using FaceAttributeHandler = AttributeHandler; + using FaceAttributeHandler = AttributeHandler; template - using VolumeAttributeHandler = AttributeHandler; + using VolumeAttributeHandler = AttributeHandler; using DartMarker = typename cgogn::DartMarker; using DartMarkerStore = typename cgogn::DartMarkerStore; @@ -184,9 +190,9 @@ class CMap2_T : public CMap1_T { Dart e = phi2(d); // Get the adjacent 1D-edge - phi2_unsew(d); // Unsew the 2D-edge separating its two 1D-edges - Dart nd = Inherit::cut_edge_topo(d); - Dart ne = Inherit::cut_edge_topo(e); // Cut the two adjacent 1D-edges + phi2_unsew(d); // Separate the two 1D-edges of the edge + Dart nd = this->split_vertex_topo(d); + Dart ne = this->split_vertex_topo(e); // Cut the two adjacent 1D-edges phi2_sew(d, ne); // Sew the new 1D-edges phi2_sew(e, nd); // To build the new 2D-edges @@ -202,47 +208,47 @@ class CMap2_T : public CMap1_T * \return A dart of the inserted vertex * The edge of d is cut by inserting a new vertex. * The returned dart is the dart of the inserted vertex that belongs to the face of d. - * If the map has DART, VERTEX, EDGE, FACE or VOLUME attributes, + * If the map has Dart, Vertex2, Edge2, Face2 or Volume2 attributes, * the inserted darts are automatically embedded on new attribute elements. - * Actually a VERTEX attribute is created, if needed, for the inserted vertex. + * Actually a Vertex2 attribute is created, if needed, for the inserted vertex. */ - inline Vertex cut_edge(Edge e) + inline Vertex2 cut_edge(Edge2 e) { CGOGN_CHECK_CONCRETE_TYPE; const Dart ne = cut_edge_topo(e); const Dart nf = this->phi1(phi2(e)); - if (this->template is_orbit_embedded()) { - this->template new_embedding(ne); - this->template new_embedding(nf); + if (this->is_embedded(Vertex0(ne))) { + this->new_embedding(Vertex0(ne)); + this->new_embedding(Vertex0(nf)); } - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) { - const unsigned int idx = this->template new_embedding(ne); - this->template set_embedding(nf, idx); + const unsigned int idx = this->new_embedding(Vertex2(ne)); + this->set_embedding(Vertex2(nf), idx); } - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) { - this->template copy_embedding(nf, e); - this->template new_orbit_embedding(ne); + this->copy_embedding(Edge2(nf), e); + this->new_orbit_embedding(Edge2(ne)); } - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) { - this->template copy_embedding(ne, e.dart); - this->template copy_embedding(nf, this->phi_1(nf)); + this->copy_embedding(Face2(ne), Face2(e.dart)); + this->copy_embedding(Face2(nf), Face2(this->phi_1(nf))); } - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) { - const unsigned int idx = this->template new_embedding(ne); - this->template set_embedding(nf, idx); + const unsigned int idx = this->new_embedding(Volume2(ne)); + this->set_embedding(Volume2(nf), idx); } - return Vertex(ne); + return Vertex2(ne); } protected: @@ -274,10 +280,10 @@ class CMap2_T : public CMap1_T Dart dd = this->phi_1(d); Dart ee = this->phi_1(e); - Dart nd = Inherit::cut_edge_topo(dd); // cut the edge before d (insert a new dart before d) - Dart ne = Inherit::cut_edge_topo(ee); // cut the edge before e (insert a new dart before e) - this->phi1_sew(dd, ee); // subdivide phi1 cycle at the inserted darts - phi2_sew(nd, ne); // build the new 2D-edge from the inserted darts + Dart nd = Inherit::split_vertex_topo(dd); // cut the edge before d (insert a new dart before d) + Dart ne = Inherit::split_vertex_topo(ee); // cut the edge before e (insert a new dart before e) + this->phi1_sew(dd, ee); // subdivide phi1 cycle at the inserted darts + phi2_sew(nd, ne); // build the new 2D-edge from the inserted darts } public: @@ -288,46 +294,46 @@ class CMap2_T : public CMap1_T * \param e : second vertex * The vertices d and e should belong to the same face and be distinct from each other. * An edge made of two new darts is inserted between the two given vertices. - * If the map has DART, VERTEX, EDGE, FACE or VOLUME attributes, + * If the map has Dart, Vertex2, Edge2, Face2 or Volume2 attributes, * the inserted darts are automatically embedded on new attribute elements. - * Actually an EDGE attribute is created, if needed, for the inserted edge - * and a new FACE attribute is created for the subdived face that e belongs to. - * The FACE attribute of the subdived face that d belongs to is kept unchanged. + * Actually an Edge2 attribute is created, if needed, for the inserted edge + * and a new Face2 attribute is created for the subdived face that e belongs to. + * The Face2 attribute of the subdived face that d belongs to is kept unchanged. */ - inline void cut_face(Vertex d, Vertex e) + inline void cut_face(Vertex2 d, Vertex2 e) { CGOGN_CHECK_CONCRETE_TYPE; cut_face_topo(d,e); - const Dart nd = this->phi_1(d); - const Dart ne = this->phi_1(e); + Dart nd = this->phi_1(d); + Dart ne = this->phi_1(e); - if (this->template is_orbit_embedded()) { - this->template new_embedding(nd); - this->template new_embedding(ne); + if (this->is_embedded(Vertex0(nd))) { + this->new_embedding(Vertex0(nd)); + this->new_embedding(Vertex0(ne)); } - if (this->template is_orbit_embedded()) + if (this->is_embedded(Vertex2(nd))) { - this->template copy_embedding(nd, e); - this->template copy_embedding(ne, d); + this->copy_embedding(Vertex2(nd), e); + this->copy_embedding(Vertex2(ne), d); } - if (this->template is_orbit_embedded()) + if (this->is_embedded(Edge2(nd))) { - this->template new_orbit_embedding(nd); + this->new_orbit_embedding(Edge2(nd)); } - if (this->template is_orbit_embedded()) + if (this->is_embedded(Face2(nd))) { - this->template copy_embedding(nd, d.dart); - this->template new_orbit_embedding(ne); + this->copy_embedding(Face2(nd), Face2(d.dart)); + this->new_orbit_embedding(Face2(ne)); } - if (this->template is_orbit_embedded()) + if (this->is_embedded(Volume2(nd))) { - unsigned int idx = this->template copy_embedding(nd, d.dart); - this->template set_embedding(ne, idx); + unsigned int idx = this->copy_embedding(Volume2(nd), Volume2(d.dart)); + this->set_embedding(Volume2(ne), idx); } } @@ -338,21 +344,20 @@ class CMap2_T : public CMap1_T * \param size : the number of darts in the built face * \return A dart of the built face. */ - Face add_face_topo(unsigned int size) + Dart add_face_topo(unsigned int size) { - const Face f = Inherit::add_face_topo(size); - const Face g = Inherit::add_face_topo(size); + Dart d = Inherit::add_face_topo(size); + Dart e = Inherit::add_face_topo(size); - Dart d = f.dart; - Dart e = g.dart; + Dart it = d; do { - phi2_sew(d, e); - d = this->phi1(d); + phi2_sew(it, e); + it = this->phi1(it); e = this->phi_1(e); - } while (d != f.dart); + } while (it != d); - return f; + return d; } public: @@ -361,39 +366,39 @@ class CMap2_T : public CMap1_T * \brief Add a face in the map. * \param size : the number of edges in the built face * \return A dart of the built face - * If the map has DART, VERTEX, EDGE, FACE or VOLUME attributes, + * If the map has Dart, Vertex2, Edge2, Face2 or Volume2 attributes, * the inserted darts are automatically embedded on new attribute elements. - * Actually a FACE attribute is created, if needed, for the new face. + * Actually a Face2 attribute is created, if needed, for the new face. */ - Face add_face(unsigned int size) + Face2 add_face(unsigned int size) { CGOGN_CHECK_CONCRETE_TYPE; - Face f = add_face_topo(size); + Face2 f = add_face_topo(size); - if (this->template is_orbit_embedded()) + if (this->is_embedded(Vertex0(f.dart))) foreach_dart_of_orbit(f, [this] (Dart d) { - this->template new_embedding(d); + this->new_embedding(Vertex0(d)); }); - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) foreach_dart_of_orbit(f, [this] (Dart v) { - this->template new_embedding(v); + this->template new_embedding(v); }); - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) foreach_dart_of_orbit(f, [this] (Dart e) { - this->template new_embedding(e); + this->template new_embedding(e); }); - if (this->template is_orbit_embedded()) - this->template new_embedding(f.dart); + if (this->template is_orbit_embedded()) + this->template new_embedding(f.dart); - if (this->template is_orbit_embedded()) - this->template new_orbit_embedding(f.dart); + if (this->template is_orbit_embedded()) + this->template new_orbit_embedding(f.dart); return f; } @@ -440,37 +445,37 @@ class CMap2_T : public CMap1_T if (phi2(d) == d) { close_hole_topo(d); - const Face new_face = phi2(d); + const Face2 new_face = phi2(d); - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) foreach_dart_of_orbit(new_face, [this] (Dart d) { - this->template new_embedding(d); + this->template new_embedding(d); }); - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) foreach_dart_of_orbit(new_face, [this] (Dart fd) { - this->template copy_embedding(fd, this->phi1(phi2(fd))); + this->template copy_embedding(fd, this->phi1(phi2(fd))); }); - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) foreach_dart_of_orbit(new_face, [this] (Dart fd) { - this->template copy_embedding(fd, phi2(fd)); + this->template copy_embedding(fd, phi2(fd)); }); - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) { this->template new_orbit_embedding(new_face); } - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) { - const unsigned int idx = this->template get_embedding(d); + const unsigned int idx = this->template get_embedding(d); foreach_dart_of_orbit(new_face, [this, idx] (Dart fd) { - this->template set_embedding(fd, idx); + this->template set_embedding(fd, idx); }); } } @@ -479,12 +484,12 @@ class CMap2_T : public CMap1_T public: - inline unsigned int degree(Face f) const + inline unsigned int degree(Face2 f) const { return Inherit::degree(f); } - inline unsigned int degree(Vertex v) const + inline unsigned int degree(Vertex2 v) const { return this->nb_darts(v); } @@ -653,18 +658,18 @@ class CMap2_T : public CMap1_T static_assert(check_func_parameter_type(FUNC, Cell), "Wrong function cell parameter type"); - static_assert((ORBIT_IN == VERTEX && ORBIT_OUT == EDGE) || - (ORBIT_IN == VERTEX && ORBIT_OUT == FACE) || - (ORBIT_IN == EDGE && ORBIT_OUT == VERTEX) || - (ORBIT_IN == EDGE && ORBIT_OUT == FACE) || - (ORBIT_IN == FACE && ORBIT_OUT == VERTEX) || - (ORBIT_IN == FACE && ORBIT_OUT == EDGE) || - (ORBIT_IN == VOLUME && ORBIT_OUT == VERTEX) || - (ORBIT_IN == VOLUME && ORBIT_OUT == EDGE) || - (ORBIT_IN == VOLUME && ORBIT_OUT == FACE), + static_assert((ORBIT_IN == Orbit::PHI21 && ORBIT_OUT == Orbit::PHI2) || + (ORBIT_IN == Orbit::PHI21 && ORBIT_OUT == Orbit::PHI1) || + (ORBIT_IN == Orbit::PHI2 && ORBIT_OUT == Orbit::PHI21) || + (ORBIT_IN == Orbit::PHI2 && ORBIT_OUT == Orbit::PHI1) || + (ORBIT_IN == Orbit::PHI1 && ORBIT_OUT == Orbit::PHI21) || + (ORBIT_IN == Orbit::PHI1 && ORBIT_OUT == Orbit::PHI2) || + (ORBIT_IN == Orbit::PHI1_PHI2 && ORBIT_OUT == Orbit::PHI21) || + (ORBIT_IN == Orbit::PHI1_PHI2 && ORBIT_OUT == Orbit::PHI2) || + (ORBIT_IN == Orbit::PHI1_PHI2 && ORBIT_OUT == Orbit::PHI1), "Invalid incidence relation"); - if (ORBIT_IN == VOLUME) { + if (ORBIT_IN == Orbit::PHI1_PHI2) { DartMarkerStore marker(*this); foreach_dart_of_orbit(c, [&] (Dart d) { @@ -686,25 +691,25 @@ class CMap2_T : public CMap1_T template inline void foreach_incident_vertex(Cell c, const FUNC& f) const { - foreach_incident_cell(c, f); + foreach_incident_cell(c, f); } template inline void foreach_incident_edge(Cell c, const FUNC& f) const { - foreach_incident_cell(c, f); + foreach_incident_cell(c, f); } template inline void foreach_incident_face(Cell c, const FUNC& f) const { - foreach_incident_cell(c, f); + foreach_incident_cell(c, f); } template inline void foreach_incident_volume(Cell c, const FUNC& f) const { - foreach_incident_cell(c, f); + foreach_incident_cell(c, f); } /*! @@ -716,15 +721,15 @@ class CMap2_T : public CMap1_T static_assert(check_func_parameter_type(FUNC, Cell), "Wrong function cell parameter type"); - static_assert((ORBIT_IN == VERTEX && ORBIT_OUT == EDGE) || - (ORBIT_IN == VERTEX && ORBIT_OUT == FACE) || - (ORBIT_IN == EDGE && ORBIT_OUT == VERTEX) || - (ORBIT_IN == EDGE && ORBIT_OUT == FACE) || - (ORBIT_IN == FACE && ORBIT_OUT == VERTEX) || - (ORBIT_IN == FACE && ORBIT_OUT == EDGE) || - (ORBIT_IN == VOLUME && ORBIT_OUT == VERTEX) || - (ORBIT_IN == VOLUME && ORBIT_OUT == EDGE) || - (ORBIT_IN == VOLUME && ORBIT_OUT == FACE), + static_assert((ORBIT_IN == Orbit::PHI21 && ORBIT_OUT == Orbit::PHI2) || + (ORBIT_IN == Orbit::PHI21 && ORBIT_OUT == Orbit::PHI1) || + (ORBIT_IN == Orbit::PHI2 && ORBIT_OUT == Orbit::PHI21) || + (ORBIT_IN == Orbit::PHI2 && ORBIT_OUT == Orbit::PHI1) || + (ORBIT_IN == Orbit::PHI1 && ORBIT_OUT == Orbit::PHI21) || + (ORBIT_IN == Orbit::PHI1 && ORBIT_OUT == Orbit::PHI2) || + (ORBIT_IN == Orbit::PHI1_PHI2 && ORBIT_OUT == Orbit::PHI21) || + (ORBIT_IN == Orbit::PHI1_PHI2 && ORBIT_OUT == Orbit::PHI2) || + (ORBIT_IN == Orbit::PHI1_PHI2 && ORBIT_OUT == Orbit::PHI1), "Invalid incidence relation"); DartMarkerStore marker(*this); @@ -772,14 +777,14 @@ class CMap2_T : public CMap1_T // inline void foreach_incident_vertex(Face f, const FUNC& func) const // { // static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); -// foreach_dart_of_orbit(f, func); +// foreach_dart_of_orbit(f, func); // } // template // inline void foreach_incident_edge(Face f, const FUNC& func) const // { // static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); -// foreach_dart_of_orbit(f, func); +// foreach_dart_of_orbit(f, func); // } // template @@ -787,11 +792,11 @@ class CMap2_T : public CMap1_T // { // static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); // DartMarkerStore marker(*this); -// foreach_dart_of_orbit(v, [&] (Dart d) +// foreach_dart_of_orbit(v, [&] (Dart d) // { // if (!marker.is_marked(d)) // { -// marker.template mark_orbit(d); +// marker.template mark_orbit(d); // f(d); // } // }); @@ -802,11 +807,11 @@ class CMap2_T : public CMap1_T // { // static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); // DartMarkerStore marker(*this); -// foreach_dart_of_orbit(v, [&] (Dart d) +// foreach_dart_of_orbit(v, [&] (Dart d) // { // if (!marker.is_marked(d)) // { -// marker.template mark_orbit(d); +// marker.template mark_orbit(d); // f(d); // } // }); @@ -817,11 +822,11 @@ class CMap2_T : public CMap1_T // { // static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); // DartMarkerStore marker(*this); -// foreach_dart_of_orbit(v, [&] (Dart d) +// foreach_dart_of_orbit(v, [&] (Dart d) // { // if (!marker.is_marked(d)) // { -// marker.template mark_orbit(d); +// marker.template mark_orbit(d); // f(d); // } // }); @@ -832,79 +837,79 @@ class CMap2_T : public CMap1_T *******************************************************************************/ template - inline void foreach_adjacent_vertex_through_edge(Vertex v, const FUNC& f) const + inline void foreach_adjacent_vertex_through_edge(Vertex2 v, const FUNC& f) const { - static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); - foreach_dart_of_orbit(v, [this, &f] (Dart d) { f(Vertex(this->phi2(d))); }); + static_assert(check_func_parameter_type(FUNC, Vertex2), "Wrong function cell parameter type"); + foreach_dart_of_orbit(v, [this, &f] (Dart d) { f(Vertex2(this->phi2(d))); }); } template - inline void foreach_adjacent_vertex_through_face(Vertex v, const FUNC& f) const + inline void foreach_adjacent_vertex_through_face(Vertex2 v, const FUNC& f) const { - static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); + static_assert(check_func_parameter_type(FUNC, Vertex2), "Wrong function cell parameter type"); foreach_dart_of_orbit(v, [this, &f] (Dart vd) { Dart vd1 = this->phi1(vd); - this->foreach_dart_of_orbit(vd, [&f, vd, vd1] (Dart fd) + this->foreach_dart_of_orbit(vd, [&f, vd, vd1] (Dart fd) { - // skip Vertex v itself and its first successor around current face + // skip Vertex2 v itself and its first successor around current face if (fd != vd && fd != vd1) - f(Vertex(fd)); + f(Vertex2(fd)); }); }); } template - inline void foreach_adjacent_edge_through_vertex(Edge e, const FUNC& f) const + inline void foreach_adjacent_edge_through_vertex(Edge2 e, const FUNC& f) const { - static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); + static_assert(check_func_parameter_type(FUNC, Edge2), "Wrong function cell parameter type"); foreach_dart_of_orbit(e, [&f, this] (Dart ed) { - this->foreach_dart_of_orbit(ed, [&f, ed] (Dart vd) + this->foreach_dart_of_orbit(ed, [&f, ed] (Dart vd) { // skip Edge e itself if (vd != ed) - f(Edge(vd)); + f(Edge2(vd)); }); }); } template - inline void foreach_adjacent_edge_through_face(Edge e, const FUNC& f) const + inline void foreach_adjacent_edge_through_face(Edge2 e, const FUNC& f) const { - static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); + static_assert(check_func_parameter_type(FUNC, Edge2), "Wrong function cell parameter type"); foreach_dart_of_orbit(e, [&f, this] (Dart ed) { - this->foreach_dart_of_orbit(ed, [&f, ed] (Dart fd) + this->foreach_dart_of_orbit(ed, [&f, ed] (Dart fd) { // skip Edge e itself if (fd != ed) - f(Edge(fd)); + f(Edge2(fd)); }); }); } template - inline void foreach_adjacent_face_through_vertex(Face f, const FUNC& func) const + inline void foreach_adjacent_face_through_vertex(Face2 f, const FUNC& func) const { - static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); + static_assert(check_func_parameter_type(FUNC, Face2), "Wrong function cell parameter type"); foreach_dart_of_orbit(f, [this, &func] (Dart fd) { Dart fd1 = this->phi2(this->phi_1(fd)); - this->foreach_dart_of_orbit(fd, [&func, fd, fd1] (Dart vd) + this->foreach_dart_of_orbit(fd, [&func, fd, fd1] (Dart vd) { // skip Face f itself and its first successor around current vertex if (vd != fd && vd != fd1) - func(Face(vd)); + func(Face2(vd)); }); }); } template - inline void foreach_adjacent_face_through_edge(Face f, const FUNC& func) const + inline void foreach_adjacent_face_through_edge(Face2 f, const FUNC& func) const { - static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); - foreach_dart_of_orbit(f, [this, &func] (Dart d) { func(Face(this->phi2(d))); }); + static_assert(check_func_parameter_type(FUNC, Face2), "Wrong function cell parameter type"); + foreach_dart_of_orbit(f, [this, &func] (Dart d) { func(Face2(this->phi2(d))); }); } }; diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 92547771..ea7f51e7 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -344,21 +344,21 @@ class CMap3_T : public CMap2_T this->template new_embedding(d); }); - if (this->template is_orbit_embedded()) - Inherit::foreach_incident_vertex(new_volume, [this] (Cell v) + if (this->template is_orbit_embedded()) + Inherit::foreach_incident_vertex(new_volume, [this] (Cell v) { this->new_orbit_embedding(v); }); - if (this->template is_orbit_embedded()) - Inherit::foreach_incident_edge(new_volume, [this] (Cell e) + if (this->template is_orbit_embedded()) + Inherit::foreach_incident_edge(new_volume, [this] (Cell e) { this->new_orbit_embedding(e); }); - if (this->template is_orbit_embedded()) // cmap2 faces + if (this->template is_orbit_embedded()) // cmap2 faces { - Inherit::foreach_incident_face(new_volume, [this] (Cell f) + Inherit::foreach_incident_face(new_volume, [this] (Cell f) { this->new_orbit_embedding(f); }); @@ -401,7 +401,7 @@ class CMap3_T : public CMap2_T inline unsigned int degree(Face f) const { - return Inherit::degree(typename Inherit::Face(f.dart)); + return Inherit::degree(typename Inherit::Face2(f.dart)); } protected: @@ -621,7 +621,7 @@ class CMap3_T : public CMap2_T { if (!marker.is_marked(d)) { - marker.mark_orbit(d); + marker.mark_orbit(d); f(d); } }); @@ -653,14 +653,14 @@ class CMap3_T : public CMap2_T inline void foreach_incident_vertex(Face f, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); - foreach_dart_of_orbit(f.dart, func); + foreach_dart_of_orbit(f.dart, func); } template inline void foreach_incident_edge(Face f, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); - foreach_dart_of_orbit(f.dart, func); + foreach_dart_of_orbit(f.dart, func); } template diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 6c618cde..1c4e97f6 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -350,18 +350,24 @@ class MapBase : public MapBaseData } template - inline unsigned int new_embedding(Dart d) + inline bool is_embedded(Cell /* c */) + { + return this->template is_orbit_embedded(); + } + + template + inline unsigned int new_embedding(Cell c) { unsigned int emb = add_attribute_element(); - this->template set_embedding(d, emb); + this->template set_embedding(c.dart, emb); return emb; } template - inline unsigned int copy_embedding(Dart d, Dart e) + inline unsigned int copy_embedding(Cell c, Cell d) { - unsigned int emb = this->template get_embedding(e); - this->template set_embedding(d, emb); + unsigned int emb = this->template get_embedding(d.dart); + this->template set_embedding(c.dart, emb); return emb; } diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index a3d8aa69..e5eb3ea2 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -259,20 +259,20 @@ class MapBaseData : public MapGen protected: template - inline void set_embedding(Dart d, unsigned int emb) + inline void set_embedding(Cell c, unsigned int emb) { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); cgogn_message_assert(is_orbit_embedded(), "Invalid parameter: orbit not embedded"); cgogn_message_assert(emb != EMBNULL,"cannot set an embedding to EMBNULL."); - const unsigned int old = (*embeddings_[ORBIT])[d.index]; + const unsigned int old = (*embeddings_[ORBIT])[c.dart.index]; // ref_line() is done before unref_line() to avoid deleting the indexed line if old == emb this->attributes_[ORBIT].ref_line(emb); // ref the new emb if (old != EMBNULL) this->attributes_[ORBIT].unref_line(old); // unref the old emb - (*this->embeddings_[ORBIT])[d.index] = emb; // affect the embedding to the dart + (*this->embeddings_[ORBIT])[c.dart.index] = emb; // affect the embedding to the dart } /******************************************************************************* diff --git a/cgogn/core/examples/map/map.cpp b/cgogn/core/examples/map/map.cpp index e8c143ea..f57f93ce 100644 --- a/cgogn/core/examples/map/map.cpp +++ b/cgogn/core/examples/map/map.cpp @@ -57,12 +57,12 @@ template int test1(MAP& map) { // add an attribute on vertex of map with - typename MAP::template VertexAttributeHandler ah = map.template add_attribute("floats"); + typename MAP::template VertexAttributeHandler ah = map.template add_attribute("floats"); - typename MAP::template FaceAttributeHandler ahf = map.template add_attribute("floats"); + typename MAP::template FaceAttributeHandler ahf = map.template add_attribute("floats"); // get attribute and change type (dangerous!) - typename MAP::template VertexAttributeHandler ahf2 = map.template get_attribute_force_type("floats"); + typename MAP::template VertexAttributeHandler ahf2 = map.template get_attribute_force_type("floats"); map.remove_attribute(ahf); std::cout << "ahf valid : " << std::boolalpha << ahf.is_valid() << std::endl; @@ -88,7 +88,7 @@ int test1(MAP& map) // cgogn::get_dart_buffers()->release_cell_buffer(vert_b); DartMarker dm(map); - CellMarker cm(map); + CellMarker cm(map); dm.mark(d1); @@ -100,7 +100,7 @@ int test1(MAP& map) std::cout << "End Darts" << std::endl; std::cout << "Vertices :" << std::endl; - map.template foreach_cell([&] (typename MAP::Vertex v) + map.template foreach_cell([&] (typename MAP::Vertex2 v) { std::cout << v << std::endl; ah[v] = 2.0f; @@ -113,7 +113,7 @@ int test1(MAP& map) // }); // get ChunkArrayContainer -> get ChunkArray -> fill -// typename MAP::template ChunkArrayContainer& container = map.get_attribute_container(MAP::VERTEX); +// typename MAP::template ChunkArrayContainer& container = map.get_attribute_container(MAP::Vertex); // typename MAP::template ChunkArray* att = container.template get_attribute("floats"); // for (unsigned int i = 0; i < 10; ++i) // container.template insert_lines<1>(); diff --git a/cgogn/core/tests/cmap/cmap1_test.cpp b/cgogn/core/tests/cmap/cmap1_test.cpp index 3c5c2d13..ca02bf4d 100644 --- a/cgogn/core/tests/cmap/cmap1_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_test.cpp @@ -36,7 +36,7 @@ class CMap1Test: public ::testing::Test public: typedef CMap1 myCMap1; - typedef myCMap1::Face Face; + typedef myCMap1::Face1 Face; protected: myCMap1 cmap_; diff --git a/cgogn/core/tests/cmap/cmap1_topo_test.cpp b/cgogn/core/tests/cmap/cmap1_topo_test.cpp index 2ba68290..39b3f5fc 100644 --- a/cgogn/core/tests/cmap/cmap1_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_topo_test.cpp @@ -33,7 +33,7 @@ namespace cgogn class CMap1TopoTest: public CMap1, public ::testing::Test { public: - typedef CMap1TopoTest::Face Face; + typedef CMap1TopoTest::Face1 Face; protected: @@ -58,25 +58,25 @@ TEST_F(CMap1TopoTest, testFaceDegree) EXPECT_EQ(10, this->degree(Face(d))); } -TEST_F(CMap1TopoTest, testCutEdge) +TEST_F(CMap1TopoTest, testSplitVertex) { Dart d = this->add_face_topo(10); Dart d1 = this->phi1(d); - Dart e = this->cut_edge_topo(d); + Dart e = this->split_vertex_topo(d); EXPECT_EQ(d1.index, this->phi1(e).index); EXPECT_EQ(d.index, this->phi_1(e).index); EXPECT_EQ(11, this->degree(Face(d))); } -TEST_F(CMap1TopoTest, testCollapseEdge) +TEST_F(CMap1TopoTest, testRemoveVertex) { Dart d = this->add_face_topo(10); Dart d_1 = this->phi_1(d); Dart d1 = this->phi1(d); - this->collapse_edge_topo(d); + this->remove_vertex(d); EXPECT_EQ(d1.index, this->phi1(d_1).index); EXPECT_EQ(9, this->degree(Face(d_1))); diff --git a/cgogn/geometry/algos/normal.h b/cgogn/geometry/algos/normal.h index c7e6445d..37838624 100644 --- a/cgogn/geometry/algos/normal.h +++ b/cgogn/geometry/algos/normal.h @@ -83,7 +83,7 @@ inline VEC3 vertex_normal(const MAP& map, Cell v, const typename M VEC3 n{0,0,0}; const VEC3& p = position[v.dart]; // map.foreach_incident_face(v, [&] (Cell f) - map.template foreach_incident_cell(v, [&] (Cell f) + map.template foreach_incident_cell(v, [&] (Cell f) { VEC3 facen = face_normal(map, f, position); const VEC3& p1 = position[map.phi1(f.dart)]; @@ -105,7 +105,7 @@ inline VEC3 vertex_normal(const MAP& map, Cell v, const typename M VEC3 n{0,0,0}; const VEC3& p = position[v.dart]; // map.foreach_incident_face(v, [&] (Cell f) - map.template foreach_incident_cell(v, [&] (Cell f) + map.template foreach_incident_cell(v, [&] (Cell f) { VEC3 facen = fnormal[f]; const VEC3& p1 = position[map.phi1(f.dart)]; diff --git a/cgogn/io/examples/cmap2_import.cpp b/cgogn/io/examples/cmap2_import.cpp index 749c43a2..31268389 100644 --- a/cgogn/io/examples/cmap2_import.cpp +++ b/cgogn/io/examples/cmap2_import.cpp @@ -60,22 +60,22 @@ int main(int argc, char** argv) std::cout << "nb darts // -> " << nb_darts_2 << std::endl; - VertexAttributeHandler vertex_position = map.get_attribute("position"); - VertexAttributeHandler vertex_normal = map.add_attribute("normal"); + VertexAttributeHandler vertex_position = map.get_attribute("position"); + VertexAttributeHandler vertex_normal = map.add_attribute("normal"); FaceAttributeHandler face_normal = map.add_attribute("normal"); map.enable_topo_cache(); - map.enable_topo_cache(); + map.enable_topo_cache(); map.enable_topo_cache(); - std::cout << "Vertex orbits are well embedded ? -> " << std::boolalpha << cgogn::is_well_embedded(map) << std::endl; + std::cout << "Vertex orbits are well embedded ? -> " << std::boolalpha << cgogn::is_well_embedded(map) << std::endl; std::cout << "Face orbits are well embedded ? -> " << std::boolalpha << cgogn::is_well_embedded(map) << std::endl; - std::cout << "Vertex orbit is uniquely embedded ? -> " << std::boolalpha << cgogn::is_orbit_embedding_unique(map) << std::endl; + std::cout << "Vertex orbit is uniquely embedded ? -> " << std::boolalpha << cgogn::is_orbit_embedding_unique(map) << std::endl; std::cout << "Face orbit is uniquely embedded ? -> " << std::boolalpha << cgogn::is_orbit_embedding_unique(map) << std::endl; - std::cout << "Vertex container is well referenced ? -> " << std::boolalpha << cgogn::is_container_well_referenced(map) << std::endl; + std::cout << "Vertex container is well referenced ? -> " << std::boolalpha << cgogn::is_container_well_referenced(map) << std::endl; std::cout << "Face container is well referenced ? -> " << std::boolalpha << cgogn::is_container_well_referenced(map) << std::endl; diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index f201161f..5fd9c556 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -153,7 +153,7 @@ class SurfaceImport void create_map(Map& map) { using MapBuilder = cgogn::CMap2Builder_T; - const Orbit VERTEX = Map::VERTEX; + const Orbit VERTEX = Map::Vertex2::SELF_ORBIT; if (this->nb_vertices_ == 0u) return; diff --git a/cgogn/multiresolution/cph/ihcmap2.h b/cgogn/multiresolution/cph/ihcmap2.h index a3e1aac8..62760f40 100644 --- a/cgogn/multiresolution/cph/ihcmap2.h +++ b/cgogn/multiresolution/cph/ihcmap2.h @@ -69,16 +69,18 @@ class IHCMap2_T : public CMap2_T, public CPH2 template friend class DartMarker_T; template friend class DartMarkerStore; - static const Orbit DART = Inherit_CMAP::DART; - static const Orbit VERTEX = Inherit_CMAP::VERTEX; - static const Orbit EDGE = Inherit_CMAP::EDGE; - static const Orbit FACE = Inherit_CMAP::FACE; - static const Orbit VOLUME = Inherit_CMAP::VOLUME; +// static const Orbit DART = Inherit_CMAP::DART; +// static const Orbit VERTEX = Inherit_CMAP::VERTEX; +// static const Orbit EDGE = Inherit_CMAP::EDGE; +// static const Orbit FACE = Inherit_CMAP::FACE; +// static const Orbit VOLUME = Inherit_CMAP::VOLUME; + + typedef Cell Vertex0; + typedef Cell Vertex2; + typedef Cell Edge2; + typedef Cell Face2; + typedef Cell Volume2; - typedef Cell Vertex; - typedef Cell Edge; - typedef Cell Face; - typedef Cell Volume; template using ChunkArray = typename Inherit_CMAP::template ChunkArray; @@ -88,15 +90,15 @@ class IHCMap2_T : public CMap2_T, public CPH2 template using AttributeHandler = typename Inherit_CMAP::template AttributeHandler; template - using DartAttributeHandler = AttributeHandler; + using DartAttributeHandler = AttributeHandler; template - using VertexAttributeHandler = AttributeHandler; + using VertexAttributeHandler = AttributeHandler; template - using EdgeAttributeHandler = AttributeHandler; + using EdgeAttributeHandler = AttributeHandler; template - using FaceAttributeHandler = AttributeHandler; + using FaceAttributeHandler = AttributeHandler; template - using VolumeAttributeHandler = AttributeHandler; + using VolumeAttributeHandler = AttributeHandler; using DartMarker = typename cgogn::DartMarker; using DartMarkerStore = typename cgogn::DartMarkerStore; @@ -245,29 +247,29 @@ class IHCMap2_T : public CMap2_T, public CPH2 * the inserted darts are automatically embedded on new attribute elements. * Actually a FACE attribute is created, if needed, for the new face. */ - Face add_face(unsigned int size) + Face2 add_face(unsigned int size) { - Face f = this->add_face_topo(size); + Face2 f = this->add_face_topo(size); - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) foreach_dart_of_orbit(f, [this] (Dart d) { - this->template new_embedding(d); + this->template new_embedding(d); }); - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) foreach_dart_of_orbit(f, [this] (Dart v) { - this->template new_embedding(v); + this->template new_embedding(v); }); - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) cgogn_assert_not_reached("Not implemented"); - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) cgogn_assert_not_reached("Not implemented"); - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) cgogn_assert_not_reached("Not implemented"); return f; diff --git a/cgogn/multiresolution/cph/ihcmap2_adaptive.h b/cgogn/multiresolution/cph/ihcmap2_adaptive.h index 944548ef..baefccb6 100644 --- a/cgogn/multiresolution/cph/ihcmap2_adaptive.h +++ b/cgogn/multiresolution/cph/ihcmap2_adaptive.h @@ -43,10 +43,10 @@ class IHCMap2Adaptive_T : public IHCMap2_T friend class MapBase; - using Vertex = typename Inherit::Vertex; - using Edge = typename Inherit::Edge; - using Face = typename Inherit::Face; - using Volume = typename Inherit::Volume; + using Vertex = typename Inherit::Vertex2; + using Edge = typename Inherit::Edge2; + using Face = typename Inherit::Face2; + using Volume = typename Inherit::Volume2; IHCMap2Adaptive_T() : Inherit() {} @@ -244,7 +244,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T Dart d2 = Inherit::phi2(d) ; unsigned int cur = Inherit::get_current_level(); Inherit::set_current_level(cur + 1); - if(this->degree(typename Inherit::Vertex(Inherit::phi1(d))) == 2) + if(this->degree(typename Inherit::Vertex2(Inherit::phi1(d))) == 2) { degree2 = true ; if(edge_is_subdivided(d) || edge_is_subdivided(d2)) diff --git a/cgogn/multiresolution/cph/ihcmap2_regular.h b/cgogn/multiresolution/cph/ihcmap2_regular.h index a59def13..245f0856 100644 --- a/cgogn/multiresolution/cph/ihcmap2_regular.h +++ b/cgogn/multiresolution/cph/ihcmap2_regular.h @@ -39,10 +39,10 @@ class IHCMap2Regular_T : public IHCMap2_T friend class MapBase; - using Vertex = typename Inherit::Vertex; - using Edge = typename Inherit::Edge; - using Face = typename Inherit::Face; - using Volume = typename Inherit::Volume; + using Vertex = typename Inherit::Vertex2; + using Edge = typename Inherit::Edge2; + using Face = typename Inherit::Face2; + using Volume = typename Inherit::Volume2; IHCMap2Regular_T() : Inherit() {} From 05e2f4fa88d551058147d3a35f2019c0a4efe44b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Mon, 22 Feb 2016 11:59:36 +0100 Subject: [PATCH 126/402] Remove ORBIT template parameter when possible. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- .../multithreading/bench_multithreading.cpp | 12 +- cgogn/core/basic/cell.h | 4 +- cgogn/core/cmap/map_base.h | 105 +++++++++++------- cgogn/core/cmap/sanity_check.h | 4 +- cgogn/core/examples/map/map.cpp | 2 +- cgogn/geometry/algos/normal.h | 6 +- cgogn/io/examples/cmap2_import.cpp | 4 +- cgogn/io/examples/cmap3_import.cpp | 8 +- cgogn/multiresolution/cph/ihcmap2_regular.h | 12 +- cgogn/multiresolution/examples/cph/cph2.cpp | 50 ++++----- cgogn/multiresolution/mra/lerp_triquad_mra.h | 4 +- cgogn/rendering/map_render.h | 6 +- 12 files changed, 121 insertions(+), 96 deletions(-) diff --git a/benchmarks/multithreading/bench_multithreading.cpp b/benchmarks/multithreading/bench_multithreading.cpp index 29649da3..3977f7e9 100644 --- a/benchmarks/multithreading/bench_multithreading.cpp +++ b/benchmarks/multithreading/bench_multithreading.cpp @@ -93,7 +93,7 @@ static void BENCH_faces_normals_single_threaded(benchmark::State& state) cgogn_assert(face_normal.is_valid()); state.ResumeTiming(); - map.template foreach_cell([&] (Face f) + map.template foreach_cell([&] (Face f) { face_normal[f] = cgogn::geometry::face_normal(map, f, vertex_position); }); @@ -112,7 +112,7 @@ static void BENCH_faces_normals_multi_threaded(benchmark::State& state) cgogn_assert(face_normal_mt.is_valid()); state.ResumeTiming(); - map.template parallel_foreach_cell([&] (Face f,unsigned int) + map.template parallel_foreach_cell([&] (Face f,unsigned int) { face_normal_mt[f] = cgogn::geometry::face_normal(map, f, vertex_position); }); @@ -121,7 +121,7 @@ static void BENCH_faces_normals_multi_threaded(benchmark::State& state) state.PauseTiming(); FaceAttributeHandler face_normal = map.get_attribute("normal"); - map.template foreach_cell([&] (Face f) + map.template foreach_cell([&] (Face f) { Vec3 error = face_normal[f] - face_normal_mt[f]; if (!cgogn::almost_equal_absolute(error.squaredNorm(), 0., 1e-9 )) @@ -151,7 +151,7 @@ static void BENCH_vertices_normals_single_threaded(benchmark::State& state) cgogn_assert(vartices_normal.is_valid()); state.ResumeTiming(); - map.template foreach_cell([&] (Vertex v) + map.template foreach_cell([&] (Vertex v) { vartices_normal[v] = cgogn::geometry::vertex_normal(map, v, vertex_position); }); @@ -170,7 +170,7 @@ static void BENCH_vertices_normals_multi_threaded(benchmark::State& state) cgogn_assert(vertices_normal_mt.is_valid()); state.ResumeTiming(); - map.template parallel_foreach_cell([&] (Vertex v, unsigned int) + map.template parallel_foreach_cell([&] (Vertex v, unsigned int) { vertices_normal_mt[v] = cgogn::geometry::vertex_normal(map, v, vertex_position); }); @@ -179,7 +179,7 @@ static void BENCH_vertices_normals_multi_threaded(benchmark::State& state) state.PauseTiming(); VertexAttributeHandler vertices_normal = map.get_attribute("normal"); - map.template foreach_cell([&] (Vertex v) + map.template foreach_cell([&] (Vertex v) { Vec3 error = vertices_normal[v] - vertices_normal_mt[v]; if (!cgogn::almost_equal_absolute(error.squaredNorm(), 0., 1e-9 )) diff --git a/cgogn/core/basic/cell.h b/cgogn/core/basic/cell.h index cce25ae7..43676b9f 100644 --- a/cgogn/core/basic/cell.h +++ b/cgogn/core/basic/cell.h @@ -79,11 +79,11 @@ inline std::string orbit_name(Orbit orbit) * Dart -> Cell (or const Cell&) ok * \tparam ORBIT The type of the orbit used to create the Cell */ -template +template class Cell { public: - + static const Orbit ORBIT = ORBIT_VAL; /** * \brief the dart representing this cell */ diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index afb224f7..236634d9 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -340,7 +340,7 @@ class MapBase : public MapBaseData }); // initialize the indices of the existing orbits - foreach_cell([this] (Cell c) + foreach_cell([this] (Cell c) { set_orbit_embedding(c, add_attribute_element()); }); @@ -370,7 +370,7 @@ class MapBase : public MapBaseData for (unsigned int& i : counter) i = 0; ConcreteMap* cmap = to_concrete(); - foreach_cell([cmap, &counter] (Cell c) + foreach_cell([cmap, &counter] (Cell c) { if (counter[c] > 0) cmap->set_orbit_embedding(c, cmap->template add_attribute_element()); @@ -434,7 +434,7 @@ class MapBase : public MapBaseData static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); cgogn_message_assert(is_topo_cache_enabled(), "Trying to update a disabled global topo cache"); - foreach_cell([this] (Cell c) + foreach_cell([this] (Cell c) { (*this->global_topo_cache_[ORBIT])[this->get_embedding(c)] = c.dart; }); @@ -680,104 +680,108 @@ class MapBase : public MapBaseData /** * \brief apply a function on each orbit of the map - * @tparam ORBIT orbit to traverse * @tparam FUNC type of the callable * @param f a callable */ - template + template inline void foreach_cell(const FUNC& f) const { - static_assert(check_func_parameter_type(FUNC, Cell), "Wrong function cell parameter type"); + using cell_type = typename function_traits::template arg<0>::type; +// static_assert(check_func_parameter_type(FUNC, Cell), "Wrong function cell parameter type"); switch (STRATEGY) { case FORCE_DART_MARKING : - foreach_cell_dart_marking(f); + foreach_cell_dart_marking(f); break; case FORCE_CELL_MARKING : - foreach_cell_cell_marking(f); + foreach_cell_cell_marking(f); break; case FORCE_TOPO_CACHE : - foreach_cell_topo_cache(f); + foreach_cell_topo_cache(f); break; case AUTO : - if (is_topo_cache_enabled()) - foreach_cell_topo_cache(f); - else if (this->template is_orbit_embedded()) - foreach_cell_cell_marking(f); + if (is_topo_cache_enabled()) + foreach_cell_topo_cache(f); + else if (this->template is_orbit_embedded()) + foreach_cell_cell_marking(f); else - foreach_cell_dart_marking(f); + foreach_cell_dart_marking(f); break; } } - template + template inline void parallel_foreach_cell(const FUNC& f) const { - static_assert(check_func_ith_parameter_type(FUNC, 0, Cell), "Wrong function first parameter type"); + using cell_type = typename function_traits::template arg<0>::type; + static const Orbit ORBIT = cell_type::ORBIT; static_assert(check_func_ith_parameter_type(FUNC, 1, unsigned int), "Wrong function second parameter type"); switch (STRATEGY) { case FORCE_DART_MARKING : - parallel_foreach_cell_dart_marking(f); + parallel_foreach_cell_dart_marking(f); break; case FORCE_CELL_MARKING : - parallel_foreach_cell_cell_marking(f); + parallel_foreach_cell_cell_marking(f); break; case FORCE_TOPO_CACHE : - parallel_foreach_cell_topo_cache(f); + parallel_foreach_cell_topo_cache(f); break; case AUTO : if (is_topo_cache_enabled()) - parallel_foreach_cell_topo_cache(f); + parallel_foreach_cell_topo_cache(f); else if (this->template is_orbit_embedded()) - parallel_foreach_cell_cell_marking(f); + parallel_foreach_cell_cell_marking(f); else - parallel_foreach_cell_dart_marking(f); + parallel_foreach_cell_dart_marking(f); break; } } /** * \brief apply a function on each orbit of the map and stops when the function returns false - * @tparam ORBIT orbit to traverse * @tparam FUNC type of the callable * @param f a callable */ - template + template void foreach_cell_until(const FUNC& f) const { - static_assert(check_func_parameter_type(FUNC, Cell), "Wrong function cell parameter type"); + using cell_type = typename function_traits::template arg<0>::type; + static const Orbit ORBIT = cell_type::ORBIT; static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); switch (STRATEGY) { case FORCE_DART_MARKING : - foreach_cell_until_dart_marking(f); + foreach_cell_until_dart_marking(f); break; case FORCE_CELL_MARKING : - foreach_cell_until_cell_marking(f); + foreach_cell_until_cell_marking(f); break; case FORCE_TOPO_CACHE : - foreach_cell_until_topo_cache(f); + foreach_cell_until_topo_cache(f); break; case AUTO : if (is_topo_cache_enabled()) - foreach_cell_until_topo_cache(f); + foreach_cell_until_topo_cache(f); else if (this->template is_orbit_embedded()) - foreach_cell_until_cell_marking(f); + foreach_cell_until_cell_marking(f); else - foreach_cell_until_dart_marking(f); + foreach_cell_until_dart_marking(f); break; } } protected: - template + template inline void foreach_cell_dart_marking(const FUNC& f) const { + using cell_type = typename function_traits::template arg<0>::type; + static const Orbit ORBIT = cell_type::ORBIT; + DartMarker dm(*to_concrete()); for (Dart d = Dart(this->topology_.begin()), end = Dart(this->topology_.end()); d != end; @@ -791,9 +795,11 @@ class MapBase : public MapBaseData } } - template + template inline void parallel_foreach_cell_dart_marking(const FUNC& f) const { + using cell_type = typename function_traits::template arg<0>::type; + static const Orbit ORBIT = cell_type::ORBIT; using VecCell = std::vector>; using Future = std::future< typename std::result_of, unsigned int)>::type >; @@ -858,9 +864,12 @@ class MapBase : public MapBaseData } } - template + template inline void foreach_cell_cell_marking(const FUNC& f) const { + using cell_type = typename function_traits::template arg<0>::type; + static const Orbit ORBIT = cell_type::ORBIT; + CellMarker cm(*to_concrete()); for (Dart d = Dart(this->topology_.begin()), end = Dart(this->topology_.end()); d != end; @@ -874,9 +883,11 @@ class MapBase : public MapBaseData } } - template + template inline void parallel_foreach_cell_cell_marking(const FUNC& f) const { + using cell_type = typename function_traits::template arg<0>::type; + static const Orbit ORBIT = cell_type::ORBIT; using VecCell = std::vector>; using Future = std::future< typename std::result_of, unsigned int)>::type >; @@ -941,9 +952,12 @@ class MapBase : public MapBaseData } } - template + template inline void foreach_cell_topo_cache(const FUNC& f) const { + using cell_type = typename function_traits::template arg<0>::type; + static const Orbit ORBIT = cell_type::ORBIT; + for (unsigned int i = this->attributes_[ORBIT].begin(), end = this->attributes_[ORBIT].end(); i != end; this->attributes_[ORBIT].next(i)) @@ -952,9 +966,11 @@ class MapBase : public MapBaseData } } - template + template inline void parallel_foreach_cell_topo_cache(const FUNC& f) const { + using cell_type = typename function_traits::template arg<0>::type; + static const Orbit ORBIT = cell_type::ORBIT; using VecCell = std::vector>; using Future = std::future< typename std::result_of, unsigned int)>::type >; @@ -1017,9 +1033,12 @@ class MapBase : public MapBaseData } } - template + template inline void foreach_cell_until_dart_marking(const FUNC& f) const { + using cell_type = typename function_traits::template arg<0>::type; + static const Orbit ORBIT = cell_type::ORBIT; + DartMarker dm(*to_concrete()); for (Dart d = Dart(this->topology_.begin()), end = Dart(this->topology_.end()); d != end; @@ -1034,9 +1053,12 @@ class MapBase : public MapBaseData } } - template + template inline void foreach_cell_until_cell_marking(const FUNC& f) const { + using cell_type = typename function_traits::template arg<0>::type; + static const Orbit ORBIT = cell_type::ORBIT; + CellMarker cm(*to_concrete()); for (Dart d = Dart(this->topology_.begin()), end = Dart(this->topology_.end()); d != end; @@ -1051,9 +1073,12 @@ class MapBase : public MapBaseData } } - template + template inline void foreach_cell_until_topo_cache(const FUNC& f) const { + using cell_type = typename function_traits::template arg<0>::type; + static const Orbit ORBIT = cell_type::ORBIT; + for (unsigned int i = this->attributes_[ORBIT].begin(), end = this->attributes_[ORBIT].end(); i != end; this->attributes_[ORBIT].next(i)) diff --git a/cgogn/core/cmap/sanity_check.h b/cgogn/core/cmap/sanity_check.h index cbb7f9b1..38052708 100644 --- a/cgogn/core/cmap/sanity_check.h +++ b/cgogn/core/cmap/sanity_check.h @@ -39,7 +39,7 @@ template bool is_well_embedded(const MAP& map) { bool result = true; - map.template foreach_cell([&] (Cell c) + map.foreach_cell([&] (Cell c) { result = map.template is_well_embedded(c); }); @@ -63,7 +63,7 @@ bool is_orbit_embedding_unique(MAP& map) for (unsigned int& i : counter) i = 0; bool result = true; - map.template foreach_cell([&] (Cell c) + map.template foreach_cell([&] (Cell c) { if (counter[c] > 0) { diff --git a/cgogn/core/examples/map/map.cpp b/cgogn/core/examples/map/map.cpp index a2dd0851..e45ca260 100644 --- a/cgogn/core/examples/map/map.cpp +++ b/cgogn/core/examples/map/map.cpp @@ -100,7 +100,7 @@ int test1(MAP& map) std::cout << "End Darts" << std::endl; std::cout << "Vertices :" << std::endl; - map.template foreach_cell([&] (typename MAP::Vertex v) + map.foreach_cell([&] (typename MAP::Vertex v) { std::cout << v << std::endl; ah[v] = 2.0f; diff --git a/cgogn/geometry/algos/normal.h b/cgogn/geometry/algos/normal.h index 2a94734c..6f4d82b7 100644 --- a/cgogn/geometry/algos/normal.h +++ b/cgogn/geometry/algos/normal.h @@ -120,7 +120,7 @@ inline VEC3 vertex_normal(const MAP& map, Cell v, const typename M template inline void compute_normal_faces(MAP& map, const typename MAP::template VertexAttributeHandler& position, typename MAP::template AttributeHandler& normal) { - map.template parallel_foreach_cell([&] (Cell f, unsigned int) + map.parallel_foreach_cell([&] (Cell f, unsigned int) { normal[f] = face_normal(map, f, position); }); @@ -129,7 +129,7 @@ inline void compute_normal_faces(MAP& map, const typename MAP::template VertexAt template inline void compute_normal_vertices(MAP& map, const typename MAP::template VertexAttributeHandler& position, typename MAP::template AttributeHandler& normal) { - map.template parallel_foreach_cell([&] (Cell v, unsigned int) + map.parallel_foreach_cell([&] (Cell v, unsigned int) { normal[v] = vertex_normal(map, v, position); }); @@ -138,7 +138,7 @@ inline void compute_normal_vertices(MAP& map, const typename MAP::template Verte template inline void compute_normal_vertices(MAP& map, const typename MAP::template VertexAttributeHandler& position, const typename MAP::template AttributeHandler& fnormal, typename MAP::template AttributeHandler& normal) { - map.template parallel_foreach_cell([&] (Cell v, unsigned int) + map.parallel_foreach_cell([&] (Cell v, unsigned int) { normal[v] = vertex_normal(map, v, position, fnormal); }); diff --git a/cgogn/io/examples/cmap2_import.cpp b/cgogn/io/examples/cmap2_import.cpp index 749c43a2..da176b73 100644 --- a/cgogn/io/examples/cmap2_import.cpp +++ b/cgogn/io/examples/cmap2_import.cpp @@ -80,14 +80,14 @@ int main(int argc, char** argv) unsigned int nb_faces = 0; - map.foreach_cell([&nb_faces] (Map2::Face) { nb_faces++; }); + map.foreach_cell([&nb_faces] (Map2::Face) { nb_faces++; }); std::cout << "nb faces -> " << nb_faces << std::endl; unsigned int nb_faces_2 = 0; std::vector nb_faces_per_thread(cgogn::NB_THREADS - 1); for (unsigned int& n : nb_faces_per_thread) n = 0; - map.parallel_foreach_cell([&nb_faces_per_thread] (Map2::Face, unsigned int thread_index) + map.parallel_foreach_cell([&nb_faces_per_thread] (Map2::Face, unsigned int thread_index) { nb_faces_per_thread[thread_index]++; }); diff --git a/cgogn/io/examples/cmap3_import.cpp b/cgogn/io/examples/cmap3_import.cpp index bc484ed7..9b3a7e4e 100644 --- a/cgogn/io/examples/cmap3_import.cpp +++ b/cgogn/io/examples/cmap3_import.cpp @@ -49,13 +49,13 @@ int main(int argc, char** argv) unsigned int nbw = 0u; - map.foreach_cell([&nbw] (Map3::Volume) + map.foreach_cell([&nbw] (Map3::Volume) { ++nbw; }); unsigned int nbf = 0u; - map.foreach_cell([&] (Map3::Face f) + map.foreach_cell([&] (Map3::Face f) { ++nbf; Vec3 v1 = vertex_position[map.phi1(f.dart)] - vertex_position[f.dart]; @@ -63,7 +63,7 @@ int main(int argc, char** argv) }); unsigned int nbv = 0; - map.foreach_cell([&] (Map3::Vertex v) + map.foreach_cell([&] (Map3::Vertex v) { ++nbv; unsigned int nb_incident = 0; @@ -74,7 +74,7 @@ int main(int argc, char** argv) }); unsigned int nbe = 0; - map.foreach_cell([&nbe] (Map3::Edge) + map.foreach_cell([&nbe] (Map3::Edge) { ++nbe; }); diff --git a/cgogn/multiresolution/cph/ihcmap2_regular.h b/cgogn/multiresolution/cph/ihcmap2_regular.h index 71743e23..596ed8bb 100644 --- a/cgogn/multiresolution/cph/ihcmap2_regular.h +++ b/cgogn/multiresolution/cph/ihcmap2_regular.h @@ -61,7 +61,7 @@ class IHCMap2Regular_T : public IHCMap2_T Inherit::set_current_level(Inherit::get_maximum_level() + 1) ; //cut edges - Inherit::template foreach_cell([&] (typename Inherit::Edge e) + Inherit::template foreach_cell([&] (typename Inherit::Edge e) { Dart dd = Inherit::phi2(e); // Inherit::cut_edge(e); @@ -72,7 +72,7 @@ class IHCMap2Regular_T : public IHCMap2_T }); //cut faces - Inherit::template foreach_cell([&] (typename Inherit::Face d) + Inherit::template foreach_cell([&] (typename Inherit::Face d) { Dart old = d ; @@ -113,7 +113,7 @@ class IHCMap2Regular_T : public IHCMap2_T Inherit::set_current_level(Inherit::get_maximum_level() + 1) ; //cut edges - Inherit::template foreach_cell([&] (typename Inherit::Edge e) + Inherit::template foreach_cell([&] (typename Inherit::Edge e) { Dart dd = Inherit::phi2(e); // Inherit::cut_edge(e); @@ -124,7 +124,7 @@ class IHCMap2Regular_T : public IHCMap2_T }); //cut faces - Inherit::template foreach_cell([&] (typename Inherit::Face d) + Inherit::template foreach_cell([&] (typename Inherit::Face d) { Dart old = d ; @@ -172,7 +172,7 @@ class IHCMap2Regular_T : public IHCMap2_T Inherit::set_current_level(Inherit::get_maximum_level() + 1) ; //cut edges - Inherit::template foreach_cell([&] (typename Inherit::Edge e) + Inherit::template foreach_cell([&] (typename Inherit::Edge e) { Dart dd = Inherit::phi2(e); // Inherit::cut_edge(e); @@ -183,7 +183,7 @@ class IHCMap2Regular_T : public IHCMap2_T }); //cut faces - Inherit::template foreach_cell([&] (typename Inherit::Face d) + Inherit::template foreach_cell([&] (typename Inherit::Face d) { Dart old = d ; diff --git a/cgogn/multiresolution/examples/cph/cph2.cpp b/cgogn/multiresolution/examples/cph/cph2.cpp index b1808b2e..15140ff6 100644 --- a/cgogn/multiresolution/examples/cph/cph2.cpp +++ b/cgogn/multiresolution/examples/cph/cph2.cpp @@ -18,46 +18,46 @@ using VertexAttributeHandler = IHMap2::VertexAttributeHandler; int main() { - IHMap2 map; - VertexAttributeHandler position = map.get_attribute("position"); + IHMap2 map; + VertexAttributeHandler position = map.get_attribute("position"); - LerpTriQuadMRAnalysis lerp(map, position); + LerpTriQuadMRAnalysis lerp(map, position); map.add_face(4); std::cout << "before add level Faces :" << std::endl; - map.template foreach_cell([&] (IHMap2::Face v) + map.foreach_cell([&] (IHMap2::Face v) { std::cout << v << std::endl; }); std::cout << "End Faces" << std::endl; - { - lerp.add_level(); - lerp.synthesis(); + { + lerp.add_level(); + lerp.synthesis(); - std::cout << "after add level Faces :" << std::endl; - map.template foreach_cell([&] (IHMap2::Face f) - { - std::cout << f << " | " << map.get_dart_level(f.dart) << std::endl; - }); - std::cout << "End Faces" << std::endl; + std::cout << "after add level Faces :" << std::endl; + map.foreach_cell([&] (IHMap2::Face f) + { + std::cout << f << " | " << map.get_dart_level(f.dart) << std::endl; + }); + std::cout << "End Faces" << std::endl; - unsigned int cur = map.get_current_level(); + unsigned int cur = map.get_current_level(); - std::cout << "current level = " << cur << std::endl; - map.set_current_level(cur - 1); + std::cout << "current level = " << cur << std::endl; + map.set_current_level(cur - 1); - std::cout << "after add level Faces :" << std::endl; - map.template foreach_cell([&] (IHMap2::Face f) - { - std::cout << f << " | " << map.get_dart_level(f.dart) << std::endl; - }); - std::cout << "End Vertices" << std::endl; - } + std::cout << "after add level Faces :" << std::endl; + map.foreach_cell([&] (IHMap2::Face f) + { + std::cout << f << " | " << map.get_dart_level(f.dart) << std::endl; + }); + std::cout << "End Vertices" << std::endl; + } - /* + /* { map.add_mixed_level(); @@ -106,7 +106,7 @@ int main() }); std::cout << "End Vertices" << std::endl; } - */ + */ return 0; } diff --git a/cgogn/multiresolution/mra/lerp_triquad_mra.h b/cgogn/multiresolution/mra/lerp_triquad_mra.h index e4a40f98..ec70e78f 100644 --- a/cgogn/multiresolution/mra/lerp_triquad_mra.h +++ b/cgogn/multiresolution/mra/lerp_triquad_mra.h @@ -62,7 +62,7 @@ class LerpTriQuadMRAnalysis : public MRAnalysis std::function lerp_tri_quad_odd_synthesis_ = [this] () { - this->map_.template foreach_cell([&] (typename MRMAP::Face f) + this->map_.foreach_cell([&] (typename MRMAP::Face f) { if(this->map_.degree(f) != 3) { @@ -92,7 +92,7 @@ class LerpTriQuadMRAnalysis : public MRAnalysis } }); - this->map_.template foreach_cell([&] (typename MRMAP::Edge e) + this->map_.foreach_cell([&] (typename MRMAP::Edge e) { VEC3 ve = (va_[e.dart] + va_[this->map_.phi1(e)]) * 0.5; diff --git a/cgogn/rendering/map_render.h b/cgogn/rendering/map_render.h index 3cdb6bdf..3b3a62da 100644 --- a/cgogn/rendering/map_render.h +++ b/cgogn/rendering/map_render.h @@ -75,7 +75,7 @@ class MapRender void init_points(MAP& m, std::vector& table_indices) { // table_indices.reserve(m.get_nb_darts()/6); - m.template foreach_cell([&] (typename MAP::Vertex v) + m.foreach_cell([&] (typename MAP::Vertex v) { table_indices.push_back(m.get_embedding(v)); }); @@ -85,7 +85,7 @@ class MapRender void init_lines(MAP& m, std::vector& table_indices) { // table_indices.reserve(m.get_nb_darts()/2); - m.template foreach_cell([&] (typename MAP::Edge e) + m.foreach_cell([&] (typename MAP::Edge e) { table_indices.push_back(m.template get_embedding(e.dart)); table_indices.push_back(m.template get_embedding(m.phi1(e.dart))); @@ -97,7 +97,7 @@ class MapRender { // reserve more ? // table_indices.reserve(m.get_nb_darts()/3); - m.template foreach_cell([&] (typename MAP::Face f) + m.foreach_cell([&] (typename MAP::Face f) { Dart d = f; Dart d1 = m.phi1(d); From 76ebd2000401e8324f729699fa96f593e0daca84 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Mon, 22 Feb 2016 12:08:14 +0100 Subject: [PATCH 127/402] Back to Cell with no dimension --- .../multithreading/bench_multithreading.cpp | 8 +- cgogn/core/cmap/cmap0.h | 15 +- cgogn/core/cmap/cmap1.h | 36 ++-- cgogn/core/cmap/cmap2.h | 169 +++++++++--------- cgogn/core/cmap/cmap3.h | 2 +- cgogn/core/cmap/map_base.h | 6 - cgogn/core/examples/map/map.cpp | 4 +- cgogn/core/tests/cmap/cmap1_test.cpp | 11 +- cgogn/core/tests/cmap/cmap1_topo_test.cpp | 2 +- cgogn/io/examples/cmap2_import.cpp | 24 +-- cgogn/io/surface_import.h | 2 +- 11 files changed, 133 insertions(+), 146 deletions(-) diff --git a/benchmarks/multithreading/bench_multithreading.cpp b/benchmarks/multithreading/bench_multithreading.cpp index ecaeee92..ae160ded 100644 --- a/benchmarks/multithreading/bench_multithreading.cpp +++ b/benchmarks/multithreading/bench_multithreading.cpp @@ -36,11 +36,11 @@ using Map2 = cgogn::CMap2; Map2 map; -const cgogn::Orbit VERTEX = Map2::Vertex2::SELF_ORBIT; -using Vertex = cgogn::Cell; +using Vertex = Map2::Vertex; +const cgogn::Orbit VERTEX = Vertex::SELF_ORBIT; -const cgogn::Orbit FACE = Map2::Face2::SELF_ORBIT; -using Face = cgogn::Cell; +using Face = Map2::Face; +const cgogn::Orbit FACE = Face::SELF_ORBIT; const unsigned int ITERATIONS = 1u; diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index e9ac6452..cc18764b 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -47,9 +47,7 @@ class CMap0_T : public MapBase // static const Orbit VERTEX = Orbit::DART; - typedef Cell Vertex0; - - typedef Vertex0 Vertex; + typedef Cell Vertex; template using ChunkArray = typename Inherit::template ChunkArray; @@ -104,13 +102,14 @@ class CMap0_T : public MapBase * \return The added dart. If the map has DART attributes, * the inserted darts are automatically embedded on new attribute elements. */ - inline Vertex0 add_vertex() + inline Vertex add_vertex() { CGOGN_CHECK_CONCRETE_TYPE; - Vertex0 v(this->add_dart()); + Vertex v = this->add_dart(); - if (this->is_embedded(v)) this->new_embedding(v); + if (this->template is_orbit_embedded()) + this->new_embedding(v); return v; } @@ -118,11 +117,11 @@ class CMap0_T : public MapBase /*! * \brief Remove a vertex (or dart) from the map. */ - inline void remove_vertex(Vertex0 d) + inline void remove_vertex(Vertex v) { CGOGN_CHECK_CONCRETE_TYPE; - this->remove_dart(d.dart); + this->remove_dart(v.dart); } /******************************************************************************* diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 110a60d5..41033cdf 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -48,11 +48,8 @@ class CMap1_T : public CMap0_T // static const Orbit DART = Orbit::DART; // static const Orbit FACE = Orbit::PHI1; - typedef Cell Vertex1; - typedef Cell Face1; - - typedef Vertex1 Vertex; - typedef Face1 Face; + typedef Cell Vertex; + typedef Cell Face; template using ChunkArray = typename Inherit::template ChunkArray; @@ -210,15 +207,16 @@ class CMap1_T : public CMap0_T * If the map has DART or FACE attributes, the inserted darts * are automatically embedded on new attribute elements. */ - inline Vertex1 split_vertex(Vertex1 v) + inline Vertex split_vertex(Vertex v) { CGOGN_CHECK_CONCRETE_TYPE; - Vertex1 nv = split_vertex_topo(v); + Vertex nv = split_vertex_topo(v); - if (this->is_embedded(nv)) this->new_embedding(nv); + if (this->template is_orbit_embedded()) this->new_embedding(nv); - if (this->is_embedded(Face1(nv))) this->copy_embedding(Face1(nv), Face1(v)); + if (this->template is_orbit_embedded()) + this->copy_embedding(Face(nv.dart), Face(v.dart)); return nv; } @@ -228,7 +226,7 @@ class CMap1_T : public CMap0_T * @param v : a vertex * The vertex that preceeds v in the face is linked its successor. */ - inline void remove_vertex(Vertex1 v) + inline void remove_vertex(Vertex v) { CGOGN_CHECK_CONCRETE_TYPE; @@ -263,19 +261,19 @@ class CMap1_T : public CMap0_T * \return A dart of the built face. If the map has DART or FACE attributes, * the inserted darts are automatically embedded on new attribute elements. */ - Face1 add_face(unsigned int size) + Face add_face(unsigned int size) { CGOGN_CHECK_CONCRETE_TYPE; - Face1 f = add_face_topo(size); + Face f = add_face_topo(size); - if (this->is_embedded(Vertex1(f))) - foreach_dart_of_PHI1(f.dart, [this] (Vertex1 v) + if (this->template is_orbit_embedded()) + foreach_dart_of_PHI1(f.dart, [this] (Vertex v) { this->new_embedding(v); }); - if (this->is_embedded(f)) this->new_orbit_embedding(f); + if (this->template is_orbit_embedded()) this->new_orbit_embedding(f); return f; } @@ -284,7 +282,7 @@ class CMap1_T : public CMap0_T * \brief Remove a face from the map. * \param d : a dart of the face to remove */ - inline void remove_face(Face1 f) + inline void remove_face(Face f) { Dart d = f.dart; Dart e = phi1(d); @@ -321,7 +319,7 @@ class CMap1_T : public CMap0_T public: - inline unsigned int degree(Face1 f) const + inline unsigned int degree(Face f) const { return this->nb_darts(f); } @@ -405,9 +403,9 @@ class CMap1_T : public CMap0_T *******************************************************************************/ template - inline void foreach_incident_vertex(Face1 f, const FUNC& func) const + inline void foreach_incident_vertex(Face f, const FUNC& func) const { - static_assert(check_func_parameter_type(FUNC, Vertex1), + static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); foreach_dart_of_orbit(f, func); } diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index a7bc6b4b..6209509c 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -57,16 +57,11 @@ class CMap2_T : public CMap1_T static const Orbit FACE = Orbit::PHI1; // static const Orbit VOLUME = Orbit::PHI1_PHI2; - typedef Cell Vertex0; - typedef Cell Vertex2; - typedef Cell Edge2; - typedef Cell Face2; - typedef Cell Volume2; - - typedef Vertex2 Vertex; - typedef Edge2 Edge; - typedef Face2 Face; - typedef Volume2 Volume; + typedef Cell CDart; + typedef Cell Vertex; + typedef Cell Edge; + typedef Cell Face; + typedef Cell Volume; template using ChunkArray = typename Inherit::template ChunkArray; @@ -208,47 +203,47 @@ class CMap2_T : public CMap1_T * \return A dart of the inserted vertex * The edge of d is cut by inserting a new vertex. * The returned dart is the dart of the inserted vertex that belongs to the face of d. - * If the map has Dart, Vertex2, Edge2, Face2 or Volume2 attributes, + * If the map has Dart, Vertex, Edge, Face or Volume attributes, * the inserted darts are automatically embedded on new attribute elements. - * Actually a Vertex2 attribute is created, if needed, for the inserted vertex. + * Actually a Vertex attribute is created, if needed, for the inserted vertex. */ - inline Vertex2 cut_edge(Edge2 e) + inline Vertex cut_edge(Edge e) { CGOGN_CHECK_CONCRETE_TYPE; - const Dart ne = cut_edge_topo(e); - const Dart nf = this->phi1(phi2(e)); + const CDart ne = cut_edge_topo(e); + const CDart nf = this->phi1(phi2(e)); - if (this->is_embedded(Vertex0(ne))) { - this->new_embedding(Vertex0(ne)); - this->new_embedding(Vertex0(nf)); + if (this->template is_orbit_embedded()) { + this->new_embedding(ne); + this->new_embedding(nf); } if (this->template is_orbit_embedded()) { - const unsigned int idx = this->new_embedding(Vertex2(ne)); - this->set_embedding(Vertex2(nf), idx); + const unsigned int idx = this->new_embedding(Vertex(ne)); + this->set_embedding(Vertex(nf), idx); } if (this->template is_orbit_embedded()) { - this->copy_embedding(Edge2(nf), e); - this->new_orbit_embedding(Edge2(ne)); + this->copy_embedding(Edge(nf), e); + this->new_orbit_embedding(Edge(ne)); } if (this->template is_orbit_embedded()) { - this->copy_embedding(Face2(ne), Face2(e.dart)); - this->copy_embedding(Face2(nf), Face2(this->phi_1(nf))); + this->copy_embedding(Face(ne), Face(e.dart)); + this->copy_embedding(Face(nf), Face(this->phi_1(nf))); } if (this->template is_orbit_embedded()) { - const unsigned int idx = this->new_embedding(Volume2(ne)); - this->set_embedding(Volume2(nf), idx); + const unsigned int idx = this->new_embedding(Volume(ne)); + this->set_embedding(Volume(nf), idx); } - return Vertex2(ne); + return Vertex(ne); } protected: @@ -294,46 +289,46 @@ class CMap2_T : public CMap1_T * \param e : second vertex * The vertices d and e should belong to the same face and be distinct from each other. * An edge made of two new darts is inserted between the two given vertices. - * If the map has Dart, Vertex2, Edge2, Face2 or Volume2 attributes, + * If the map has Dart, Vertex, Edge, Face or Volume attributes, * the inserted darts are automatically embedded on new attribute elements. - * Actually an Edge2 attribute is created, if needed, for the inserted edge - * and a new Face2 attribute is created for the subdived face that e belongs to. - * The Face2 attribute of the subdived face that d belongs to is kept unchanged. + * Actually an Edge attribute is created, if needed, for the inserted edge + * and a new Face attribute is created for the subdived face that e belongs to. + * The Face attribute of the subdived face that d belongs to is kept unchanged. */ - inline void cut_face(Vertex2 d, Vertex2 e) + inline void cut_face(Vertex d, Vertex e) { CGOGN_CHECK_CONCRETE_TYPE; cut_face_topo(d,e); - Dart nd = this->phi_1(d); - Dart ne = this->phi_1(e); + CDart nd = this->phi_1(d); + CDart ne = this->phi_1(e); - if (this->is_embedded(Vertex0(nd))) { - this->new_embedding(Vertex0(nd)); - this->new_embedding(Vertex0(ne)); + if (this->template is_orbit_embedded()) { + this->new_embedding(nd); + this->new_embedding(ne); } - if (this->is_embedded(Vertex2(nd))) + if (this->template is_orbit_embedded()) { - this->copy_embedding(Vertex2(nd), e); - this->copy_embedding(Vertex2(ne), d); + this->copy_embedding(Vertex(nd.dart), e); + this->copy_embedding(Vertex(ne.dart), d); } - if (this->is_embedded(Edge2(nd))) + if (this->template is_orbit_embedded()) { - this->new_orbit_embedding(Edge2(nd)); + this->new_orbit_embedding(Edge(nd.dart)); } - if (this->is_embedded(Face2(nd))) + if (this->template is_orbit_embedded()) { - this->copy_embedding(Face2(nd), Face2(d.dart)); - this->new_orbit_embedding(Face2(ne)); + this->copy_embedding(Face(nd.dart), Face(d.dart)); + this->new_orbit_embedding(Face(ne.dart)); } - if (this->is_embedded(Volume2(nd))) + if (this->template is_orbit_embedded()) { - unsigned int idx = this->copy_embedding(Volume2(nd), Volume2(d.dart)); - this->set_embedding(Volume2(ne), idx); + unsigned int idx = this->copy_embedding(Volume(nd.dart), Volume(d.dart)); + this->set_embedding(Volume(ne), idx); } } @@ -366,39 +361,39 @@ class CMap2_T : public CMap1_T * \brief Add a face in the map. * \param size : the number of edges in the built face * \return A dart of the built face - * If the map has Dart, Vertex2, Edge2, Face2 or Volume2 attributes, + * If the map has Dart, Vertex, Edge, Face or Volume attributes, * the inserted darts are automatically embedded on new attribute elements. - * Actually a Face2 attribute is created, if needed, for the new face. + * Actually a Face attribute is created, if needed, for the new face. */ - Face2 add_face(unsigned int size) + Face add_face(unsigned int size) { CGOGN_CHECK_CONCRETE_TYPE; - Face2 f = add_face_topo(size); + Face f = add_face_topo(size); - if (this->is_embedded(Vertex0(f.dart))) - foreach_dart_of_orbit(f, [this] (Dart d) + if (this->template is_orbit_embedded()) + foreach_dart_of_orbit(f, [this] (CDart d) { - this->new_embedding(Vertex0(d)); + this->new_embedding(d); }); - if (this->template is_orbit_embedded()) - foreach_dart_of_orbit(f, [this] (Dart v) + if (this->template is_orbit_embedded()) + foreach_dart_of_orbit(f, [this] (Vertex v) { - this->template new_embedding(v); + this->new_embedding(v); }); - if (this->template is_orbit_embedded()) - foreach_dart_of_orbit(f, [this] (Dart e) + if (this->template is_orbit_embedded()) + foreach_dart_of_orbit(f, [this] (Edge e) { - this->template new_embedding(e); + this->new_embedding(e); }); - if (this->template is_orbit_embedded()) - this->template new_embedding(f.dart); + if (this->template is_orbit_embedded()) + this->new_embedding(f); - if (this->template is_orbit_embedded()) - this->template new_orbit_embedding(f.dart); + if (this->template is_orbit_embedded()) + this->new_orbit_embedding(Volume(f.dart)); return f; } @@ -445,7 +440,7 @@ class CMap2_T : public CMap1_T if (phi2(d) == d) { close_hole_topo(d); - const Face2 new_face = phi2(d); + const Face new_face = phi2(d); if (this->template is_orbit_embedded()) foreach_dart_of_orbit(new_face, [this] (Dart d) @@ -484,12 +479,12 @@ class CMap2_T : public CMap1_T public: - inline unsigned int degree(Face2 f) const + inline unsigned int degree(Face f) const { return Inherit::degree(f); } - inline unsigned int degree(Vertex2 v) const + inline unsigned int degree(Vertex v) const { return this->nb_darts(v); } @@ -837,62 +832,62 @@ class CMap2_T : public CMap1_T *******************************************************************************/ template - inline void foreach_adjacent_vertex_through_edge(Vertex2 v, const FUNC& f) const + inline void foreach_adjacent_vertex_through_edge(Vertex v, const FUNC& f) const { - static_assert(check_func_parameter_type(FUNC, Vertex2), "Wrong function cell parameter type"); - foreach_dart_of_orbit(v, [this, &f] (Dart d) { f(Vertex2(this->phi2(d))); }); + static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); + foreach_dart_of_orbit(v, [this, &f] (Dart d) { f(Vertex(this->phi2(d))); }); } template - inline void foreach_adjacent_vertex_through_face(Vertex2 v, const FUNC& f) const + inline void foreach_adjacent_vertex_through_face(Vertex v, const FUNC& f) const { - static_assert(check_func_parameter_type(FUNC, Vertex2), "Wrong function cell parameter type"); + static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); foreach_dart_of_orbit(v, [this, &f] (Dart vd) { Dart vd1 = this->phi1(vd); this->foreach_dart_of_orbit(vd, [&f, vd, vd1] (Dart fd) { - // skip Vertex2 v itself and its first successor around current face + // skip Vertex v itself and its first successor around current face if (fd != vd && fd != vd1) - f(Vertex2(fd)); + f(Vertex(fd)); }); }); } template - inline void foreach_adjacent_edge_through_vertex(Edge2 e, const FUNC& f) const + inline void foreach_adjacent_edge_through_vertex(Edge e, const FUNC& f) const { - static_assert(check_func_parameter_type(FUNC, Edge2), "Wrong function cell parameter type"); + static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); foreach_dart_of_orbit(e, [&f, this] (Dart ed) { this->foreach_dart_of_orbit(ed, [&f, ed] (Dart vd) { // skip Edge e itself if (vd != ed) - f(Edge2(vd)); + f(Edge(vd)); }); }); } template - inline void foreach_adjacent_edge_through_face(Edge2 e, const FUNC& f) const + inline void foreach_adjacent_edge_through_face(Edge e, const FUNC& f) const { - static_assert(check_func_parameter_type(FUNC, Edge2), "Wrong function cell parameter type"); + static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); foreach_dart_of_orbit(e, [&f, this] (Dart ed) { this->foreach_dart_of_orbit(ed, [&f, ed] (Dart fd) { // skip Edge e itself if (fd != ed) - f(Edge2(fd)); + f(Edge(fd)); }); }); } template - inline void foreach_adjacent_face_through_vertex(Face2 f, const FUNC& func) const + inline void foreach_adjacent_face_through_vertex(Face f, const FUNC& func) const { - static_assert(check_func_parameter_type(FUNC, Face2), "Wrong function cell parameter type"); + static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); foreach_dart_of_orbit(f, [this, &func] (Dart fd) { Dart fd1 = this->phi2(this->phi_1(fd)); @@ -900,16 +895,16 @@ class CMap2_T : public CMap1_T { // skip Face f itself and its first successor around current vertex if (vd != fd && vd != fd1) - func(Face2(vd)); + func(Face(vd)); }); }); } template - inline void foreach_adjacent_face_through_edge(Face2 f, const FUNC& func) const + inline void foreach_adjacent_face_through_edge(Face f, const FUNC& func) const { - static_assert(check_func_parameter_type(FUNC, Face2), "Wrong function cell parameter type"); - foreach_dart_of_orbit(f, [this, &func] (Dart d) { func(Face2(this->phi2(d))); }); + static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); + foreach_dart_of_orbit(f, [this, &func] (Dart d) { func(Face(this->phi2(d))); }); } }; diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index ea7f51e7..22c4d2ea 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -401,7 +401,7 @@ class CMap3_T : public CMap2_T inline unsigned int degree(Face f) const { - return Inherit::degree(typename Inherit::Face2(f.dart)); + return Inherit::degree(typename Inherit::Face(f.dart)); } protected: diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 1c4e97f6..d24a0709 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -349,12 +349,6 @@ class MapBase : public MapBaseData }); } - template - inline bool is_embedded(Cell /* c */) - { - return this->template is_orbit_embedded(); - } - template inline unsigned int new_embedding(Cell c) { diff --git a/cgogn/core/examples/map/map.cpp b/cgogn/core/examples/map/map.cpp index f57f93ce..8522a531 100644 --- a/cgogn/core/examples/map/map.cpp +++ b/cgogn/core/examples/map/map.cpp @@ -57,7 +57,7 @@ template int test1(MAP& map) { // add an attribute on vertex of map with - typename MAP::template VertexAttributeHandler ah = map.template add_attribute("floats"); + typename MAP::template VertexAttributeHandler ah = map.template add_attribute("floats"); typename MAP::template FaceAttributeHandler ahf = map.template add_attribute("floats"); @@ -100,7 +100,7 @@ int test1(MAP& map) std::cout << "End Darts" << std::endl; std::cout << "Vertices :" << std::endl; - map.template foreach_cell([&] (typename MAP::Vertex2 v) + map.template foreach_cell([&] (typename MAP::Vertex v) { std::cout << v << std::endl; ah[v] = 2.0f; diff --git a/cgogn/core/tests/cmap/cmap1_test.cpp b/cgogn/core/tests/cmap/cmap1_test.cpp index ca02bf4d..cd25926d 100644 --- a/cgogn/core/tests/cmap/cmap1_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_test.cpp @@ -36,7 +36,8 @@ class CMap1Test: public ::testing::Test public: typedef CMap1 myCMap1; - typedef myCMap1::Face1 Face; + typedef myCMap1::Vertex Vertex; + typedef myCMap1::Face Face; protected: myCMap1 cmap_; @@ -51,11 +52,11 @@ TEST_F(CMap1Test, addFace) { Face f = cmap_.add_face(10); -// cmap_.cut_edge(Edge(f)); + cmap_.split_vertex(Vertex(f.dart)); -// EXPECT_TRUE(is_well_embedded(cmap_)); -// EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); -// EXPECT_TRUE(is_container_well_referenced(cmap_)); + EXPECT_TRUE(is_well_embedded(cmap_)); + EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); + EXPECT_TRUE(is_container_well_referenced(cmap_)); } diff --git a/cgogn/core/tests/cmap/cmap1_topo_test.cpp b/cgogn/core/tests/cmap/cmap1_topo_test.cpp index 39b3f5fc..dfa15f47 100644 --- a/cgogn/core/tests/cmap/cmap1_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_topo_test.cpp @@ -33,7 +33,7 @@ namespace cgogn class CMap1TopoTest: public CMap1, public ::testing::Test { public: - typedef CMap1TopoTest::Face1 Face; + typedef CMap1TopoTest::Face Face; protected: diff --git a/cgogn/io/examples/cmap2_import.cpp b/cgogn/io/examples/cmap2_import.cpp index 31268389..190fddbb 100644 --- a/cgogn/io/examples/cmap2_import.cpp +++ b/cgogn/io/examples/cmap2_import.cpp @@ -60,23 +60,23 @@ int main(int argc, char** argv) std::cout << "nb darts // -> " << nb_darts_2 << std::endl; - VertexAttributeHandler vertex_position = map.get_attribute("position"); - VertexAttributeHandler vertex_normal = map.add_attribute("normal"); - FaceAttributeHandler face_normal = map.add_attribute("normal"); + VertexAttributeHandler vertex_position = map.get_attribute("position"); + VertexAttributeHandler vertex_normal = map.add_attribute("normal"); + FaceAttributeHandler face_normal = map.add_attribute("normal"); - map.enable_topo_cache(); - map.enable_topo_cache(); - map.enable_topo_cache(); + map.enable_topo_cache(); + map.enable_topo_cache(); + map.enable_topo_cache(); - std::cout << "Vertex orbits are well embedded ? -> " << std::boolalpha << cgogn::is_well_embedded(map) << std::endl; - std::cout << "Face orbits are well embedded ? -> " << std::boolalpha << cgogn::is_well_embedded(map) << std::endl; + std::cout << "Vertex orbits are well embedded ? -> " << std::boolalpha << cgogn::is_well_embedded(map) << std::endl; + std::cout << "Face orbits are well embedded ? -> " << std::boolalpha << cgogn::is_well_embedded(map) << std::endl; - std::cout << "Vertex orbit is uniquely embedded ? -> " << std::boolalpha << cgogn::is_orbit_embedding_unique(map) << std::endl; - std::cout << "Face orbit is uniquely embedded ? -> " << std::boolalpha << cgogn::is_orbit_embedding_unique(map) << std::endl; + std::cout << "Vertex orbit is uniquely embedded ? -> " << std::boolalpha << cgogn::is_orbit_embedding_unique(map) << std::endl; + std::cout << "Face orbit is uniquely embedded ? -> " << std::boolalpha << cgogn::is_orbit_embedding_unique(map) << std::endl; - std::cout << "Vertex container is well referenced ? -> " << std::boolalpha << cgogn::is_container_well_referenced(map) << std::endl; - std::cout << "Face container is well referenced ? -> " << std::boolalpha << cgogn::is_container_well_referenced(map) << std::endl; + std::cout << "Vertex container is well referenced ? -> " << std::boolalpha << cgogn::is_container_well_referenced(map) << std::endl; + std::cout << "Face container is well referenced ? -> " << std::boolalpha << cgogn::is_container_well_referenced(map) << std::endl; unsigned int nb_faces = 0; diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index 5fd9c556..b2d9f1a9 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -153,7 +153,7 @@ class SurfaceImport void create_map(Map& map) { using MapBuilder = cgogn::CMap2Builder_T; - const Orbit VERTEX = Map::Vertex2::SELF_ORBIT; + const Orbit VERTEX = Map::Vertex::SELF_ORBIT; if (this->nb_vertices_ == 0u) return; From b3fac47e846c0d808534600cb6f948c795a1c2b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Mon, 22 Feb 2016 14:16:33 +0100 Subject: [PATCH 128/402] Using using. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- .../multithreading/bench_multithreading.cpp | 4 +-- cgogn/core/basic/cell_marker.h | 15 +++++------ cgogn/core/basic/dart_marker.h | 26 +++++++++---------- cgogn/core/cmap/attribute_handler.h | 20 ++++++-------- cgogn/core/cmap/cmap0.h | 16 ++++++------ cgogn/core/cmap/cmap1.h | 19 ++++++-------- cgogn/core/cmap/cmap2.h | 20 +++++++------- cgogn/core/cmap/cmap3.h | 18 ++++++------- cgogn/core/cmap/map_base.h | 4 +-- cgogn/core/cmap/map_base_data.h | 6 ++--- cgogn/core/container/chunk_array.h | 12 ++++----- cgogn/core/container/chunk_array_container.h | 4 +-- cgogn/core/container/chunk_array_factory.h | 6 ++--- cgogn/core/container/chunk_array_gen.h | 2 +- cgogn/core/container/chunk_stack.h | 6 ++--- .../core/examples/chunk_array/chunk_array.cpp | 4 +-- cgogn/core/examples/map/map.cpp | 11 ++++---- cgogn/core/tests/cmap/cmap1_test.cpp | 12 ++++----- cgogn/core/tests/cmap/cmap1_topo_test.cpp | 2 +- cgogn/core/utils/assert.h | 4 +-- cgogn/core/utils/buffers.h | 4 +-- cgogn/core/utils/make_unique.h | 8 +++--- cgogn/io/examples/cmap2_import.cpp | 24 ++++++++--------- cgogn/io/surface_import.h | 2 +- .../cph/attribute_handler_cph.h | 6 ++--- cgogn/multiresolution/cph/cph2.h | 4 +-- cgogn/multiresolution/cph/cph_base.h | 2 +- cgogn/multiresolution/cph/ihcmap2.h | 22 ++++++++-------- cgogn/multiresolution/cph/ihcmap2_adaptive.h | 10 +++---- cgogn/multiresolution/cph/ihcmap2_regular.h | 2 +- cgogn/multiresolution/cph/ihcmap3.h | 2 +- cgogn/multiresolution/mrcmap/mr_base.h | 2 +- cgogn/multiresolution/mrcmap/mrcmap2.h | 14 +++++----- 33 files changed, 152 insertions(+), 161 deletions(-) diff --git a/benchmarks/multithreading/bench_multithreading.cpp b/benchmarks/multithreading/bench_multithreading.cpp index ba1ae2dc..c3620044 100644 --- a/benchmarks/multithreading/bench_multithreading.cpp +++ b/benchmarks/multithreading/bench_multithreading.cpp @@ -37,10 +37,10 @@ using Map2 = cgogn::CMap2; Map2 map; using Vertex = Map2::Vertex; -const cgogn::Orbit VERTEX = Vertex::SELF_ORBIT; +const cgogn::Orbit VERTEX = Vertex::ORBIT; using Face = Map2::Face; -const cgogn::Orbit FACE = Face::SELF_ORBIT; +const cgogn::Orbit FACE = Face::ORBIT; const unsigned int ITERATIONS = 1u; diff --git a/cgogn/core/basic/cell_marker.h b/cgogn/core/basic/cell_marker.h index 405f5c39..095afe9c 100644 --- a/cgogn/core/basic/cell_marker.h +++ b/cgogn/core/basic/cell_marker.h @@ -34,7 +34,7 @@ namespace cgogn //class CGOGN_CORE_API CellMarkerGen //{ //public: -// typedef CellMarkerGen Self; +// using Self = CellMarkerGen; // CellMarkerGen() // {} @@ -113,9 +113,9 @@ class CellMarker : public CellMarker_T { public: - typedef CellMarker_T Inherit; - typedef CellMarker< MAP, ORBIT > Self; - typedef typename Inherit::Map Map; + using Inherit = CellMarker_T; + using Self = CellMarker< MAP, ORBIT >; + using Map = typename Inherit::Map; CellMarker(Map& map) : Inherit(map) @@ -147,10 +147,9 @@ class CellMarkerStore : public CellMarker_T { public: - typedef CellMarker_T Inherit; - typedef CellMarkerStore< MAP, ORBIT > Self; - - typedef typename Inherit::Map Map; + using Inherit = CellMarker_T; + using Self = CellMarkerStore< MAP, ORBIT >; + using Map = typename Inherit::Map; protected: diff --git a/cgogn/core/basic/dart_marker.h b/cgogn/core/basic/dart_marker.h index 71442dcb..8bf027e2 100644 --- a/cgogn/core/basic/dart_marker.h +++ b/cgogn/core/basic/dart_marker.h @@ -35,7 +35,7 @@ namespace cgogn //class CGOGN_CORE_API DartMarkerGen //{ //public: -// typedef DartMarkerGen Self; +// using Self = DartMarkerGen; // DartMarkerGen() // {} @@ -52,10 +52,8 @@ class DartMarker_T // : public DartMarkerGen { public: -// typedef DartMarkerGen Inherit; - typedef DartMarker_T Self; - - typedef MAP Map; + using Self = DartMarker_T; + using Map = MAP; using ChunkArrayBool = typename Map::template ChunkArray; protected: @@ -126,9 +124,9 @@ class DartMarker : public DartMarker_T { public: - typedef DartMarker_T Inherit; - typedef DartMarker Self; - typedef MAP Map; + using Inherit = DartMarker_T; + using Self = DartMarker; + using Map = MAP; DartMarker(const MAP& map) : Inherit(map) @@ -156,9 +154,9 @@ class DartMarkerStore : public DartMarker_T { public: - typedef DartMarkerStore Self; - typedef DartMarker_T Inherit; - typedef MAP Map; + using Self = DartMarkerStore; + using Inherit = DartMarker_T; + using Map = MAP; protected: @@ -220,9 +218,9 @@ class DartMarkerNoUnmark : public DartMarker_T { public: - typedef DartMarker_T Inherit; - typedef DartMarkerNoUnmark Self; - typedef MAP Map; + using Inherit = DartMarker_T; + using Self = DartMarkerNoUnmark; + using Map = MAP; DartMarkerNoUnmark(const MAP& map) : Inherit(map) diff --git a/cgogn/core/cmap/attribute_handler.h b/cgogn/core/cmap/attribute_handler.h index 8e3a436f..57aa5fe0 100644 --- a/cgogn/core/cmap/attribute_handler.h +++ b/cgogn/core/cmap/attribute_handler.h @@ -39,9 +39,8 @@ class AttributeHandlerGen { public: - typedef AttributeHandlerGen Self; - - typedef MapBaseData MapData; + using Self = AttributeHandlerGen; + using MapData = MapBaseData; protected: @@ -111,10 +110,9 @@ class AttributeHandlerOrbit : public AttributeHandlerGen { public: - typedef AttributeHandlerGen Inherit; - typedef AttributeHandlerOrbit Self; - - typedef typename Inherit::MapData MapData; + using Inherit = AttributeHandlerGen; + using Self = AttributeHandlerOrbit; + using MapData = typename Inherit::MapData; static const unsigned int CHUNKSIZE = MapData::CHUNKSIZE; @@ -196,11 +194,9 @@ class AttributeHandler : public AttributeHandlerOrbit { public: - typedef AttributeHandlerOrbit Inherit; - typedef AttributeHandler Self; - - typedef T value_type; - + using Inherit = AttributeHandlerOrbit; + using Self = AttributeHandler; + using value_type = T; using MapData = typename Inherit::MapData; using TChunkArray = typename Inherit::template ChunkArray; diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index cc18764b..af70645d 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -36,18 +36,18 @@ class CMap0_T : public MapBase static const int PRIM_SIZE = 1; - typedef MAP_TRAITS MapTraits; - typedef MAP_TYPE MapType; - typedef MapBase Inherit; - typedef CMap0_T Self; + using MapTraits = MAP_TRAITS; + using MapType = MAP_TYPE; + using Inherit = MapBase; + using Self = CMap0_T; friend class MapBase; template friend class DartMarker_T; template friend class DartMarkerStore; -// static const Orbit VERTEX = Orbit::DART; + static const Orbit VERTEX = Orbit::DART; - typedef Cell Vertex; + using Vertex = Cell; template using ChunkArray = typename Inherit::template ChunkArray; @@ -57,7 +57,7 @@ class CMap0_T : public MapBase template using AttributeHandler = typename Inherit::template AttributeHandler; template - using DartAttributeHandler = AttributeHandler; + using VertexAttributeHandler = AttributeHandler; using DartMarker = typename cgogn::DartMarker; using DartMarkerStore = typename cgogn::DartMarkerStore; @@ -148,7 +148,7 @@ class CMap0_T : public MapBase template struct CMap0Type { - typedef CMap0_T> TYPE; + using TYPE = CMap0_T>; }; template diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 41033cdf..122b04e1 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -36,20 +36,17 @@ class CMap1_T : public CMap0_T static const int PRIM_SIZE = 1; - typedef MAP_TRAITS MapTraits; - typedef MAP_TYPE MapType; - typedef CMap0_T Inherit; - typedef CMap1_T Self; + using MapTraits = MAP_TRAITS ; + using MapType = MAP_TYPE ; + using Inherit = CMap0_T; + using Self = CMap1_T; friend class MapBase; template friend class DartMarker_T; template friend class DartMarkerStore; -// static const Orbit DART = Orbit::DART; -// static const Orbit FACE = Orbit::PHI1; - - typedef Cell Vertex; - typedef Cell Face; + using Vertex = Cell; + using Face = Cell; template using ChunkArray = typename Inherit::template ChunkArray; @@ -61,7 +58,7 @@ class CMap1_T : public CMap0_T template using DartAttributeHandler = AttributeHandler; template - using FaceAttributeHandler = AttributeHandler; + using FaceAttributeHandler = AttributeHandler; using DartMarker = typename cgogn::DartMarker; using DartMarkerStore = typename cgogn::DartMarkerStore; @@ -414,7 +411,7 @@ class CMap1_T : public CMap0_T template struct CMap1Type { - typedef CMap1_T> TYPE; + using TYPE = CMap1_T>; }; template diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 6209509c..68b78984 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -39,10 +39,10 @@ class CMap2_T : public CMap1_T { public: - typedef MAP_TRAITS MapTraits; - typedef MAP_TYPE MapType; - typedef CMap1_T Inherit; - typedef CMap2_T Self; + using MapTraits = MAP_TRAITS; + using MapType = MAP_TYPE; + using Inherit = CMap1_T; + using Self = CMap2_T; friend class MapBase; friend class CMap2Builder_T; @@ -57,11 +57,11 @@ class CMap2_T : public CMap1_T static const Orbit FACE = Orbit::PHI1; // static const Orbit VOLUME = Orbit::PHI1_PHI2; - typedef Cell CDart; - typedef Cell Vertex; - typedef Cell Edge; - typedef Cell Face; - typedef Cell Volume; + using CDart = Cell ; + using Vertex = Cell ; + using Edge = Cell ; + using Face = Cell ; + using Volume = Cell; template using ChunkArray = typename Inherit::template ChunkArray; @@ -911,7 +911,7 @@ class CMap2_T : public CMap1_T template struct CMap2Type { - typedef CMap2_T> TYPE; + using TYPE = CMap2_T>; }; template diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 22c4d2ea..fdb68d38 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -39,10 +39,10 @@ class CMap3_T : public CMap2_T { public: - typedef MAP_TRAITS MapTraits; - typedef MAP_TYPE MapType; - typedef CMap2_T Inherit; - typedef CMap3_T Self; + using MapTraits = MAP_TRAITS; + using MapType = MAP_TYPE; + using Inherit = CMap2_T; + using Self = CMap3_T; friend class MapBase; friend class CMap3Builder_T; @@ -57,10 +57,10 @@ class CMap3_T : public CMap2_T static const Orbit FACE = Orbit::PHI1_PHI3; static const Orbit VOLUME = Orbit::PHI1_PHI2; - typedef Cell Vertex; - typedef Cell Edge; - typedef Cell Face; - typedef Cell Volume; + using Vertex = Cell; + using Edge = Cell; + using Face = Cell; + using Volume = Cell; template using ChunkArray = typename Inherit::template ChunkArray; @@ -915,7 +915,7 @@ class CMap3_T : public CMap2_T template struct CMap3Type { - typedef CMap3_T> TYPE; + using TYPE = CMap3_T>; }; template diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 5dbdd319..62dd1e54 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -53,8 +53,8 @@ class MapBase : public MapBaseData { public: - typedef MapBaseData Inherit; - typedef MapBase Self; + using Inherit = MapBaseData; + using Self = MapBase; template friend class DartMarker_T; template friend class CellMarker_T; diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index e5eb3ea2..7bd80c1b 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -55,7 +55,7 @@ class CGOGN_CORE_API MapGen { public: - typedef MapGen Self; + using Self = MapGen; protected: @@ -92,8 +92,8 @@ class MapBaseData : public MapGen { public: - typedef MapGen Inherit; - typedef MapBaseData Self; + using Inherit = MapGen; + using Self = MapBaseData; static const unsigned int CHUNKSIZE = MAP_TRAITS::CHUNK_SIZE; static const unsigned int NB_UNKNOWN_THREADS = 4u; diff --git a/cgogn/core/container/chunk_array.h b/cgogn/core/container/chunk_array.h index b68de742..c660b4c5 100644 --- a/cgogn/core/container/chunk_array.h +++ b/cgogn/core/container/chunk_array.h @@ -49,9 +49,9 @@ class ChunkArray : public ChunkArrayGen { public: - typedef ChunkArrayGen Inherit; - typedef ChunkArray Self; - typedef T value_type; + using Inherit = ChunkArrayGen; + using Self = ChunkArray; + using value_type = T; protected: @@ -391,9 +391,9 @@ class ChunkArray : public ChunkArrayGen { public: - typedef ChunkArrayGen Inherit; - typedef ChunkArray Self; - typedef unsigned int value_type; + using Inherit = ChunkArrayGen; + using Self = ChunkArray; + using value_type = unsigned int; protected: diff --git a/cgogn/core/container/chunk_array_container.h b/cgogn/core/container/chunk_array_container.h index ea5ed42a..0ada02b8 100644 --- a/cgogn/core/container/chunk_array_container.h +++ b/cgogn/core/container/chunk_array_container.h @@ -84,8 +84,8 @@ class ChunkArrayContainer { public: - typedef ChunkArrayContainer Self; - typedef T_REF ref_type; + using Self = ChunkArrayContainer; + using ref_type = T_REF; using ChunkArrayGen = cgogn::ChunkArrayGen; template diff --git a/cgogn/core/container/chunk_array_factory.h b/cgogn/core/container/chunk_array_factory.h index 765c087d..9b7f2b8b 100644 --- a/cgogn/core/container/chunk_array_factory.h +++ b/cgogn/core/container/chunk_array_factory.h @@ -43,9 +43,9 @@ class ChunkArrayFactory static_assert(!(CHUNKSIZE & (CHUNKSIZE - 1)),"CHUNKSIZE must be a power of 2"); public: - typedef std::unique_ptr< ChunkArrayGen > ChunkArrayGenPtr; - typedef std::map NamePtrMap; - typedef std::unique_ptr UniqueNamePtrMap; + using ChunkArrayGenPtr = std::unique_ptr< ChunkArrayGen >; + using NamePtrMap = std::map; + using UniqueNamePtrMap = std::unique_ptr; static UniqueNamePtrMap map_CA_; diff --git a/cgogn/core/container/chunk_array_gen.h b/cgogn/core/container/chunk_array_gen.h index 686ea93e..de53307f 100644 --- a/cgogn/core/container/chunk_array_gen.h +++ b/cgogn/core/container/chunk_array_gen.h @@ -44,7 +44,7 @@ class ChunkArrayGen { public: - typedef ChunkArrayGen Self; + using Self = ChunkArrayGen; inline ChunkArrayGen() { diff --git a/cgogn/core/container/chunk_stack.h b/cgogn/core/container/chunk_stack.h index ace862e4..2620dd20 100644 --- a/cgogn/core/container/chunk_stack.h +++ b/cgogn/core/container/chunk_stack.h @@ -40,9 +40,9 @@ template class ChunkStack : public ChunkArray { public: - typedef ChunkArray Inherit; - typedef ChunkStack Self; - typedef T value_type; + using Inherit = ChunkArray; + using Self = ChunkStack; + using value_type = T; protected: diff --git a/cgogn/core/examples/chunk_array/chunk_array.cpp b/cgogn/core/examples/chunk_array/chunk_array.cpp index 726070dc..16250e6d 100644 --- a/cgogn/core/examples/chunk_array/chunk_array.cpp +++ b/cgogn/core/examples/chunk_array/chunk_array.cpp @@ -209,8 +209,8 @@ int test3() int test4() { std::cout << "=============== TEST 4 ===============" << std::endl; - typedef std::vector< std::vector< double > > vecvecdouble; - typedef std::vector< std::list< double > > veclistdouble; + using vecvecdouble = std::vector< std::vector< double > >; + using veclistdouble = std::vector< std::list< double > >; ChunkArrayContainer container; ChunkArray* att1 = container.add_attribute("entier"); ChunkArray* att2 = container.add_attribute("reel"); diff --git a/cgogn/core/examples/map/map.cpp b/cgogn/core/examples/map/map.cpp index 76b0ff2e..b54622fe 100644 --- a/cgogn/core/examples/map/map.cpp +++ b/cgogn/core/examples/map/map.cpp @@ -59,7 +59,7 @@ int test1(MAP& map) // add an attribute on vertex of map with typename MAP::template VertexAttributeHandler ah = map.template add_attribute("floats"); - typename MAP::template FaceAttributeHandler ahf = map.template add_attribute("floats"); + typename MAP::template FaceAttributeHandler ahf = map.template add_attribute("floats"); // get attribute and change type (dangerous!) typename MAP::template VertexAttributeHandler ahf2 = map.template get_attribute_force_type("floats"); @@ -107,10 +107,11 @@ int test1(MAP& map) }); std::cout << "End Vertices" << std::endl; - map.foreach_adjacent_vertex_through_edge(d1, [&] (typename MAP::Vertex v) - { - ah[v] = 4.0f; - }); + // the method foreach_adjacent_vertex_through_edge is not well defined for a MAP1 +// map.foreach_adjacent_vertex_through_edge(d1, [&] (typename MAP::Vertex v) +// { +// ah[v] = 4.0f; +// }); // get ChunkArrayContainer -> get ChunkArray -> fill // typename MAP::template ChunkArrayContainer& container = map.get_attribute_container(MAP::Vertex); diff --git a/cgogn/core/tests/cmap/cmap1_test.cpp b/cgogn/core/tests/cmap/cmap1_test.cpp index cd25926d..f4d925fc 100644 --- a/cgogn/core/tests/cmap/cmap1_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_test.cpp @@ -35,9 +35,9 @@ class CMap1Test: public ::testing::Test { public: - typedef CMap1 myCMap1; - typedef myCMap1::Vertex Vertex; - typedef myCMap1::Face Face; + using myCMap1 = CMap1; + using Vertex = myCMap1::Vertex; + using Face = myCMap1::Face; protected: myCMap1 cmap_; @@ -54,9 +54,9 @@ TEST_F(CMap1Test, addFace) cmap_.split_vertex(Vertex(f.dart)); - EXPECT_TRUE(is_well_embedded(cmap_)); - EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); - EXPECT_TRUE(is_container_well_referenced(cmap_)); + EXPECT_TRUE(is_well_embedded(cmap_)); + EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); + EXPECT_TRUE(is_container_well_referenced(cmap_)); } diff --git a/cgogn/core/tests/cmap/cmap1_topo_test.cpp b/cgogn/core/tests/cmap/cmap1_topo_test.cpp index dfa15f47..1f2904bc 100644 --- a/cgogn/core/tests/cmap/cmap1_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_topo_test.cpp @@ -33,7 +33,7 @@ namespace cgogn class CMap1TopoTest: public CMap1, public ::testing::Test { public: - typedef CMap1TopoTest::Face Face; + using Face = CMap1TopoTest::Face; protected: diff --git a/cgogn/core/utils/assert.h b/cgogn/core/utils/assert.h index 61cdda27..2e61394d 100644 --- a/cgogn/core/utils/assert.h +++ b/cgogn/core/utils/assert.h @@ -222,12 +222,12 @@ struct function_traits enum { arity = sizeof...(Args) }; // arity is the number of arguments. - typedef ReturnType result_type; + using result_type = ReturnType; template struct arg { - typedef typename std::tuple_element>::type type; + using type = typename std::tuple_element>::type; // the i-th argument is equivalent to the i-th tuple element of a tuple // composed of those arguments. }; diff --git a/cgogn/core/utils/buffers.h b/cgogn/core/utils/buffers.h index c00dc0dc..4aad31f7 100644 --- a/cgogn/core/utils/buffers.h +++ b/cgogn/core/utils/buffers.h @@ -37,7 +37,7 @@ namespace cgogn template class Buffers { - typedef T value_type; + using value_type = T; static const unsigned int DEFAULT_SIZE = 128u; static const unsigned int SHRINK_SIZE = 1024u; @@ -84,7 +84,7 @@ class Buffers template <> class Buffers { - typedef Dart value_type; + using value_type = Dart; static const unsigned int DEFAULT_SIZE = 128u; static const unsigned int SHRINK_SIZE = 1024u; diff --git a/cgogn/core/utils/make_unique.h b/cgogn/core/utils/make_unique.h index 7402af6c..61e5d7fc 100644 --- a/cgogn/core/utils/make_unique.h +++ b/cgogn/core/utils/make_unique.h @@ -41,19 +41,19 @@ namespace cgogn template struct _Unique_if { - typedef std::unique_ptr _Single_object; + using _Single_object = std::unique_ptr; }; template struct _Unique_if { - typedef std::unique_ptr _Unknown_bound; + using _Unknown_bound = std::unique_ptr; }; template struct _Unique_if { - typedef void _Known_bound; + using _Known_bound = void; }; template @@ -67,7 +67,7 @@ template typename _Unique_if::_Unknown_bound make_unique(size_t n) { - typedef typename std::remove_extent::type U; + using U = typename std::remove_extent::type; return std::unique_ptr(new U[n]()); } diff --git a/cgogn/io/examples/cmap2_import.cpp b/cgogn/io/examples/cmap2_import.cpp index 3b6a4aa3..eca85c62 100644 --- a/cgogn/io/examples/cmap2_import.cpp +++ b/cgogn/io/examples/cmap2_import.cpp @@ -60,23 +60,23 @@ int main(int argc, char** argv) std::cout << "nb darts // -> " << nb_darts_2 << std::endl; - VertexAttributeHandler vertex_position = map.get_attribute("position"); - VertexAttributeHandler vertex_normal = map.add_attribute("normal"); - FaceAttributeHandler face_normal = map.add_attribute("normal"); + VertexAttributeHandler vertex_position = map.get_attribute("position"); + VertexAttributeHandler vertex_normal = map.add_attribute("normal"); + FaceAttributeHandler face_normal = map.add_attribute("normal"); - map.enable_topo_cache(); - map.enable_topo_cache(); - map.enable_topo_cache(); + map.enable_topo_cache(); + map.enable_topo_cache(); + map.enable_topo_cache(); - std::cout << "Vertex orbits are well embedded ? -> " << std::boolalpha << cgogn::is_well_embedded(map) << std::endl; - std::cout << "Face orbits are well embedded ? -> " << std::boolalpha << cgogn::is_well_embedded(map) << std::endl; + std::cout << "Vertex orbits are well embedded ? -> " << std::boolalpha << cgogn::is_well_embedded(map) << std::endl; + std::cout << "Face orbits are well embedded ? -> " << std::boolalpha << cgogn::is_well_embedded(map) << std::endl; - std::cout << "Vertex orbit is uniquely embedded ? -> " << std::boolalpha << cgogn::is_orbit_embedding_unique(map) << std::endl; - std::cout << "Face orbit is uniquely embedded ? -> " << std::boolalpha << cgogn::is_orbit_embedding_unique(map) << std::endl; + std::cout << "Vertex orbit is uniquely embedded ? -> " << std::boolalpha << cgogn::is_orbit_embedding_unique(map) << std::endl; + std::cout << "Face orbit is uniquely embedded ? -> " << std::boolalpha << cgogn::is_orbit_embedding_unique(map) << std::endl; - std::cout << "Vertex container is well referenced ? -> " << std::boolalpha << cgogn::is_container_well_referenced(map) << std::endl; - std::cout << "Face container is well referenced ? -> " << std::boolalpha << cgogn::is_container_well_referenced(map) << std::endl; + std::cout << "Vertex container is well referenced ? -> " << std::boolalpha << cgogn::is_container_well_referenced(map) << std::endl; + std::cout << "Face container is well referenced ? -> " << std::boolalpha << cgogn::is_container_well_referenced(map) << std::endl; unsigned int nb_faces = 0; diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index b2d9f1a9..54c8edcb 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -153,7 +153,7 @@ class SurfaceImport void create_map(Map& map) { using MapBuilder = cgogn::CMap2Builder_T; - const Orbit VERTEX = Map::Vertex::SELF_ORBIT; + const Orbit VERTEX = Map::Vertex::ORBIT; if (this->nb_vertices_ == 0u) return; diff --git a/cgogn/multiresolution/cph/attribute_handler_cph.h b/cgogn/multiresolution/cph/attribute_handler_cph.h index ed26ef10..9f0aea26 100644 --- a/cgogn/multiresolution/cph/attribute_handler_cph.h +++ b/cgogn/multiresolution/cph/attribute_handler_cph.h @@ -39,10 +39,10 @@ class AttributeHandlerCPH : public AttributeHandler { public: - typedef AttributeHandler Inherit; - typedef AttributeHandlerCPH Self; + using Inherit = AttributeHandler; + using Self = AttributeHandlerCPH; - typedef T value_type; + using value_type = T; using MapData = typename Inherit::MapData; using TChunkArray = typename Inherit::template ChunkArray; diff --git a/cgogn/multiresolution/cph/cph2.h b/cgogn/multiresolution/cph/cph2.h index 22d7e47e..1c83cb23 100644 --- a/cgogn/multiresolution/cph/cph2.h +++ b/cgogn/multiresolution/cph/cph2.h @@ -35,8 +35,8 @@ class CPH2 : public CPHBase public: - typedef CPH2 Self; - typedef CPHBase Inherit; + using Self = CPH2; + using Inherit = CPHBase; template using ChunkArray = typename Inherit::template ChunkArray; diff --git a/cgogn/multiresolution/cph/cph_base.h b/cgogn/multiresolution/cph/cph_base.h index 675748b1..99bb4d1d 100644 --- a/cgogn/multiresolution/cph/cph_base.h +++ b/cgogn/multiresolution/cph/cph_base.h @@ -40,7 +40,7 @@ class CPHBase public: - typedef CPHBase Self; + using Self = CPHBase; template using ChunkArray = cgogn::ChunkArray; diff --git a/cgogn/multiresolution/cph/ihcmap2.h b/cgogn/multiresolution/cph/ihcmap2.h index 62760f40..28889c6b 100644 --- a/cgogn/multiresolution/cph/ihcmap2.h +++ b/cgogn/multiresolution/cph/ihcmap2.h @@ -59,11 +59,11 @@ class IHCMap2_T : public CMap2_T, public CPH2 static const int PRIM_SIZE = 1; - typedef MAP_TRAITS MapTraits; - typedef MAP_TYPE MapType; - typedef CMap2_T Inherit_CMAP; - typedef CPH2 Inherit_CPH; - typedef IHCMap2_T Self; + using MapTraits = MAP_TRAITS; + using MapType = MAP_TYPE; + using Inherit_CMAP = CMap2_T; + using Inherit_CPH = CPH2; + using Self = IHCMap2_T; friend class MapBase; template friend class DartMarker_T; @@ -75,11 +75,11 @@ class IHCMap2_T : public CMap2_T, public CPH2 // static const Orbit FACE = Inherit_CMAP::FACE; // static const Orbit VOLUME = Inherit_CMAP::VOLUME; - typedef Cell Vertex0; - typedef Cell Vertex2; - typedef Cell Edge2; - typedef Cell Face2; - typedef Cell Volume2; + using Vertex0 = Cell ; + using Vertex2 = Cell ; + using Edge2 = Cell ; + using Face2 = Cell ; + using Volume2 = Cell; template @@ -370,7 +370,7 @@ class IHCMap2_T : public CMap2_T, public CPH2 template struct IHCMap2Type { - typedef IHCMap2_T> TYPE; + using TYPE = IHCMap2_T>; }; template diff --git a/cgogn/multiresolution/cph/ihcmap2_adaptive.h b/cgogn/multiresolution/cph/ihcmap2_adaptive.h index baefccb6..5231fd92 100644 --- a/cgogn/multiresolution/cph/ihcmap2_adaptive.h +++ b/cgogn/multiresolution/cph/ihcmap2_adaptive.h @@ -36,10 +36,10 @@ class IHCMap2Adaptive_T : public IHCMap2_T static const int PRIM_SIZE = 1; - typedef MAP_TRAITS MapTraits; - typedef MAP_TYPE MapType; - typedef IHCMap2_T Inherit; - typedef IHCMap2Adaptive_T Self; + using MapTraits = MAP_TRAITS; + using MapType = MAP_TYPE; + using Inherit = IHCMap2_T; + using Self = IHCMap2Adaptive_T; friend class MapBase; @@ -579,7 +579,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T template struct IHCMap2AdaptiveType { - typedef IHCMap2Adaptive_T> TYPE; + using TYPE = IHCMap2Adaptive_T>; }; template diff --git a/cgogn/multiresolution/cph/ihcmap2_regular.h b/cgogn/multiresolution/cph/ihcmap2_regular.h index 0ff197ae..669296dc 100644 --- a/cgogn/multiresolution/cph/ihcmap2_regular.h +++ b/cgogn/multiresolution/cph/ihcmap2_regular.h @@ -284,7 +284,7 @@ class IHCMap2Regular_T : public IHCMap2_T template struct IHCMap2RegularType { - typedef IHCMap2Regular_T> TYPE; + using TYPE = IHCMap2Regular_T>; }; template diff --git a/cgogn/multiresolution/cph/ihcmap3.h b/cgogn/multiresolution/cph/ihcmap3.h index 2409aeb3..5c8c9a83 100644 --- a/cgogn/multiresolution/cph/ihcmap3.h +++ b/cgogn/multiresolution/cph/ihcmap3.h @@ -389,7 +389,7 @@ class IHCMap3_T :public CMap3_T, public CPH3 template struct IHCMap3Type { - typedef IHCMap3_T> TYPE; + using TYPE = IHCMap3_T>; }; template diff --git a/cgogn/multiresolution/mrcmap/mr_base.h b/cgogn/multiresolution/mrcmap/mr_base.h index 1f536400..a5349d96 100644 --- a/cgogn/multiresolution/mrcmap/mr_base.h +++ b/cgogn/multiresolution/mrcmap/mr_base.h @@ -35,7 +35,7 @@ template class MRBase { public: - typedef MRBase Self; + using Self = MRBase; template using ChunkArray = typename MAP::template ChunkArray; diff --git a/cgogn/multiresolution/mrcmap/mrcmap2.h b/cgogn/multiresolution/mrcmap/mrcmap2.h index feeb5cea..611cdc20 100644 --- a/cgogn/multiresolution/mrcmap/mrcmap2.h +++ b/cgogn/multiresolution/mrcmap/mrcmap2.h @@ -35,18 +35,18 @@ class MRCMap2_T : public MRBase> { public: - typedef MRCMap2_T Self; - typedef CMap2_T CMap2; + using Self = MRCMap2_T; + using CMap2 = CMap2_T; static const Orbit VERTEX = CMap2::VERTEX; static const Orbit EDGE = CMap2::EDGE; static const Orbit FACE = CMap2::FACE; static const Orbit VOLUME = CMap2::VOLUME; - typedef CMap2::Vertex Vertex; - typedef CMap2::Edge Edge; - typedef CMap2::Face Face; - typedef CMap2::Volume Volume; + using Vertex = CMap2::Vertex; + using Edge = CMap2::Edge; + using Face = CMap2::Face; + using Volume = CMap2::Volume; public: @@ -122,7 +122,7 @@ class MRCMap2_T : public MRBase> template struct MRCMap2Type { - typedef MRCMap2_T> TYPE; + using TYPE = MRCMap2_T>; }; template From b09af128fbffeaededd7dac80fab6364d70fd724 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Mon, 22 Feb 2016 14:21:26 +0100 Subject: [PATCH 129/402] Work in progress --- .../multithreading/bench_multithreading.cpp | 4 +- cgogn/core/cmap/cmap0.h | 13 +- cgogn/core/cmap/cmap1.h | 38 +- cgogn/core/cmap/cmap2.h | 326 ++++++------------ cgogn/core/cmap/map_base_data.h | 7 + cgogn/core/examples/map/map.cpp | 10 +- cgogn/core/tests/cmap/cmap1_test.cpp | 6 +- cgogn/geometry/algos/normal.h | 6 +- cgogn/io/examples/cmap2_import.cpp | 24 +- cgogn/io/surface_import.h | 2 +- 10 files changed, 167 insertions(+), 269 deletions(-) diff --git a/benchmarks/multithreading/bench_multithreading.cpp b/benchmarks/multithreading/bench_multithreading.cpp index ba1ae2dc..c3620044 100644 --- a/benchmarks/multithreading/bench_multithreading.cpp +++ b/benchmarks/multithreading/bench_multithreading.cpp @@ -37,10 +37,10 @@ using Map2 = cgogn::CMap2; Map2 map; using Vertex = Map2::Vertex; -const cgogn::Orbit VERTEX = Vertex::SELF_ORBIT; +const cgogn::Orbit VERTEX = Vertex::ORBIT; using Face = Map2::Face; -const cgogn::Orbit FACE = Face::SELF_ORBIT; +const cgogn::Orbit FACE = Face::ORBIT; const unsigned int ITERATIONS = 1u; diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index cc18764b..b71e25d4 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -45,8 +45,6 @@ class CMap0_T : public MapBase template friend class DartMarker_T; template friend class DartMarkerStore; -// static const Orbit VERTEX = Orbit::DART; - typedef Cell Vertex; template @@ -57,7 +55,7 @@ class CMap0_T : public MapBase template using AttributeHandler = typename Inherit::template AttributeHandler; template - using DartAttributeHandler = AttributeHandler; + using VertexAttributeHandler = AttributeHandler; using DartMarker = typename cgogn::DartMarker; using DartMarkerStore = typename cgogn::DartMarkerStore; @@ -108,7 +106,7 @@ class CMap0_T : public MapBase Vertex v = this->add_dart(); - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) this->new_embedding(v); return v; @@ -139,8 +137,7 @@ class CMap0_T : public MapBase template inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const { - static_assert(ORBIT == Orbit::DART, - "Orbit not supported in a CMap0"); + static_assert(ORBIT == Orbit::DART, "Orbit not supported in a CMap0"); this->foreach_dart_of_DART(c, f); } }; @@ -159,8 +156,8 @@ extern template class CGOGN_CORE_API CMap0_T>; extern template class CGOGN_CORE_API DartMarkerStore>; extern template class CGOGN_CORE_API DartMarkerNoUnmark>; -extern template class CGOGN_CORE_API CellMarker, Orbit::DART>; -extern template class CGOGN_CORE_API CellMarkerStore, Orbit::DART>; +extern template class CGOGN_CORE_API CellMarker, Vertex::ORBIT>; +extern template class CGOGN_CORE_API CellMarkerStore, Vertex::ORBIT>; #endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_MAP_MAP0_CPP_)) } // namespace cgogn diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 41033cdf..db1bddb0 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -45,9 +45,6 @@ class CMap1_T : public CMap0_T template friend class DartMarker_T; template friend class DartMarkerStore; -// static const Orbit DART = Orbit::DART; -// static const Orbit FACE = Orbit::PHI1; - typedef Cell Vertex; typedef Cell Face; @@ -59,9 +56,9 @@ class CMap1_T : public CMap0_T template using AttributeHandler = typename Inherit::template AttributeHandler; template - using DartAttributeHandler = AttributeHandler; + using VertexAttributeHandler = AttributeHandler; template - using FaceAttributeHandler = AttributeHandler; + using FaceAttributeHandler = AttributeHandler; using DartMarker = typename cgogn::DartMarker; using DartMarkerStore = typename cgogn::DartMarkerStore; @@ -213,9 +210,10 @@ class CMap1_T : public CMap0_T Vertex nv = split_vertex_topo(v); - if (this->template is_orbit_embedded()) this->new_embedding(nv); + if (this->template is_embedded()) + this->new_embedding(nv); - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) this->copy_embedding(Face(nv.dart), Face(v.dart)); return nv; @@ -267,13 +265,13 @@ class CMap1_T : public CMap0_T Face f = add_face_topo(size); - if (this->template is_orbit_embedded()) - foreach_dart_of_PHI1(f.dart, [this] (Vertex v) + if (this->template is_embedded()) + foreach_dart_of_orbit(f, [this] (Vertex v) { this->new_embedding(v); }); - if (this->template is_orbit_embedded()) this->new_orbit_embedding(f); + if (this->template is_embedded()) this->new_orbit_embedding(f); return f; } @@ -344,9 +342,6 @@ class CMap1_T : public CMap0_T template inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const { - static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1, - "Orbit not supported in a CMap1"); - switch (ORBIT) { case Orbit::DART: this->foreach_dart_of_DART(c, f); break; @@ -357,7 +352,7 @@ class CMap1_T : public CMap0_T case Orbit::PHI2_PHI3: case Orbit::PHI21: case Orbit::PHI21_PHI31: - default: cgogn_assert_not_reached("This orbit is not handled"); break; + default: cgogn_assert_not_reached("Orbit not supported in a CMap1"); break; } } @@ -379,9 +374,6 @@ class CMap1_T : public CMap0_T static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); - static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1, - "Orbit not supported in a CMap1"); - switch (ORBIT) { case Orbit::DART: this->foreach_dart_of_DART(c, f); break; @@ -392,7 +384,7 @@ class CMap1_T : public CMap0_T case Orbit::PHI2_PHI3: case Orbit::PHI21: case Orbit::PHI21_PHI31: - default: cgogn_assert_not_reached("This orbit is not handled"); break; + default: cgogn_assert_not_reached("Orbit not supported in a CMap1"); break; } } @@ -407,7 +399,7 @@ class CMap1_T : public CMap0_T { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); - foreach_dart_of_orbit(f, func); + foreach_dart_of_orbit(f, func); } }; @@ -425,10 +417,10 @@ extern template class CGOGN_CORE_API CMap1_T>; extern template class CGOGN_CORE_API DartMarkerStore>; extern template class CGOGN_CORE_API DartMarkerNoUnmark>; -extern template class CGOGN_CORE_API CellMarker, Orbit::DART>; -extern template class CGOGN_CORE_API CellMarker, Orbit::PHI1>; -extern template class CGOGN_CORE_API CellMarkerStore, Orbit::DART>; -extern template class CGOGN_CORE_API CellMarkerStore, Orbit::PHI1>; +extern template class CGOGN_CORE_API CellMarker, Vertex::ORBIT>; +extern template class CGOGN_CORE_API CellMarker, Face::ORBIT>; +extern template class CGOGN_CORE_API CellMarkerStore, Vertex::ORBIT>; +extern template class CGOGN_CORE_API CellMarkerStore, Face::ORBIT>; #endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_MAP_MAP1_CPP_)) } // namespace cgogn diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 6209509c..12c4bc81 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -39,6 +39,8 @@ class CMap2_T : public CMap1_T { public: + static const int PRIM_SIZE = 1; + typedef MAP_TRAITS MapTraits; typedef MAP_TYPE MapType; typedef CMap1_T Inherit; @@ -49,8 +51,6 @@ class CMap2_T : public CMap1_T template friend class DartMarker_T; template friend class DartMarkerStore; - static const int PRIM_SIZE = 1; - // static const Orbit DART = Orbit::DART; static const Orbit VERTEX = Orbit::PHI21; static const Orbit EDGE = Orbit::PHI2; @@ -71,13 +71,13 @@ class CMap2_T : public CMap1_T template using AttributeHandler = typename Inherit::template AttributeHandler; template - using VertexAttributeHandler = AttributeHandler; + using VertexAttributeHandler = AttributeHandler; template - using EdgeAttributeHandler = AttributeHandler; + using EdgeAttributeHandler = AttributeHandler; template - using FaceAttributeHandler = AttributeHandler; + using FaceAttributeHandler = AttributeHandler; template - using VolumeAttributeHandler = AttributeHandler; + using VolumeAttributeHandler = AttributeHandler; using DartMarker = typename cgogn::DartMarker; using DartMarkerStore = typename cgogn::DartMarkerStore; @@ -205,42 +205,45 @@ class CMap2_T : public CMap1_T * The returned dart is the dart of the inserted vertex that belongs to the face of d. * If the map has Dart, Vertex, Edge, Face or Volume attributes, * the inserted darts are automatically embedded on new attribute elements. - * Actually a Vertex attribute is created, if needed, for the inserted vertex. + * - Actually a Vertex attribute is created, if needed, for the inserted vertex. + * - If needed, an Edge attribute is created for the edge inserted after e. + * The Edge attribute of e is kept unchanged. */ inline Vertex cut_edge(Edge e) { CGOGN_CHECK_CONCRETE_TYPE; const CDart ne = cut_edge_topo(e); - const CDart nf = this->phi1(phi2(e)); + const CDart nf = phi2(e); + const CDart f = phi2(ne); - if (this->template is_orbit_embedded()) { + if (this->template is_embedded()) { this->new_embedding(ne); this->new_embedding(nf); } - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) { const unsigned int idx = this->new_embedding(Vertex(ne)); this->set_embedding(Vertex(nf), idx); } - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) { this->copy_embedding(Edge(nf), e); this->new_orbit_embedding(Edge(ne)); } - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) { - this->copy_embedding(Face(ne), Face(e.dart)); - this->copy_embedding(Face(nf), Face(this->phi_1(nf))); + this->copy_embedding(Face(ne), Face(e)); + this->copy_embedding(Face(nf), Face(f)); } - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) { - const unsigned int idx = this->new_embedding(Volume(ne)); - this->set_embedding(Volume(nf), idx); + this->copy_embedding(Volume(ne),Volume(e)); + this->copy_embedding(Volume(nf), Volume(e)); } return Vertex(ne); @@ -303,29 +306,29 @@ class CMap2_T : public CMap1_T CDart nd = this->phi_1(d); CDart ne = this->phi_1(e); - if (this->template is_orbit_embedded()) { + if (this->template is_embedded()) { this->new_embedding(nd); this->new_embedding(ne); } - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) { this->copy_embedding(Vertex(nd.dart), e); this->copy_embedding(Vertex(ne.dart), d); } - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) { this->new_orbit_embedding(Edge(nd.dart)); } - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) { this->copy_embedding(Face(nd.dart), Face(d.dart)); this->new_orbit_embedding(Face(ne.dart)); } - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) { unsigned int idx = this->copy_embedding(Volume(nd.dart), Volume(d.dart)); this->set_embedding(Volume(ne), idx); @@ -371,28 +374,28 @@ class CMap2_T : public CMap1_T Face f = add_face_topo(size); - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) foreach_dart_of_orbit(f, [this] (CDart d) { this->new_embedding(d); }); - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) foreach_dart_of_orbit(f, [this] (Vertex v) { this->new_embedding(v); }); - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) foreach_dart_of_orbit(f, [this] (Edge e) { this->new_embedding(e); }); - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) this->new_embedding(f); - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) this->new_orbit_embedding(Volume(f.dart)); return f; @@ -448,29 +451,29 @@ class CMap2_T : public CMap1_T this->template new_embedding(d); }); - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) foreach_dart_of_orbit(new_face, [this] (Dart fd) { - this->template copy_embedding(fd, this->phi1(phi2(fd))); + this->template copy_embedding(fd, this->phi1(phi2(fd))); }); - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) foreach_dart_of_orbit(new_face, [this] (Dart fd) { - this->template copy_embedding(fd, phi2(fd)); + this->template copy_embedding(fd, phi2(fd)); }); - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) { this->template new_orbit_embedding(new_face); } - if (this->template is_orbit_embedded()) + if (this->template is_orbit_embedded()) { - const unsigned int idx = this->template get_embedding(d); + const unsigned int idx = this->template get_embedding(d); foreach_dart_of_orbit(new_face, [this, idx] (Dart fd) { - this->template set_embedding(fd, idx); + this->template set_embedding(fd, idx); }); } } @@ -545,10 +548,6 @@ class CMap2_T : public CMap1_T template inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const { - static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || ORBIT == Orbit::PHI2 || - ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21, - "Orbit not supported in a CMap2"); - switch (ORBIT) { case Orbit::DART: this->foreach_dart_of_DART(c, f); break; @@ -623,10 +622,6 @@ class CMap2_T : public CMap1_T static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); - static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || ORBIT == Orbit::PHI2 || - ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21, - "Orbit not supported in a CMap2"); - switch (ORBIT) { case Orbit::DART: this->foreach_dart_of_DART(c, f); break; @@ -647,185 +642,94 @@ class CMap2_T : public CMap1_T public: - template - inline void foreach_incident_cell(Cell c, const FUNC& f) const - { - static_assert(check_func_parameter_type(FUNC, Cell), - "Wrong function cell parameter type"); - - static_assert((ORBIT_IN == Orbit::PHI21 && ORBIT_OUT == Orbit::PHI2) || - (ORBIT_IN == Orbit::PHI21 && ORBIT_OUT == Orbit::PHI1) || - (ORBIT_IN == Orbit::PHI2 && ORBIT_OUT == Orbit::PHI21) || - (ORBIT_IN == Orbit::PHI2 && ORBIT_OUT == Orbit::PHI1) || - (ORBIT_IN == Orbit::PHI1 && ORBIT_OUT == Orbit::PHI21) || - (ORBIT_IN == Orbit::PHI1 && ORBIT_OUT == Orbit::PHI2) || - (ORBIT_IN == Orbit::PHI1_PHI2 && ORBIT_OUT == Orbit::PHI21) || - (ORBIT_IN == Orbit::PHI1_PHI2 && ORBIT_OUT == Orbit::PHI2) || - (ORBIT_IN == Orbit::PHI1_PHI2 && ORBIT_OUT == Orbit::PHI1), - "Invalid incidence relation"); - - if (ORBIT_IN == Orbit::PHI1_PHI2) { - DartMarkerStore marker(*this); - foreach_dart_of_orbit(c, [&] (Dart d) - { - if (!marker.is_marked(d)) - { - marker.template mark_orbit(d); - f(Cell(d)); - } - }); - } - else { - foreach_dart_of_orbit(c, [&] (Dart d) - { - f(Cell(d)); - }); - } + template + inline void foreach_incident_edge(Vertex v, const FUNC& f) const + { + static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); + foreach_dart_of_orbit(v, f); } - template - inline void foreach_incident_vertex(Cell c, const FUNC& f) const + template + inline void foreach_incident_face(Vertex v, const FUNC& f) const { - foreach_incident_cell(c, f); + static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); + foreach_dart_of_orbit(v, f); } - template - inline void foreach_incident_edge(Cell c, const FUNC& f) const + template + inline void foreach_incident_vertex(Edge e, const FUNC& f) const { - foreach_incident_cell(c, f); + static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); + f(e.dart); + f(phi2(e.dart)); } - template - inline void foreach_incident_face(Cell c, const FUNC& f) const + template + inline void foreach_incident_face(Edge e, const FUNC& f) const { - foreach_incident_cell(c, f); + static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); + f(e.dart); + f(phi2(e.dart)); } - template - inline void foreach_incident_volume(Cell c, const FUNC& f) const + template + inline void foreach_incident_vertex(Face f, const FUNC& func) const { - foreach_incident_cell(c, f); + static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); + foreach_dart_of_orbit(f, func); } - /*! - * Idem + assure l'unicité en cas de multi-incidence - */ - template - inline void foreach_unique_incident_cell(Cell c, const FUNC& f) const - { - static_assert(check_func_parameter_type(FUNC, Cell), - "Wrong function cell parameter type"); - - static_assert((ORBIT_IN == Orbit::PHI21 && ORBIT_OUT == Orbit::PHI2) || - (ORBIT_IN == Orbit::PHI21 && ORBIT_OUT == Orbit::PHI1) || - (ORBIT_IN == Orbit::PHI2 && ORBIT_OUT == Orbit::PHI21) || - (ORBIT_IN == Orbit::PHI2 && ORBIT_OUT == Orbit::PHI1) || - (ORBIT_IN == Orbit::PHI1 && ORBIT_OUT == Orbit::PHI21) || - (ORBIT_IN == Orbit::PHI1 && ORBIT_OUT == Orbit::PHI2) || - (ORBIT_IN == Orbit::PHI1_PHI2 && ORBIT_OUT == Orbit::PHI21) || - (ORBIT_IN == Orbit::PHI1_PHI2 && ORBIT_OUT == Orbit::PHI2) || - (ORBIT_IN == Orbit::PHI1_PHI2 && ORBIT_OUT == Orbit::PHI1), - "Invalid incidence relation"); + template + inline void foreach_incident_edge(Face f, const FUNC& func) const + { + static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); + foreach_dart_of_orbit(f, func); + } + template + inline void foreach_incident_vertex(Volume v, const FUNC& f) const + { + static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); DartMarkerStore marker(*this); - foreach_dart_of_orbit(c, [&] (Dart d) + foreach_dart_of_orbit(v, [&] (Dart d) { if (!marker.is_marked(d)) { - marker.template mark_orbit(d); - f(Cell(d)); + marker.template mark_orbit(d); + f(d); } }); } -// template -// inline void foreach_incident_edge(Vertex v, const FUNC& f) const -// { -// static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); -// foreach_dart_of_orbit(v, f); -// } - -// template -// inline void foreach_incident_face(Vertex v, const FUNC& f) const -// { -// static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); -// foreach_dart_of_orbit(v, f); -// } - -// template -// inline void foreach_incident_vertex(Edge e, const FUNC& f) const -// { -// static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); -// f(e.dart); -// f(phi2(e.dart)); -// } - -// template -// inline void foreach_incident_face(Edge e, const FUNC& f) const -// { -// static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); -// f(e.dart); -// f(phi2(e.dart)); -// } - -// template -// inline void foreach_incident_vertex(Face f, const FUNC& func) const -// { -// static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); -// foreach_dart_of_orbit(f, func); -// } - -// template -// inline void foreach_incident_edge(Face f, const FUNC& func) const -// { -// static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); -// foreach_dart_of_orbit(f, func); -// } - -// template -// inline void foreach_incident_vertex(Volume v, const FUNC& f) const -// { -// static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); -// DartMarkerStore marker(*this); -// foreach_dart_of_orbit(v, [&] (Dart d) -// { -// if (!marker.is_marked(d)) -// { -// marker.template mark_orbit(d); -// f(d); -// } -// }); -// } - -// template -// inline void foreach_incident_edge(Volume v, const FUNC& f) const -// { -// static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); -// DartMarkerStore marker(*this); -// foreach_dart_of_orbit(v, [&] (Dart d) -// { -// if (!marker.is_marked(d)) -// { -// marker.template mark_orbit(d); -// f(d); -// } -// }); -// } - -// template -// inline void foreach_incident_face(Volume v, const FUNC& f) const -// { -// static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); -// DartMarkerStore marker(*this); -// foreach_dart_of_orbit(v, [&] (Dart d) -// { -// if (!marker.is_marked(d)) -// { -// marker.template mark_orbit(d); -// f(d); -// } -// }); -// } + template + inline void foreach_incident_edge(Volume v, const FUNC& f) const + { + static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); + DartMarkerStore marker(*this); + foreach_dart_of_orbit(v, [&] (Dart d) + { + if (!marker.is_marked(d)) + { + marker.template mark_orbit(d); + f(d); + } + }); + } + + template + inline void foreach_incident_face(Volume v, const FUNC& f) const + { + static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); + DartMarkerStore marker(*this); + foreach_dart_of_orbit(v, [&] (Dart d) + { + if (!marker.is_marked(d)) + { + marker.template mark_orbit(d); + f(d); + } + }); + } /******************************************************************************* * Adjacence traversal @@ -845,7 +749,7 @@ class CMap2_T : public CMap1_T foreach_dart_of_orbit(v, [this, &f] (Dart vd) { Dart vd1 = this->phi1(vd); - this->foreach_dart_of_orbit(vd, [&f, vd, vd1] (Dart fd) + this->foreach_dart_of_orbit(vd, [&f, vd, vd1] (Dart fd) { // skip Vertex v itself and its first successor around current face if (fd != vd && fd != vd1) @@ -860,7 +764,7 @@ class CMap2_T : public CMap1_T static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); foreach_dart_of_orbit(e, [&f, this] (Dart ed) { - this->foreach_dart_of_orbit(ed, [&f, ed] (Dart vd) + this->foreach_dart_of_orbit(ed, [&f, ed] (Dart vd) { // skip Edge e itself if (vd != ed) @@ -875,7 +779,7 @@ class CMap2_T : public CMap1_T static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); foreach_dart_of_orbit(e, [&f, this] (Dart ed) { - this->foreach_dart_of_orbit(ed, [&f, ed] (Dart fd) + this->foreach_dart_of_orbit(ed, [&f, ed] (Dart fd) { // skip Edge e itself if (fd != ed) @@ -891,7 +795,7 @@ class CMap2_T : public CMap1_T foreach_dart_of_orbit(f, [this, &func] (Dart fd) { Dart fd1 = this->phi2(this->phi_1(fd)); - this->foreach_dart_of_orbit(fd, [&func, fd, fd1] (Dart vd) + this->foreach_dart_of_orbit(fd, [&func, fd, fd1] (Dart vd) { // skip Face f itself and its first successor around current vertex if (vd != fd && vd != fd1) @@ -922,14 +826,14 @@ extern template class CGOGN_CORE_API CMap2_T>; extern template class CGOGN_CORE_API DartMarkerStore>; extern template class CGOGN_CORE_API DartMarkerNoUnmark>; -extern template class CGOGN_CORE_API CellMarker, Orbit::PHI21>; -extern template class CGOGN_CORE_API CellMarker, Orbit::PHI2>; -extern template class CGOGN_CORE_API CellMarker, Orbit::PHI1>; -extern template class CGOGN_CORE_API CellMarker, Orbit::PHI1_PHI2>; -extern template class CGOGN_CORE_API CellMarkerStore, Orbit::PHI21>; -extern template class CGOGN_CORE_API CellMarkerStore, Orbit::PHI2>; -extern template class CGOGN_CORE_API CellMarkerStore, Orbit::PHI1>; -extern template class CGOGN_CORE_API CellMarkerStore, Orbit::PHI1_PHI2>; +extern template class CGOGN_CORE_API CellMarker, Vertex::ORBIT>; +extern template class CGOGN_CORE_API CellMarker, Edge::ORBIT>; +extern template class CGOGN_CORE_API CellMarker, Face::ORBIT>; +extern template class CGOGN_CORE_API CellMarker, Volume::ORBIT>; +extern template class CGOGN_CORE_API CellMarkerStore, Vertex::ORBIT>; +extern template class CGOGN_CORE_API CellMarkerStore, Edge::ORBIT>; +extern template class CGOGN_CORE_API CellMarkerStore, Face::ORBIT>; +extern template class CGOGN_CORE_API CellMarkerStore, Volume::ORBIT>; #endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_MAP_MAP2_CPP_)) } // namespace cgogn diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index e5eb3ea2..3e4ae798 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -246,6 +246,13 @@ class MapBaseData : public MapGen return embeddings_[ORBIT] != nullptr; } + template + inline bool is_embedded() const + { + static_assert(Cell::ORBIT < NB_ORBITS, "Unknown orbit parameter"); + return embeddings_[Cell::ORBIT] != nullptr; + } + template inline unsigned int get_embedding(Cell c) const { diff --git a/cgogn/core/examples/map/map.cpp b/cgogn/core/examples/map/map.cpp index 76b0ff2e..21d0db5d 100644 --- a/cgogn/core/examples/map/map.cpp +++ b/cgogn/core/examples/map/map.cpp @@ -57,12 +57,12 @@ template int test1(MAP& map) { // add an attribute on vertex of map with - typename MAP::template VertexAttributeHandler ah = map.template add_attribute("floats"); + typename MAP::template VertexAttributeHandler ah = map.template add_attribute("floats"); - typename MAP::template FaceAttributeHandler ahf = map.template add_attribute("floats"); + typename MAP::template FaceAttributeHandler ahf = map.template add_attribute("floats"); // get attribute and change type (dangerous!) - typename MAP::template VertexAttributeHandler ahf2 = map.template get_attribute_force_type("floats"); + typename MAP::template VertexAttributeHandler ahf2 = map.template get_attribute_force_type("floats"); map.remove_attribute(ahf); std::cout << "ahf valid : " << std::boolalpha << ahf.is_valid() << std::endl; @@ -88,7 +88,7 @@ int test1(MAP& map) // cgogn::get_dart_buffers()->release_cell_buffer(vert_b); DartMarker dm(map); - CellMarker cm(map); + CellMarker cm(map); dm.mark(d1); @@ -138,7 +138,7 @@ int main() Map1 map1; Map2 map2; // Map3 map3; - test1(map1); +// test1(map1); test1(map2); // test1(map3); diff --git a/cgogn/core/tests/cmap/cmap1_test.cpp b/cgogn/core/tests/cmap/cmap1_test.cpp index cd25926d..d0989316 100644 --- a/cgogn/core/tests/cmap/cmap1_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_test.cpp @@ -54,9 +54,9 @@ TEST_F(CMap1Test, addFace) cmap_.split_vertex(Vertex(f.dart)); - EXPECT_TRUE(is_well_embedded(cmap_)); - EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); - EXPECT_TRUE(is_container_well_referenced(cmap_)); + EXPECT_TRUE(is_well_embedded(cmap_)); + EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); + EXPECT_TRUE(is_container_well_referenced(cmap_)); } diff --git a/cgogn/geometry/algos/normal.h b/cgogn/geometry/algos/normal.h index 2bb76b8f..6f4d82b7 100644 --- a/cgogn/geometry/algos/normal.h +++ b/cgogn/geometry/algos/normal.h @@ -82,8 +82,7 @@ inline VEC3 vertex_normal(const MAP& map, Cell v, const typename M VEC3 n{0,0,0}; const VEC3& p = position[v.dart]; -// map.foreach_incident_face(v, [&] (Cell f) - map.template foreach_incident_cell(v, [&] (Cell f) + map.foreach_incident_face(v, [&] (Cell f) { VEC3 facen = face_normal(map, f, position); const VEC3& p1 = position[map.phi1(f.dart)]; @@ -104,8 +103,7 @@ inline VEC3 vertex_normal(const MAP& map, Cell v, const typename M VEC3 n{0,0,0}; const VEC3& p = position[v.dart]; -// map.foreach_incident_face(v, [&] (Cell f) - map.template foreach_incident_cell(v, [&] (Cell f) + map.foreach_incident_face(v, [&] (Cell f) { VEC3 facen = fnormal[f]; const VEC3& p1 = position[map.phi1(f.dart)]; diff --git a/cgogn/io/examples/cmap2_import.cpp b/cgogn/io/examples/cmap2_import.cpp index 3b6a4aa3..eca85c62 100644 --- a/cgogn/io/examples/cmap2_import.cpp +++ b/cgogn/io/examples/cmap2_import.cpp @@ -60,23 +60,23 @@ int main(int argc, char** argv) std::cout << "nb darts // -> " << nb_darts_2 << std::endl; - VertexAttributeHandler vertex_position = map.get_attribute("position"); - VertexAttributeHandler vertex_normal = map.add_attribute("normal"); - FaceAttributeHandler face_normal = map.add_attribute("normal"); + VertexAttributeHandler vertex_position = map.get_attribute("position"); + VertexAttributeHandler vertex_normal = map.add_attribute("normal"); + FaceAttributeHandler face_normal = map.add_attribute("normal"); - map.enable_topo_cache(); - map.enable_topo_cache(); - map.enable_topo_cache(); + map.enable_topo_cache(); + map.enable_topo_cache(); + map.enable_topo_cache(); - std::cout << "Vertex orbits are well embedded ? -> " << std::boolalpha << cgogn::is_well_embedded(map) << std::endl; - std::cout << "Face orbits are well embedded ? -> " << std::boolalpha << cgogn::is_well_embedded(map) << std::endl; + std::cout << "Vertex orbits are well embedded ? -> " << std::boolalpha << cgogn::is_well_embedded(map) << std::endl; + std::cout << "Face orbits are well embedded ? -> " << std::boolalpha << cgogn::is_well_embedded(map) << std::endl; - std::cout << "Vertex orbit is uniquely embedded ? -> " << std::boolalpha << cgogn::is_orbit_embedding_unique(map) << std::endl; - std::cout << "Face orbit is uniquely embedded ? -> " << std::boolalpha << cgogn::is_orbit_embedding_unique(map) << std::endl; + std::cout << "Vertex orbit is uniquely embedded ? -> " << std::boolalpha << cgogn::is_orbit_embedding_unique(map) << std::endl; + std::cout << "Face orbit is uniquely embedded ? -> " << std::boolalpha << cgogn::is_orbit_embedding_unique(map) << std::endl; - std::cout << "Vertex container is well referenced ? -> " << std::boolalpha << cgogn::is_container_well_referenced(map) << std::endl; - std::cout << "Face container is well referenced ? -> " << std::boolalpha << cgogn::is_container_well_referenced(map) << std::endl; + std::cout << "Vertex container is well referenced ? -> " << std::boolalpha << cgogn::is_container_well_referenced(map) << std::endl; + std::cout << "Face container is well referenced ? -> " << std::boolalpha << cgogn::is_container_well_referenced(map) << std::endl; unsigned int nb_faces = 0; diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index b2d9f1a9..54c8edcb 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -153,7 +153,7 @@ class SurfaceImport void create_map(Map& map) { using MapBuilder = cgogn::CMap2Builder_T; - const Orbit VERTEX = Map::Vertex::SELF_ORBIT; + const Orbit VERTEX = Map::Vertex::ORBIT; if (this->nb_vertices_ == 0u) return; From 345abbb7b6c33f62deb3ca87f959c8a91e082d7a Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Mon, 22 Feb 2016 14:38:51 +0100 Subject: [PATCH 130/402] import ply --- cgogn/io/CMakeLists.txt | 6 +- cgogn/io/import_ply_data.cpp | 242 +++ cgogn/io/import_ply_data.h | 136 ++ cgogn/io/ply.c | 3435 ++++++++++++++++++++++++++++++++++ cgogn/io/ply.h | 257 +++ cgogn/io/surface_import.h | 87 +- 6 files changed, 4159 insertions(+), 4 deletions(-) create mode 100644 cgogn/io/import_ply_data.cpp create mode 100644 cgogn/io/import_ply_data.h create mode 100644 cgogn/io/ply.c create mode 100644 cgogn/io/ply.h diff --git a/cgogn/io/CMakeLists.txt b/cgogn/io/CMakeLists.txt index e7344115..0a066d3e 100644 --- a/cgogn/io/CMakeLists.txt +++ b/cgogn/io/CMakeLists.txt @@ -1,5 +1,5 @@ project(cgogn_io - LANGUAGES CXX + LANGUAGES CXX C ) set(HEADER_FILES @@ -7,12 +7,16 @@ set(HEADER_FILES volume_import.h map_import.h map_export.h + ply.h + import_ply_data.h dll.h ) set(SOURCE_FILES surface_import.cpp volume_import.cpp + ply.c + import_ply_data.cpp ) add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) diff --git a/cgogn/io/import_ply_data.cpp b/cgogn/io/import_ply_data.cpp new file mode 100644 index 00000000..0bb63f10 --- /dev/null +++ b/cgogn/io/import_ply_data.cpp @@ -0,0 +1,242 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ +#define CGOGN_IO_DLL_EXPORT +#define IO_IMPORT_PLY_DATA_CPP_ + +#include +#include +#include +#include + + +namespace cgogn +{ + +namespace io +{ + +char* PlyImportData::elem_names[] = { /* list of the elements in the object */ + (char*) "vertex", (char*) "face" + }; + +PlyProperty PlyImportData::vert_props[] = { /* list of property information for a vertex */ + {(char*) "x", PLY_Float32, PLY_Float32, offsetof(VertexPly,x), 0, 0, 0, 0}, + {(char*) "y", PLY_Float32, PLY_Float32, offsetof(VertexPly,y), 0, 0, 0, 0}, + {(char*) "z", PLY_Float32, PLY_Float32, offsetof(VertexPly,z), 0, 0, 0, 0}, + {(char*) "red", PLY_Uint8, PLY_Uint8, offsetof(VertexPly,red), 0, 0, 0, 0}, + {(char*) "green", PLY_Uint8, PLY_Uint8, offsetof(VertexPly,green), 0, 0, 0, 0}, + {(char*) "blue", PLY_Uint8, PLY_Uint8, offsetof(VertexPly,blue), 0, 0, 0, 0}, + {(char*) "r", PLY_Float32, PLY_Float32, offsetof(VertexPly,r), 0, 0, 0, 0}, + {(char*) "g", PLY_Float32, PLY_Float32, offsetof(VertexPly,g), 0, 0, 0, 0}, + {(char*) "b", PLY_Float32, PLY_Float32, offsetof(VertexPly,b), 0, 0, 0, 0}, + {(char*) "nx", PLY_Float32, PLY_Float32, offsetof(VertexPly,nx), 0, 0, 0, 0}, + {(char*) "ny", PLY_Float32, PLY_Float32, offsetof(VertexPly,ny), 0, 0, 0, 0}, + {(char*) "nz", PLY_Float32, PLY_Float32, offsetof(VertexPly,nz), 0, 0, 0, 0}, + }; + +PlyProperty PlyImportData::face_props[] = { /* list of property information for a face */ + {(char*) "vertex_indices", PLY_Int32, PLY_Int32, offsetof(FacePly,verts), + 1, PLY_Uint8, PLY_Uint8, offsetof(FacePly,nverts)}, + }; + + +PlyImportData::PlyImportData(): + nverts(0),nfaces(0), + vlist(NULL), + flist(NULL), + vert_other(NULL), + face_other(NULL), + per_vertex_color_float32(0), + per_vertex_color_uint8(0), + has_normals_(0) +{ + old_locale = setlocale(LC_NUMERIC, NULL); + setlocale(LC_NUMERIC, "C"); +} + +PlyImportData::~PlyImportData() +{ +// if (vlist!= NULL) +// { +// for (int i=0; i> tag; + } while ((tag != std::string("format")) && (tag != std::string("FORMAT"))); + fs >> tag; + + fs.close(); + + if ((tag == std::string("ascii")) || (tag == std::string("ASCII"))) + fp = fopen(filename.c_str(), "r"); + else + fp = fopen(filename.c_str(), "rb"); + + + /*** Read in the original PLY object ***/ + + if (fp==NULL) + return false; + + PlyFile *in_ply = read_ply (fp); + if (in_ply==NULL) + return false; + + for (int i = 0; i < in_ply->num_elem_types; i++) + { + int elem_count; + /* prepare to read the i'th list of elements */ + char *elem_name = setup_element_read_ply (in_ply, i, &elem_count); + + if (equal_strings ((char*) "vertex", elem_name)) { + + /* create a vertex list to hold all the vertices */ + vlist = (VertexPly **) malloc (sizeof (VertexPly *) * elem_count); + nverts = elem_count; + + /* set up for getting vertex elements */ + + setup_property_ply (in_ply, &vert_props[0]); + setup_property_ply (in_ply, &vert_props[1]); + setup_property_ply (in_ply, &vert_props[2]); + + for (int j = 0; j < in_ply->elems[i]->nprops; j++) + { + PlyProperty *prop; + prop = in_ply->elems[i]->props[j]; + if (equal_strings ((char*) "red", prop->name)) { + setup_property_ply (in_ply, &vert_props[3]); + per_vertex_color_uint8 = 1; + } + if (equal_strings ((char*) "green", prop->name)) { + setup_property_ply (in_ply, &vert_props[4]); + per_vertex_color_uint8 = 1; + } + if (equal_strings ((char*) "blue", prop->name)) { + setup_property_ply (in_ply, &vert_props[5]); + per_vertex_color_uint8 = 1; + } + if (equal_strings ((char*) "r", prop->name)) { + setup_property_ply (in_ply, &vert_props[6]); + per_vertex_color_float32 = 1; + } + if (equal_strings ((char*) "g", prop->name)) { + setup_property_ply (in_ply, &vert_props[7]); + per_vertex_color_float32 = 1; + } + if (equal_strings ((char*) "b", prop->name)) { + setup_property_ply (in_ply, &vert_props[8]); + per_vertex_color_float32 = 1; + } + if (equal_strings ((char*) "nx", prop->name)) { + setup_property_ply (in_ply, &vert_props[9]); + has_normals_ = 1; + } + if (equal_strings ((char*) "ny", prop->name)) { + setup_property_ply (in_ply, &vert_props[10]); + has_normals_ = 1; + } + if (equal_strings ((char*) "nz", prop->name)) { + setup_property_ply (in_ply, &vert_props[11]); + has_normals_ = 1; + } + } + + vert_other = get_other_properties_ply (in_ply, + offsetof(VertexPly,other_props)); + + /* grab all the vertex elements */ + for (int j = 0; j < elem_count; j++) { + vlist[j] = (VertexPly *) malloc (sizeof (VertexPly)); + vlist[j]->r = 1; + vlist[j]->g = 1; + vlist[j]->b = 1; + get_element_ply (in_ply, (void *) vlist[j]); + } + } + else if (equal_strings ((char*) "face", elem_name)) { + + /* create a list to hold all the face elements */ + flist = (FacePly **) malloc (sizeof (FacePly *) * elem_count); + nfaces = elem_count; + + /* set up for getting face elements */ + + setup_property_ply (in_ply, &face_props[0]); + face_other = get_other_properties_ply (in_ply, + offsetof(FacePly,other_props)); + + /* grab all the face elements */ + for (int j = 0; j < elem_count; j++) { + flist[j] = (FacePly *) malloc (sizeof (FacePly)); + get_element_ply (in_ply, (void *) flist[j]); + } + } + else + get_other_element_ply (in_ply); + } + + close_ply (in_ply); + + free_ply (in_ply); + + return true; +} + +} // namespace io + +} // namespace cgogn diff --git a/cgogn/io/import_ply_data.h b/cgogn/io/import_ply_data.h new file mode 100644 index 00000000..7984cb5e --- /dev/null +++ b/cgogn/io/import_ply_data.h @@ -0,0 +1,136 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* version 0.1 * +* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef _IMPORT_PLY_DATA_H +#define _IMPORT_PLY_DATA_H + +#include +#include +#include + +#include +#include + +namespace cgogn +{ + +namespace io +{ + +class CGOGN_IO_API PlyImportData +{ +public: + + template + void vertex_position(int i, VEC& P) { P[0] = vlist[i]->x; P[1] = vlist[i]->y; P[2] = vlist[i]->z;} + + template + void vertex_normal(int i, VEC& N) { N[0] = vlist[i]->nx; N[1] = vlist[i]->ny; N[2] = vlist[i]->nz;} + + template + void vertexColorUint8(int i, VEC& C) { C[0] = vlist[i]->red; C[1] = vlist[i]->green; C[2] = vlist[i]->blue;} + + template + void vertex_color_float32(int i, VEC& C) { C[0] = vlist[i]->r; C[1] = vlist[i]->g; C[2] = vlist[i]->b;} + + + inline int nb_vertices() { return nverts;} + + inline int nb_faces() { return nfaces;} + + /** + * each vertex has a normal vector + */ + inline bool has_normals() { return has_normals_!=0;} + + /** + * each vertex has a color vector + */ + bool has_colors() { return has_colors_uint8() || has_colors_float32() ;} + bool has_colors_uint8() { return per_vertex_color_uint8 != 0 ;} + bool has_colors_float32() { return per_vertex_color_float32 != 0 ;} + + /** + * get the number of edges of a face + */ + int get_face_valence(int i) { return flist[i]->nverts;} + + /** + * get a table (pointer) of int of vertex indices of + */ + int* get_face_indices(int i) { return flist[i]->verts;} + + PlyImportData(); + + ~PlyImportData(); + + bool read_file(const std::string& filename); + + +protected: + + /* vertex and face definitions for a polygonal object */ + + typedef struct VertexPly { + float x,y,z; + float r,g,b; + unsigned char red,green,blue; + float nx,ny,nz; + void *other_props; /* other properties */ + } VertexPly; + + typedef struct FacePly { + unsigned char nverts; /* number of vertex indices in list */ + int *verts; /* vertex index list */ + void *other_props; /* other properties */ + } FacePly; + + static char *elem_names[]; + + static PlyProperty vert_props[]; + + static PlyProperty face_props[]; + + + /*** the PLY object ***/ + + int nverts,nfaces; + VertexPly **vlist; + FacePly **flist; + + PlyOtherProp *vert_other,*face_other; + + int per_vertex_color_float32, per_vertex_color_uint8 ; + int has_normals_; + + char *old_locale; +}; + +} // namespace io + +} // namespace cgogn + + +#endif + diff --git a/cgogn/io/ply.c b/cgogn/io/ply.c new file mode 100644 index 00000000..23ae85fa --- /dev/null +++ b/cgogn/io/ply.c @@ -0,0 +1,3435 @@ +/* + +The interface routines for reading and writing PLY polygon files. + +Greg Turk + +--------------------------------------------------------------- + +A PLY file contains a single polygonal _object_. + +An object is composed of lists of _elements_. Typical elements are +vertices, faces, edges and materials. + +Each type of element for a given object has one or more _properties_ +associated with the element type. For instance, a vertex element may +have as properties the floating-point values x,y,z and the three unsigned +chars representing red, green and blue. + +----------------------------------------------------------------------- + +Copyright (c) 1998 Georgia Institute of Technology. All rights reserved. + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose is hereby granted without fee, provided +that the above copyright notice and this permission notice appear in +all copies of this software and that you do not sell the software. + +THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND, +EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY +WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +*/ + + +#ifdef WIN32 +#pragma warning(disable:4996) +#endif + +#include +#include +#include +#include + +#include "ply.h" + +char *type_names[] = { /* names of scalar types */ +"invalid", +"int8", "int16", "int32", "uint8", "uint16", "uint32", "float32", "float64", +}; + +char *old_type_names[] = { /* old names of types for backward compatability */ +"invalid", +"char", "short", "int", "uchar", "ushort", "uint", "float", "double", +}; + +int ply_type_size[] = { + 0, 1, 2, 4, 1, 2, 4, 4, 8 +}; + +#define NO_OTHER_PROPS -1 + +#define DONT_STORE_PROP 0 +#define STORE_PROP 1 + +#define OTHER_PROP 0 +#define NAMED_PROP 1 + +/* returns 1 if strings are equal, 0 if not */ +int equal_strings(char *, char *); + +/* find an element in a plyfile's list */ +PlyElement *find_element(PlyFile *, char *); + +/* find a property in an element's list */ +PlyProperty *find_property(PlyElement *, char *, int *); + +/* write to a file the word describing a PLY file data type */ +void write_scalar_type (FILE *, int); + +/* read a line from a file and break it up into separate words */ +char **get_words(FILE *, int *, char **); + +/* write an item to a file */ +void write_binary_item(FILE *, int, unsigned int, double, int); +void write_ascii_item(FILE *, int, unsigned int, double, int); + +/* add information to a PLY file descriptor */ +void add_element(PlyFile *, char **, int); +void add_property(PlyFile *, char **, int); +void add_comment(PlyFile *, char *); +void add_obj_info(PlyFile *, char *); + +/* copy a property */ +void copy_property(PlyProperty *, PlyProperty *); + +/* store a value into where a pointer and a type specify */ +void store_item(char *, int, int, unsigned int, double); + +/* return the value of a stored item */ +void get_stored_item( void *, int, int *, unsigned int *, double *); + +/* return the value stored in an item, given ptr to it and its type */ +double get_item_value(char *, int); + +/* get binary or ascii item and store it according to ptr and type */ +void get_ascii_item(char *, int, int *, unsigned int *, double *); +void get_binary_item(FILE *, int, int *, unsigned int *, double *, int); + +/* get a bunch of elements from a file */ +void ascii_get_element(PlyFile *, char *); +void binary_get_element(PlyFile *, char *); + +/* memory allocation */ +static char *my_alloc(int, int, char *); + + +/*************/ +/* Writing */ +/*************/ + + +/****************************************************************************** +Given a file pointer, get ready to write PLY data to the file. + +Entry: + fp - the given file pointer + nelems - number of elements in object + elem_names - list of element names + file_type - file type, either ascii or binary + +Exit: + returns a pointer to a PlyFile, used to refer to this file, or NULL if error +******************************************************************************/ + +PlyFile *ply_write( + FILE *fp, + int nelems, + char **elem_names, + int file_type +) +{ + int i; + PlyFile *plyfile; + PlyElement *elem; + + /* check for NULL file pointer */ + if (fp == NULL) + return (NULL); + + /* create a record for this object */ + + plyfile = (PlyFile *) myalloc (sizeof (PlyFile)); + plyfile->file_type = file_type; + plyfile->num_comments = 0; + plyfile->num_obj_info = 0; + plyfile->num_elem_types = nelems; + plyfile->version = 1.0; + plyfile->fp = fp; + plyfile->other_elems = NULL; + + /* tuck aside the names of the elements */ + + plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *) * nelems); + for (i = 0; i < nelems; i++) { + elem = (PlyElement *) myalloc (sizeof (PlyElement)); + plyfile->elems[i] = elem; + elem->name = strdup (elem_names[i]); + elem->num = 0; + elem->nprops = 0; + } + + /* return pointer to the file descriptor */ + return (plyfile); +} + + +/****************************************************************************** +Open a polygon file for writing. + +Entry: + filename - name of file to read from + nelems - number of elements in object + elem_names - list of element names + file_type - file type, either ascii or binary + +Exit: + returns a file identifier, used to refer to this file, or NULL if error +******************************************************************************/ + +PlyFile *open_for_writing_ply( + char *filename, + int nelems, + char **elem_names, + int file_type +) +{ +// int i; + PlyFile *plyfile; +// PlyElement *elem; + char *name; + FILE *fp; + + /* tack on the extension .ply, if necessary */ + + name = (char *) myalloc (sizeof (char) * (int)(strlen (filename) + 5)); + strcpy (name, filename); + if (strlen (name) < 4 || + strcmp (name + strlen (name) - 4, ".ply") != 0) + strcat (name, ".ply"); + + /* open the file for writing */ + + fp = fopen (name, "w"); + if (fp == NULL) { + return (NULL); + } + + /* create the actual PlyFile structure */ + + plyfile = ply_write (fp, nelems, elem_names, file_type); + if (plyfile == NULL) + return (NULL); + + /* return pointer to the file descriptor */ + return (plyfile); +} + + +/****************************************************************************** +Describe an element, including its properties and how many will be written +to the file. + +Entry: + plyfile - file identifier + elem_name - name of element that information is being specified about + nelems - number of elements of this type to be written + nprops - number of properties contained in the element + prop_list - list of properties +******************************************************************************/ + +void element_layout_ply( + PlyFile *plyfile, + char *elem_name, + int nelems, + int nprops, + PlyProperty *prop_list +) +{ + int i; + PlyElement *elem; + PlyProperty *prop; + + /* look for appropriate element */ + elem = find_element (plyfile, elem_name); + if (elem == NULL) { + fprintf(stderr,"element_layout_ply: can't find element '%s'\n",elem_name); + exit (-1); + } + + elem->num = nelems; + + /* copy the list of properties */ + + elem->nprops = nprops; + elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *) * nprops); + elem->store_prop = (char *) myalloc (sizeof (char) * nprops); + + for (i = 0; i < nprops; i++) { + prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); + elem->props[i] = prop; + elem->store_prop[i] = NAMED_PROP; + copy_property (prop, &prop_list[i]); + } +} + + +/****************************************************************************** +Describe a property of an element. + +Entry: + plyfile - file identifier + elem_name - name of element that information is being specified about + prop - the new property +******************************************************************************/ + +void ply_describe_property( + PlyFile *plyfile, + char *elem_name, + PlyProperty *prop +) +{ + PlyElement *elem; + PlyProperty *elem_prop; + + /* look for appropriate element */ + elem = find_element (plyfile, elem_name); + if (elem == NULL) { + fprintf(stderr, "ply_describe_property: can't find element '%s'\n", + elem_name); + return; + } + + /* create room for new property */ + + if (elem->nprops == 0) { + elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *)); + elem->store_prop = (char *) myalloc (sizeof (char)); + elem->nprops = 1; + } + else { + elem->nprops++; + elem->props = (PlyProperty **) + realloc (elem->props, sizeof (PlyProperty *) * elem->nprops); + elem->store_prop = (char *) + realloc (elem->store_prop, sizeof (char) * elem->nprops); + } + + /* copy the new property */ + + elem_prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); + elem->props[elem->nprops - 1] = elem_prop; + elem->store_prop[elem->nprops - 1] = NAMED_PROP; + copy_property (elem_prop, prop); +} + + +/****************************************************************************** +State how many of a given element will be written. + +Entry: + plyfile - file identifier + elem_name - name of element that information is being specified about + nelems - number of elements of this type to be written +******************************************************************************/ + +void element_count_ply( + PlyFile *plyfile, + char *elem_name, + int nelems +) +{ +// int i; + PlyElement *elem; +// PlyProperty *prop; + + /* look for appropriate element */ + elem = find_element (plyfile, elem_name); + if (elem == NULL) { + fprintf(stderr,"element_count_ply: can't find element '%s'\n",elem_name); + exit (-1); + } + + elem->num = nelems; +} + + +/****************************************************************************** +Signal that we've described everything a PLY file's header and that the +header should be written to the file. + +Entry: + plyfile - file identifier +******************************************************************************/ + +void header_complete_ply(PlyFile *plyfile) +{ + int i,j; + FILE *fp = plyfile->fp; + PlyElement *elem; + PlyProperty *prop; + + fprintf (fp, "ply\n"); + + switch (plyfile->file_type) { + case PLY_ASCII: + fprintf (fp, "format ascii 1.0\n"); + break; + case PLY_BINARY_BE: + fprintf (fp, "format binary_big_endian 1.0\n"); + break; + case PLY_BINARY_LE: + fprintf (fp, "format binary_little_endian 1.0\n"); + break; + default: + fprintf (stderr, "ply_header_complete: bad file type = %d\n", + plyfile->file_type); + exit (-1); + } + + /* write out the comments */ + + for (i = 0; i < plyfile->num_comments; i++) + fprintf (fp, "comment %s\n", plyfile->comments[i]); + + /* write out object information */ + + for (i = 0; i < plyfile->num_obj_info; i++) + fprintf (fp, "obj_info %s\n", plyfile->obj_info[i]); + + /* write out information about each element */ + + for (i = 0; i < plyfile->num_elem_types; i++) { + + elem = plyfile->elems[i]; + fprintf (fp, "element %s %d\n", elem->name, elem->num); + + /* write out each property */ + for (j = 0; j < elem->nprops; j++) { + prop = elem->props[j]; + if (prop->is_list == PLY_LIST) { + fprintf (fp, "property list "); + write_scalar_type (fp, prop->count_external); + fprintf (fp, " "); + write_scalar_type (fp, prop->external_type); + fprintf (fp, " %s\n", prop->name); + } + else if (prop->is_list == PLY_STRING) { + fprintf (fp, "property string"); + fprintf (fp, " %s\n", prop->name); + } + else { + fprintf (fp, "property "); + write_scalar_type (fp, prop->external_type); + fprintf (fp, " %s\n", prop->name); + } + } + } + + fprintf (fp, "end_header\n"); +} + + +/****************************************************************************** +Specify which elements are going to be written. This should be called +before a call to the routine ply_put_element(). + +Entry: + plyfile - file identifier + elem_name - name of element we're talking about +******************************************************************************/ + +void put_element_setup_ply(PlyFile *plyfile, char *elem_name) +{ + PlyElement *elem; + + elem = find_element (plyfile, elem_name); + if (elem == NULL) { + fprintf(stderr, "put_element_setup_ply: can't find element '%s'\n", elem_name); + exit (-1); + } + + plyfile->which_elem = elem; +} + + +/****************************************************************************** +Write an element to the file. This routine assumes that we're +writing the type of element specified in the last call to the routine +put_element_setup_ply(). + +Entry: + plyfile - file identifier + elem_ptr - pointer to the element +******************************************************************************/ + +void put_element_ply(PlyFile *plyfile, void *elem_ptr) +{ +// int i; + int j,k; + FILE *fp = plyfile->fp; + PlyElement *elem; + PlyProperty *prop; + char *item; + char *elem_data; + char **item_ptr; + int list_count; + int item_size; + int int_val; + unsigned int uint_val; + double double_val; + char **other_ptr; + + elem = plyfile->which_elem; + elem_data = (char *) elem_ptr; + other_ptr = (char **) (((char *) elem_ptr) + elem->other_offset); + + /* write out either to an ascii or binary file */ + + if (plyfile->file_type == PLY_ASCII) { + + /* write an ascii file */ + + /* write out each property of the element */ + for (j = 0; j < elem->nprops; j++) { + + prop = elem->props[j]; + + if (elem->store_prop[j] == OTHER_PROP) + elem_data = *other_ptr; + else + elem_data = (char *) elem_ptr; + + if (prop->is_list == PLY_LIST) { /* list */ + item = elem_data + prop->count_offset; + get_stored_item ((void *) item, prop->count_internal, + &int_val, &uint_val, &double_val); + write_ascii_item (fp, int_val, uint_val, double_val, + prop->count_external); + list_count = uint_val; + item_ptr = (char **) (elem_data + prop->offset); + item = item_ptr[0]; + item_size = ply_type_size[prop->internal_type]; + for (k = 0; k < list_count; k++) { + get_stored_item ((void *) item, prop->internal_type, + &int_val, &uint_val, &double_val); + write_ascii_item (fp, int_val, uint_val, double_val, + prop->external_type); + item += item_size; + } + } + else if (prop->is_list == PLY_STRING) { /* string */ + char **str; + item = elem_data + prop->offset; + str = (char **) item; + fprintf (fp, "\"%s\"", *str); + } + else { /* scalar */ + item = elem_data + prop->offset; + get_stored_item ((void *) item, prop->internal_type, + &int_val, &uint_val, &double_val); + write_ascii_item (fp, int_val, uint_val, double_val, + prop->external_type); + } + } + + fprintf (fp, "\n"); + } + else { + + /* write a binary file */ + + /* write out each property of the element */ + for (j = 0; j < elem->nprops; j++) { + prop = elem->props[j]; + if (elem->store_prop[j] == OTHER_PROP) + elem_data = *other_ptr; + else + elem_data = (char *) elem_ptr; + if (prop->is_list == PLY_LIST) { /* list */ + item = elem_data + prop->count_offset; + item_size = ply_type_size[prop->count_internal]; + get_stored_item ((void *) item, prop->count_internal, + &int_val, &uint_val, &double_val); + write_binary_item (fp, int_val, uint_val, double_val, + prop->count_external); + list_count = uint_val; + item_ptr = (char **) (elem_data + prop->offset); + item = item_ptr[0]; + item_size = ply_type_size[prop->internal_type]; + for (k = 0; k < list_count; k++) { + get_stored_item ((void *) item, prop->internal_type, + &int_val, &uint_val, &double_val); + write_binary_item (fp, int_val, uint_val, double_val, + prop->external_type); + item += item_size; + } + } + else if (prop->is_list == PLY_STRING) { /* string */ + int len; + char **str; + item = elem_data + prop->offset; + str = (char **) item; + + /* write the length */ + len = (int)(strlen(*str) + 1); + fwrite (&len, sizeof(int), 1, fp); + + /* write the string, including the null character */ + fwrite (*str, len, 1, fp); + } + else { /* scalar */ + item = elem_data + prop->offset; + item_size = ply_type_size[prop->internal_type]; + get_stored_item ((void *) item, prop->internal_type, + &int_val, &uint_val, &double_val); + write_binary_item (fp, int_val, uint_val, double_val, + prop->external_type); + } + } + + } +} + + + + + + +/*************/ +/* Reading */ +/*************/ + + + +/****************************************************************************** +Given a file pointer, get ready to read PLY data from the file. + +Entry: + fp - the given file pointer + +Exit: + nelems - number of elements in object + elem_names - list of element names + returns a pointer to a PlyFile, used to refer to this file, or NULL if error +******************************************************************************/ + +PlyFile *ply_read(FILE *fp, int *nelems, char ***elem_names) +{ + int i,j; + PlyFile *plyfile; + int nwords; + char **words; +// int found_format = 0; + char **elist; + PlyElement *elem; + char *orig_line; + + /* check for NULL file pointer */ + if (fp == NULL) + return (NULL); + + /* create record for this object */ + + plyfile = (PlyFile *) myalloc (sizeof (PlyFile)); + plyfile->num_elem_types = 0; + plyfile->comments = NULL; + plyfile->num_comments = 0; + plyfile->obj_info = NULL; + plyfile->num_obj_info = 0; + plyfile->fp = fp; + plyfile->other_elems = NULL; + plyfile->rule_list = NULL; + + /* read and parse the file's header */ + + words = get_words (plyfile->fp, &nwords, &orig_line); + if (!words || !equal_strings (words[0], "ply")) + return (NULL); + + while (words) { + + /* parse words */ + + if (equal_strings (words[0], "format")) { + if (nwords != 3) + return (NULL); + if (equal_strings (words[1], "ascii")) + plyfile->file_type = PLY_ASCII; + else if (equal_strings (words[1], "binary_big_endian")) + plyfile->file_type = PLY_BINARY_BE; + else if (equal_strings (words[1], "binary_little_endian")) + plyfile->file_type = PLY_BINARY_LE; + else + return (NULL); + plyfile->version = (float) atof (words[2]); +// found_format = 1; + } + else if (equal_strings (words[0], "element")) + add_element (plyfile, words, nwords); + else if (equal_strings (words[0], "property")) + add_property (plyfile, words, nwords); + else if (equal_strings (words[0], "comment")) + add_comment (plyfile, orig_line); + else if (equal_strings (words[0], "obj_info")) + add_obj_info (plyfile, orig_line); + else if (equal_strings (words[0], "end_header")) + break; + + /* free up words space */ + free (words); + + words = get_words (plyfile->fp, &nwords, &orig_line); + } + + + /* create tags for each property of each element, to be used */ + /* later to say whether or not to store each property for the user */ + + for (i = 0; i < plyfile->num_elem_types; i++) { + elem = plyfile->elems[i]; + elem->store_prop = (char *) myalloc (sizeof (char) * elem->nprops); + for (j = 0; j < elem->nprops; j++) + elem->store_prop[j] = DONT_STORE_PROP; + elem->other_offset = NO_OTHER_PROPS; /* no "other" props by default */ + } + + /* set return values about the elements */ + + elist = (char **) myalloc (sizeof (char *) * plyfile->num_elem_types); + for (i = 0; i < plyfile->num_elem_types; i++) + elist[i] = strdup (plyfile->elems[i]->name); + + *elem_names = elist; + *nelems = plyfile->num_elem_types; + + /* return a pointer to the file's information */ + + return (plyfile); +} + + +/****************************************************************************** +Open a polygon file for reading. + +Entry: + filename - name of file to read from + +Exit: + nelems - number of elements in object + elem_names - list of element names + file_type - file type, either ascii or binary + version - version number of PLY file + returns a file identifier, used to refer to this file, or NULL if error +******************************************************************************/ + +PlyFile *ply_open_for_reading( + char *filename, + int *nelems, + char ***elem_names, + int *file_type, + float *version +) +{ + FILE *fp; + PlyFile *plyfile; + char *name; + + /* tack on the extension .ply, if necessary */ + + name = (char *) myalloc (sizeof (char) * (int)(strlen (filename) + 5)); + strcpy (name, filename); + if (strlen (name) < 4 || + strcmp (name + strlen (name) - 4, ".ply") != 0) + strcat (name, ".ply"); + + /* open the file for reading */ + + fp = fopen (name, "r"); + if (fp == NULL) + return (NULL); + + /* create the PlyFile data structure */ + + plyfile = ply_read (fp, nelems, elem_names); + + /* determine the file type and version */ + + *file_type = plyfile->file_type; + *version = plyfile->version; + + /* return a pointer to the file's information */ + + return (plyfile); +} + + +/****************************************************************************** +Get information about a particular element. + +Entry: + plyfile - file identifier + elem_name - name of element to get information about + +Exit: + nelems - number of elements of this type in the file + nprops - number of properties + returns a list of properties, or NULL if the file doesn't contain that elem +******************************************************************************/ + +PlyProperty **get_element_description_ply( + PlyFile *plyfile, + char *elem_name, + int *nelems, + int *nprops +) +{ + int i; + PlyElement *elem; + PlyProperty *prop; + PlyProperty **prop_list; + + /* find information about the element */ + elem = find_element (plyfile, elem_name); + if (elem == NULL) + return (NULL); + + *nelems = elem->num; + *nprops = elem->nprops; + + /* make a copy of the element's property list */ + prop_list = (PlyProperty **) myalloc (sizeof (PlyProperty *) * elem->nprops); + for (i = 0; i < elem->nprops; i++) { + prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); + copy_property (prop, elem->props[i]); + prop_list[i] = prop; + } + + /* return this duplicate property list */ + return (prop_list); +} + + +/****************************************************************************** +Specify which properties of an element are to be returned. This should be +called before a call to the routine get_element_ply(). + +Entry: + plyfile - file identifier + elem_name - which element we're talking about + nprops - number of properties + prop_list - list of properties +******************************************************************************/ + +void get_element_setup_ply( + PlyFile *plyfile, + char *elem_name, + int nprops, + PlyProperty *prop_list +) +{ + int i; + PlyElement *elem; + PlyProperty *prop; + int index; + + /* find information about the element */ + elem = find_element (plyfile, elem_name); + plyfile->which_elem = elem; + + /* deposit the property information into the element's description */ + for (i = 0; i < nprops; i++) { + + /* look for actual property */ + prop = find_property (elem, prop_list[i].name, &index); + if (prop == NULL) { + fprintf (stderr, "Warning: Can't find property '%s' in element '%s'\n", + prop_list[i].name, elem_name); + continue; + } + + /* store its description */ + prop->internal_type = prop_list[i].internal_type; + prop->offset = prop_list[i].offset; + prop->count_internal = prop_list[i].count_internal; + prop->count_offset = prop_list[i].count_offset; + + /* specify that the user wants this property */ + elem->store_prop[index] = STORE_PROP; + } +} + + +/****************************************************************************** +Specify a property of an element that is to be returned. This should be +called (usually multiple times) before a call to the routine ply_get_element(). +This routine should be used in preference to the less flexible old routine +called ply_get_element_setup(). + +Entry: + plyfile - file identifier + elem_name - which element we're talking about + prop - property to add to those that will be returned +******************************************************************************/ + +void ply_get_property( + PlyFile *plyfile, + char *elem_name, + PlyProperty *prop +) +{ + PlyElement *elem; + PlyProperty *prop_ptr; + int index; + + /* find information about the element */ + elem = find_element (plyfile, elem_name); + plyfile->which_elem = elem; + + /* deposit the property information into the element's description */ + + prop_ptr = find_property (elem, prop->name, &index); + if (prop_ptr == NULL) { + fprintf (stderr, "Warning: Can't find property '%s' in element '%s'\n", + prop->name, elem_name); + return; + } + prop_ptr->internal_type = prop->internal_type; + prop_ptr->offset = prop->offset; + prop_ptr->count_internal = prop->count_internal; + prop_ptr->count_offset = prop->count_offset; + + /* specify that the user wants this property */ + elem->store_prop[index] = STORE_PROP; +} + + +/****************************************************************************** +Read one element from the file. This routine assumes that we're reading +the type of element specified in the last call to the routine +ply_get_element_setup(). + +Entry: + plyfile - file identifier + elem_ptr - pointer to location where the element information should be put +******************************************************************************/ + +void ply_get_element(PlyFile *plyfile, void *elem_ptr) +{ + if (plyfile->file_type == PLY_ASCII) + ascii_get_element (plyfile, (char *) elem_ptr); + else + binary_get_element (plyfile, (char *) elem_ptr); +} + + +/****************************************************************************** +Extract the comments from the header information of a PLY file. + +Entry: + plyfile - file identifier + +Exit: + num_comments - number of comments returned + returns a pointer to a list of comments +******************************************************************************/ + +char **get_comments_ply(PlyFile *plyfile, int *num_comments) +{ + *num_comments = plyfile->num_comments; + return (plyfile->comments); +} + + +/****************************************************************************** +Extract the object information (arbitrary text) from the header information +of a PLY file. + +Entry: + plyfile - file identifier + +Exit: + num_obj_info - number of lines of text information returned + returns a pointer to a list of object info lines +******************************************************************************/ + +char **get_obj_info_ply(PlyFile *plyfile, int *num_obj_info) +{ + *num_obj_info = plyfile->num_obj_info; + return (plyfile->obj_info); +} + + +/****************************************************************************** +Make ready for "other" properties of an element-- those properties that +the user has not explicitly asked for, but that are to be stashed away +in a special structure to be carried along with the element's other +information. + +Entry: + plyfile - file identifier + elem - element for which we want to save away other properties +******************************************************************************/ + +void setup_other_props(PlyFile *plyfile, PlyElement *elem) +{ + int i; + PlyProperty *prop; + int size = 0; + int type_size; + + /* Examine each property in decreasing order of size. */ + /* We do this so that all data types will be aligned by */ + /* word, half-word, or whatever within the structure. */ + + for (type_size = 8; type_size > 0; type_size /= 2) { + + /* add up the space taken by each property, and save this information */ + /* away in the property descriptor */ + + for (i = 0; i < elem->nprops; i++) { + + /* don't bother with properties we've been asked to store explicitly */ + if (elem->store_prop[i]) + continue; + + prop = elem->props[i]; + + /* internal types will be same as external */ + prop->internal_type = prop->external_type; + prop->count_internal = prop->count_external; + + /* list case */ + if (prop->is_list == PLY_LIST) { + + /* pointer to list */ + if (type_size == sizeof (void *)) { + prop->offset = size; + size += sizeof (void *); /* always use size of a pointer here */ + } + + /* count of number of list elements */ + if (type_size == ply_type_size[prop->count_external]) { + prop->count_offset = size; + size += ply_type_size[prop->count_external]; + } + } + /* string */ + else if (prop->is_list == PLY_STRING) { + /* pointer to string */ + if (type_size == sizeof (char *)) { + prop->offset = size; + size += sizeof (char *); + } + } + /* scalar */ + else if (type_size == ply_type_size[prop->external_type]) { + prop->offset = size; + size += ply_type_size[prop->external_type]; + } + } + + } + + /* save the size for the other_props structure */ + elem->other_size = size; +} + + +/****************************************************************************** +Specify that we want the "other" properties of an element to be tucked +away within the user's structure. + +Entry: + plyfile - file identifier + elem - the element that we want to store other_props in + offset - offset to where other_props will be stored inside user's structure + +Exit: + returns pointer to structure containing description of other_props +******************************************************************************/ + +static PlyOtherProp *get_other_properties( + PlyFile *plyfile, + PlyElement *elem, + int offset +) +{ + int i; + PlyOtherProp *other; + PlyProperty *prop; + int nprops; + + /* remember that this is the "current" element */ + plyfile->which_elem = elem; + + /* save the offset to where to store the other_props */ + elem->other_offset = offset; + + /* place the appropriate pointers, etc. in the element's property list */ + setup_other_props (plyfile, elem); + + /* create structure for describing other_props */ + other = (PlyOtherProp *) myalloc (sizeof (PlyOtherProp)); + other->name = strdup (elem->name); +#if 0 + if (elem->other_offset == NO_OTHER_PROPS) { + other->size = 0; + other->props = NULL; + other->nprops = 0; + return (other); + } +#endif + other->size = elem->other_size; + other->props = (PlyProperty **) myalloc (sizeof(PlyProperty) * elem->nprops); + + /* save descriptions of each "other" property */ + nprops = 0; + for (i = 0; i < elem->nprops; i++) { + if (elem->store_prop[i]) + continue; + prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); + copy_property (prop, elem->props[i]); + other->props[nprops] = prop; + nprops++; + } + other->nprops = nprops; + + /* set other_offset pointer appropriately if there are NO other properties */ + if (other->nprops == 0) { + elem->other_offset = NO_OTHER_PROPS; + } + + /* return structure */ + return (other); +} + + +/****************************************************************************** +Specify that we want the "other" properties of an element to be tucked +away within the user's structure. The user needn't be concerned for how +these properties are stored. + +Entry: + plyfile - file identifier + elem_name - name of element that we want to store other_props in + offset - offset to where other_props will be stored inside user's structure + +Exit: + returns pointer to structure containing description of other_props +******************************************************************************/ + +PlyOtherProp *ply_get_other_properties( + PlyFile *plyfile, + char *elem_name, + int offset +) +{ + PlyElement *elem; + PlyOtherProp *other; + + /* find information about the element */ + elem = find_element (plyfile, elem_name); + if (elem == NULL) { + fprintf (stderr, "ply_get_other_properties: Can't find element '%s'\n", + elem_name); + return (NULL); + } + + other = get_other_properties (plyfile, elem, offset); + return (other); +} + + + + +/*************************/ +/* Other Element Stuff */ +/*************************/ + + + + + +/****************************************************************************** +Grab all the data for the current element that a user does not want to +explicitly read in. Stores this in the PLY object's data structure. + +Entry: + plyfile - pointer to file + +Exit: + returns pointer to ALL the "other" element data for this PLY file +******************************************************************************/ + +PlyOtherElems *get_other_element_ply (PlyFile *plyfile) +{ + int i; + PlyElement *elem; + char *elem_name; + int elem_count; + PlyOtherElems *other_elems; + OtherElem *other; + + elem = plyfile->which_elem; + elem_name = elem->name; + elem_count = elem->num; + + /* create room for the new "other" element, initializing the */ + /* other data structure if necessary */ + + if (plyfile->other_elems == NULL) { + plyfile->other_elems = (PlyOtherElems *) myalloc (sizeof (PlyOtherElems)); + other_elems = plyfile->other_elems; + other_elems->other_list = (OtherElem *) myalloc (sizeof (OtherElem)); + other = &(other_elems->other_list[0]); + other_elems->num_elems = 1; + } + else { + other_elems = plyfile->other_elems; + other_elems->other_list = (OtherElem *) realloc (other_elems->other_list, + sizeof (OtherElem) * other_elems->num_elems + 1); + other = &(other_elems->other_list[other_elems->num_elems]); + other_elems->num_elems++; + } + + /* count of element instances in file */ + other->elem_count = elem_count; + + /* save name of element */ + other->elem_name = strdup (elem_name); + + /* create a list to hold all the current elements */ + other->other_data = (OtherData **) + malloc (sizeof (OtherData *) * other->elem_count); + + /* set up for getting elements */ + other->other_props = ply_get_other_properties (plyfile, elem_name, + offsetof(OtherData,other_props)); + + /* grab all these elements */ + for (i = 0; i < other->elem_count; i++) { + /* grab and element from the file */ + other->other_data[i] = (OtherData *) malloc (sizeof (OtherData)); + ply_get_element (plyfile, (void *) other->other_data[i]); + } + + /* return pointer to the other elements data */ + return (other_elems); +} + + +/****************************************************************************** +Write out the "other" elements specified for this PLY file. + +Entry: + plyfile - pointer to PLY file to write out other elements for +******************************************************************************/ + +void put_other_elements_ply (PlyFile *plyfile) +{ + int i,j; + OtherElem *other; + + /* make sure we have other elements to write */ + if (plyfile->other_elems == NULL) + return; + + /* write out the data for each "other" element */ + + for (i = 0; i < plyfile->other_elems->num_elems; i++) { + + other = &(plyfile->other_elems->other_list[i]); + put_element_setup_ply (plyfile, other->elem_name); + + /* write out each instance of the current element */ + for (j = 0; j < other->elem_count; j++) + put_element_ply (plyfile, (void *) other->other_data[j]); + } +} + + +/****************************************************************************** +Free up storage used by an "other" elements data structure. + +Entry: + other_elems - data structure to free up +******************************************************************************/ + +void free_other_elements_ply (PlyOtherElems *other_elems) +{ + +} + + + +/*******************/ +/* Miscellaneous */ +/*******************/ + + + +/****************************************************************************** +Close a PLY file. + +Entry: + plyfile - identifier of file to close +******************************************************************************/ + +void ply_close(PlyFile *plyfile) +{ + fclose (plyfile->fp); + + /* free up memory associated with the PLY file */ + free (plyfile); +} + + +/****************************************************************************** +Get version number and file type of a PlyFile. + +Entry: + ply - pointer to PLY file + +Exit: + version - version of the file + file_type - PLY_ASCII, PLY_BINARY_BE, or PLY_BINARY_LE +******************************************************************************/ + +void get_info_ply(PlyFile *ply, float *version, int *file_type) +{ + if (ply == NULL) + return; + + *version = ply->version; + *file_type = ply->file_type; +} + + +/****************************************************************************** +Compare two strings. Returns 1 if they are the same, 0 if not. +******************************************************************************/ + +int equal_strings(char *s1, char *s2) +{ +// int i; + + while (*s1 && *s2) + if (*s1++ != *s2++) + return (0); + + if (*s1 != *s2) + return (0); + else + return (1); +} + + +/****************************************************************************** +Re-create the command line that was used to invoke this program. + +Entry: + argc - number of words in argv + argv - array of words in command line +******************************************************************************/ + +char *recreate_command_line (int argc, char *argv[]) +{ + int i; + char *line; + int len = 0; + + /* count total number of characters needed, including separating spaces */ + for (i = 0; i < argc; i++) + len += (int)(strlen(argv[i]) + 1); + + /* create empty line */ + line = (char *) malloc (sizeof(char) * len); + line[0] = '\0'; + + /* repeatedly append argv */ + for (i = 0; i < argc; i++) { + strcat (line, argv[i]); + if (i != argc - 1) + strcat (line, " "); + } + + return (line); +} + + +/****************************************************************************** +Find an element from the element list of a given PLY object. + +Entry: + plyfile - file id for PLY file + element - name of element we're looking for + +Exit: + returns the element, or NULL if not found +******************************************************************************/ + +PlyElement *find_element(PlyFile *plyfile, char *element) +{ + int i; + + for (i = 0; i < plyfile->num_elem_types; i++) + if (equal_strings (element, plyfile->elems[i]->name)) + return (plyfile->elems[i]); + + return (NULL); +} + + +/****************************************************************************** +Find a property in the list of properties of a given element. + +Entry: + elem - pointer to element in which we want to find the property + prop_name - name of property to find + +Exit: + index - index to position in list + returns a pointer to the property, or NULL if not found +******************************************************************************/ + +PlyProperty *find_property(PlyElement *elem, char *prop_name, int *index) +{ + int i; + + for (i = 0; i < elem->nprops; i++) + if (equal_strings (prop_name, elem->props[i]->name)) { + *index = i; + return (elem->props[i]); + } + + *index = -1; + return (NULL); +} + + +/****************************************************************************** +Read an element from an ascii file. + +Entry: + plyfile - file identifier + elem_ptr - pointer to element +******************************************************************************/ + +void ascii_get_element(PlyFile *plyfile, char *elem_ptr) +{ +// int i; + int j,k; + PlyElement *elem; + PlyProperty *prop; + char **words; + int nwords; + int which_word; +// FILE *fp = plyfile->fp; + char *elem_data,*item; + char *item_ptr; + int item_size; + int int_val; + unsigned int uint_val; + double double_val; + int list_count; + int store_it; + char **store_array; + char *orig_line; + char *other_data=NULL; + int other_flag; + + /* the kind of element we're reading currently */ + elem = plyfile->which_elem; + + /* do we need to setup for other_props? */ + + if (elem->other_offset != NO_OTHER_PROPS) { + char **ptr; + other_flag = 1; + /* make room for other_props */ + other_data = (char *) myalloc (elem->other_size); + /* store pointer in user's structure to the other_props */ + ptr = (char **) (elem_ptr + elem->other_offset); + *ptr = other_data; + } + else + other_flag = 0; + + /* read in the element */ + + words = get_words (plyfile->fp, &nwords, &orig_line); + if (words == NULL) { + fprintf (stderr, "ply_get_element: unexpected end of file\n"); + exit (-1); + } + + which_word = 0; + + for (j = 0; j < elem->nprops; j++) { + + prop = elem->props[j]; + store_it = (elem->store_prop[j] | other_flag); + + /* store either in the user's structure or in other_props */ + if (elem->store_prop[j]) + elem_data = elem_ptr; + else + elem_data = other_data; + + if (prop->is_list == PLY_LIST) { /* a list */ + + /* get and store the number of items in the list */ + get_ascii_item (words[which_word++], prop->count_external, + &int_val, &uint_val, &double_val); + if (store_it) { + item = elem_data + prop->count_offset; + store_item(item, prop->count_internal, int_val, uint_val, double_val); + } + + /* allocate space for an array of items and store a ptr to the array */ + list_count = int_val; + item_size = store_it ? ply_type_size[prop->internal_type] : 0; + store_array = (char **) (elem_data + prop->offset); + + if (list_count == 0) { + if (store_it) + *store_array = NULL; + } + else { + if (store_it) { + item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count); + item = item_ptr; + *store_array = item_ptr; + } + + /* read items and store them into the array */ + for (k = 0; k < list_count; k++) { + get_ascii_item (words[which_word++], prop->external_type, + &int_val, &uint_val, &double_val); + if (store_it) { + store_item (item, prop->internal_type, + int_val, uint_val, double_val); + item += item_size; + } + } + } + + } + else if (prop->is_list == PLY_STRING) { /* a string */ + if (store_it) { + char *str; + char **str_ptr; + str = strdup (words[which_word++]); + item = elem_data + prop->offset; + str_ptr = (char **) item; + *str_ptr = str; + } + else { + which_word++; + } + } + else { /* a scalar */ + get_ascii_item (words[which_word++], prop->external_type, + &int_val, &uint_val, &double_val); + if (store_it) { + item = elem_data + prop->offset; + store_item (item, prop->internal_type, int_val, uint_val, double_val); + } + } + + } + + free (words); +} + + +/****************************************************************************** +Read an element from a binary file. + +Entry: + plyfile - file identifier + elem_ptr - pointer to an element +******************************************************************************/ + +void binary_get_element(PlyFile *plyfile, char *elem_ptr) +{ +// int i; + int j,k; + PlyElement *elem; + PlyProperty *prop; + FILE *fp = plyfile->fp; + char *elem_data; + char *item; + char *item_ptr; + int item_size; + int int_val; + unsigned int uint_val; + double double_val; + int list_count; + int store_it; + char **store_array; + char *other_data; + int other_flag; + + other_data = NULL; + + /* the kind of element we're reading currently */ + elem = plyfile->which_elem; + + /* do we need to setup for other_props? */ + + if (elem->other_offset != NO_OTHER_PROPS) { + char **ptr; + other_flag = 1; + /* make room for other_props */ + other_data = (char *) myalloc (elem->other_size); + /* store pointer in user's structure to the other_props */ + ptr = (char **) (elem_ptr + elem->other_offset); + *ptr = other_data; + } + else + other_flag = 0; + + /* read in a number of elements */ + + for (j = 0; j < elem->nprops; j++) { + + prop = elem->props[j]; + store_it = (elem->store_prop[j] | other_flag); + + /* store either in the user's structure or in other_props */ + if (elem->store_prop[j]) + elem_data = elem_ptr; + else + elem_data = other_data; + + if (prop->is_list == PLY_LIST) { /* list */ + + /* get and store the number of items in the list */ + get_binary_item (fp, prop->count_external, + &int_val, &uint_val, &double_val, + plyfile->file_type); + if (store_it) { + item = elem_data + prop->count_offset; + store_item(item, prop->count_internal, int_val, uint_val, double_val); + } + + /* allocate space for an array of items and store a ptr to the array */ + list_count = int_val; + item_size = store_it ? ply_type_size[prop->internal_type] : 0; + store_array = (char **) (elem_data + prop->offset); + if (list_count == 0) { + if (store_it) + *store_array = NULL; + } + else { + if (store_it) { + item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count); + item = item_ptr; + *store_array = item_ptr; + } + + /* read items and store them into the array */ + for (k = 0; k < list_count; k++) { + get_binary_item (fp, prop->external_type, + &int_val, &uint_val, &double_val, + plyfile->file_type); + if (store_it) { + store_item (item, prop->internal_type, + int_val, uint_val, double_val); + item += item_size; + } + } + } + + } + else if (prop->is_list == PLY_STRING) { /* string */ + int len; + char *str; + if (fread (&len, sizeof(int), 1, fp) != sizeof(int)) + fprintf (stderr, "binary_get_element: problem occured in fread\n"); + str = (char *) myalloc (len); + if (fread (str, len, 1, fp) != len) + fprintf (stderr, "binary_get_element: problem occured in fread\n"); + if (store_it) { + char **str_ptr; + item = elem_data + prop->offset; + str_ptr = (char **) item; + *str_ptr = str; + } + } + else { /* scalar */ + get_binary_item (fp, prop->external_type, + &int_val, &uint_val, &double_val, + plyfile->file_type); + if (store_it) { + item = elem_data + prop->offset; + store_item (item, prop->internal_type, int_val, uint_val, double_val); + } + } + + } +} + + +/****************************************************************************** +Write to a file the word that represents a PLY data type. + +Entry: + fp - file pointer + code - code for type +******************************************************************************/ + +void write_scalar_type (FILE *fp, int code) +{ + /* make sure this is a valid code */ + + if (code <= PLY_StartType || code >= PLY_EndType) { + fprintf (stderr, "write_scalar_type: bad data code = %d\n", code); + exit (-1); + } + + /* write the code to a file */ + + fprintf (fp, "%s", type_names[code]); +} + + +/****************************************************************************** +Get a text line from a file and break it up into words. + +IMPORTANT: The calling routine should call "free" on the returned pointer once +finished with it. + +Entry: + fp - file to read from + +Exit: + nwords - number of words returned + orig_line - the original line of characters + returns a list of words from the line, or NULL if end-of-file +******************************************************************************/ + +char **get_words(FILE *fp, int *nwords, char **orig_line) +{ +#define BIG_STRING 4096 +// int i,j; + static char str[BIG_STRING]; + static char str_copy[BIG_STRING]; + char **words; + int max_words = 10; + int num_words = 0; + char *ptr,*ptr2; + char *result; + + words = (char **) myalloc (sizeof (char *) * max_words); + + /* read in a line */ + result = fgets (str, BIG_STRING, fp); + if (result == NULL) { + *nwords = 0; + *orig_line = NULL; + return (NULL); + } + + /* convert line-feed and tabs into spaces */ + /* (this guarentees that there will be a space before the */ + /* null character at the end of the string) */ + + str[BIG_STRING-2] = ' '; + str[BIG_STRING-1] = '\0'; + + for (ptr = str, ptr2 = str_copy; *ptr != '\0'; ptr++, ptr2++) { + *ptr2 = *ptr; + if (*ptr == '\t') { + *ptr = ' '; + *ptr2 = ' '; + } + else if (*ptr == '\n') { + *ptr = ' '; + *ptr2 = '\0'; + break; + } + } + + /* find the words in the line */ + + ptr = str; + while (*ptr != '\0') { + + /* jump over leading spaces */ + while (*ptr == ' ') + ptr++; + + /* break if we reach the end */ + if (*ptr == '\0') + break; + + /* allocate more room for words if necessary */ + if (num_words >= max_words) { + max_words += 10; + words = (char **) realloc (words, sizeof (char *) * max_words); + } + + if (*ptr == '\"') { /* a quote indidicates that we have a string */ + + /* skip over leading quote */ + ptr++; + + /* save pointer to beginning of word */ + words[num_words++] = ptr; + + /* find trailing quote or end of line */ + while (*ptr != '\"' && *ptr != '\0') + ptr++; + + /* replace quote with a null character to mark the end of the word */ + /* if we are not already at the end of the line */ + if (*ptr != '\0') + *ptr++ = '\0'; + } + else { /* non-string */ + + /* save pointer to beginning of word */ + words[num_words++] = ptr; + + /* jump over non-spaces */ + while (*ptr != ' ') + ptr++; + + /* place a null character here to mark the end of the word */ + *ptr++ = '\0'; + } + } + + /* return the list of words */ + *nwords = num_words; + *orig_line = str_copy; + return (words); +} + + +/****************************************************************************** +Return the value of an item, given a pointer to it and its type. + +Entry: + item - pointer to item + type - data type that "item" points to + +Exit: + returns a double-precision float that contains the value of the item +******************************************************************************/ + +double get_item_value(char *item, int type) +{ + unsigned char *puchar; + char *pchar; + short int *pshort; + unsigned short int *pushort; + int *pint; + unsigned int *puint; + float *pfloat; + double *pdouble; + int int_value; + unsigned int uint_value; + double double_value; + + switch (type) { + case PLY_Int8: + pchar = (char *) item; + int_value = *pchar; + return ((double) int_value); + case PLY_Uint8: + puchar = (unsigned char *) item; + int_value = *puchar; + return ((double) int_value); + case PLY_Int16: + pshort = (short int *) item; + int_value = *pshort; + return ((double) int_value); + case PLY_Uint16: + pushort = (unsigned short int *) item; + int_value = *pushort; + return ((double) int_value); + case PLY_Int32: + pint = (int *) item; + int_value = *pint; + return ((double) int_value); + case PLY_Uint32: + puint = (unsigned int *) item; + uint_value = *puint; + return ((double) uint_value); + case PLY_Float32: + pfloat = (float *) item; + double_value = *pfloat; + return (double_value); + case PLY_Float64: + pdouble = (double *) item; + double_value = *pdouble; + return (double_value); + default: + fprintf (stderr, "get_item_value: bad type = %d\n", type); + exit (-1); + } + + return (0.0); /* never actually gets here */ +} + + +/****************************************************************************** +Write out an item to a file as raw binary bytes. + +Entry: + fp - file to write to + int_val - integer version of item + uint_val - unsigned integer version of item + double_val - double-precision float version of item + type - data type to write out +******************************************************************************/ + +void write_binary_item( + FILE *fp, + int int_val, + unsigned int uint_val, + double double_val, + int type +) +{ + unsigned char uchar_val; + char char_val; + unsigned short ushort_val; + short short_val; + float float_val; + + switch (type) { + case PLY_Int8: + char_val = int_val; + fwrite (&char_val, 1, 1, fp); + break; + case PLY_Int16: + short_val = int_val; + fwrite (&short_val, 2, 1, fp); + break; + case PLY_Int32: + fwrite (&int_val, 4, 1, fp); + break; + case PLY_Uint8: + uchar_val = uint_val; + fwrite (&uchar_val, 1, 1, fp); + break; + case PLY_Uint16: + ushort_val = uint_val; + fwrite (&ushort_val, 2, 1, fp); + break; + case PLY_Uint32: + fwrite (&uint_val, 4, 1, fp); + break; + case PLY_Float32: + float_val = (float) double_val; + fwrite (&float_val, 4, 1, fp); + break; + case PLY_Float64: + fwrite (&double_val, 8, 1, fp); + break; + default: + fprintf (stderr, "write_binary_item: bad type = %d\n", type); + exit (-1); + } +} + + +/****************************************************************************** +Write out an item to a file as ascii characters. + +Entry: + fp - file to write to + int_val - integer version of item + uint_val - unsigned integer version of item + double_val - double-precision float version of item + type - data type to write out +******************************************************************************/ + +void write_ascii_item( + FILE *fp, + int int_val, + unsigned int uint_val, + double double_val, + int type +) +{ + switch (type) { + case PLY_Int8: + case PLY_Int16: + case PLY_Int32: + fprintf (fp, "%d ", int_val); + break; + case PLY_Uint8: + case PLY_Uint16: + case PLY_Uint32: + fprintf (fp, "%u ", uint_val); + break; + case PLY_Float32: + case PLY_Float64: + fprintf (fp, "%g ", double_val); + break; + default: + fprintf (stderr, "write_ascii_item: bad type = %d\n", type); + exit (-1); + } +} + + +/****************************************************************************** +Get the value of an item that is in memory, and place the result +into an integer, an unsigned integer and a double. + +Entry: + ptr - pointer to the item + type - data type supposedly in the item + +Exit: + int_val - integer value + uint_val - unsigned integer value + double_val - double-precision floating point value +******************************************************************************/ + +void get_stored_item( + void *ptr, + int type, + int *int_val, + unsigned int *uint_val, + double *double_val +) +{ + switch (type) { + case PLY_Int8: + *int_val = *((char *) ptr); + *uint_val = *int_val; + *double_val = *int_val; + break; + case PLY_Uint8: + *uint_val = *((unsigned char *) ptr); + *int_val = *uint_val; + *double_val = *uint_val; + break; + case PLY_Int16: + *int_val = *((short int *) ptr); + *uint_val = *int_val; + *double_val = *int_val; + break; + case PLY_Uint16: + *uint_val = *((unsigned short int *) ptr); + *int_val = *uint_val; + *double_val = *uint_val; + break; + case PLY_Int32: + *int_val = *((int *) ptr); + *uint_val = *int_val; + *double_val = *int_val; + break; + case PLY_Uint32: + *uint_val = *((unsigned int *) ptr); + *int_val = *uint_val; + *double_val = *uint_val; + break; + case PLY_Float32: + *double_val = *((float *) ptr); + *int_val = (int)(*double_val); + *uint_val = (unsigned int)(*double_val); + break; + case PLY_Float64: + *double_val = *((double *) ptr); + *int_val = (int)(*double_val); + *uint_val = (unsigned int)(*double_val); + break; + default: + fprintf (stderr, "get_stored_item: bad type = %d\n", type); + exit (-1); + } +} + + +/****************************************************************************** +Get the value of an item from a binary file, and place the result +into an integer, an unsigned integer and a double. + +Entry: + fp - file to get item from + type - data type supposedly in the word + +Exit: + int_val - integer value + uint_val - unsigned integer value + double_val - double-precision floating point value +******************************************************************************/ + +void get_binary_item( + FILE *fp, + int type, + int *int_val, + unsigned int *uint_val, + double *double_val, + int file_type +) +{ + char c[8]; + void *ptr; + short word; + char *byte; + int my_endianness; + + ptr = c; + word = 1 ; + byte = (char *) &word ; + my_endianness = byte[0] ? PLY_BINARY_LE : PLY_BINARY_BE ; + + switch (type) { + case PLY_Int8: + if (fread (ptr, 1, 1, fp) != 1) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + *int_val = *((char *) ptr); + *uint_val = *int_val; + *double_val = *int_val; + break; + case PLY_Uint8: + if (fread (ptr, 1, 1, fp) != 1) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + *uint_val = *((unsigned char *) ptr); + *int_val = *uint_val; + *double_val = *uint_val; + break; + case PLY_Int16: + if (my_endianness != file_type) + { + unsigned char *cptr; + cptr = (unsigned char*) ptr; + if (fread (cptr+1, 1, 1, fp) != 1) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + if (fread (cptr, 1, 1, fp) != 1) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + } + else + if (fread (ptr, 1, 2, fp) != 2) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + *int_val = *((short*) ptr) ; + *uint_val = *int_val; + *double_val = *int_val; + break; + case PLY_Uint16: + if (my_endianness != file_type) + { + unsigned char *cptr; + cptr = (unsigned char*) ptr; + if (fread (cptr+1, 1, 1, fp) != 1) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + if (fread (cptr, 1, 1, fp) != 1) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + } + else + if (fread (ptr, 1, 2, fp) != 2) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + *uint_val = *((unsigned short*) ptr) ; + *int_val = *uint_val; + *double_val = *uint_val; + break; + case PLY_Int32: + if (my_endianness != file_type) + { + unsigned char *cptr; + cptr = (unsigned char*) ptr; + if (fread (cptr+3, 1, 1, fp) != 1) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + if (fread (cptr+2, 1, 1, fp) != 1) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + if (fread (cptr+1, 1, 1, fp) != 1) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + if (fread (cptr, 1, 1, fp) != 1) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + } + else + if (fread (ptr, 1, 4, fp) != 4) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + *int_val = *((int*) ptr) ; + *uint_val = *int_val; + *double_val = *int_val; + break; + case PLY_Uint32: + if (my_endianness != file_type) + { + unsigned char *cptr; + cptr = (unsigned char*) ptr; + if (fread (cptr+3, 1, 1, fp) != 1) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + if (fread (cptr+2, 1, 1, fp) != 1) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + if (fread (cptr+1, 1, 1, fp) != 1) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + if (fread (cptr, 1, 1, fp) != 1) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + } + else + if (fread (ptr, 1, 4, fp) != 4) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + *uint_val = *((unsigned int*) ptr) ; + *int_val = *uint_val; + *double_val = *uint_val; + break; + case PLY_Float32: + if (my_endianness != file_type) + { + unsigned char *cptr; + cptr = (unsigned char*) ptr; + if (fread (cptr+3, 1, 1, fp) != 1) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + if (fread (cptr+2, 1, 1, fp) != 1) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + if (fread (cptr+1, 1, 1, fp) != 1) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + if (fread (cptr, 1, 1, fp) != 1) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + } + else + if (fread (ptr, 1, 4, fp) != 4) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + *double_val = *((float*) ptr) ; + *int_val = (int)(*double_val); + *uint_val = (unsigned int)(*double_val); + break; + case PLY_Float64: + if (my_endianness != file_type) + { + unsigned char *cptr; + cptr = (unsigned char*) ptr; + if (fread (cptr+7, 1, 1, fp) != 1) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + if (fread (cptr+6, 1, 1, fp) != 1) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + if (fread (cptr+5, 1, 1, fp) != 1) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + if (fread (cptr+4, 1, 1, fp) != 1) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + if (fread (cptr+3, 1, 1, fp) != 1) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + if (fread (cptr+2, 1, 1, fp) != 1) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + if (fread (cptr+1, 1, 1, fp) != 1) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + if (fread (cptr, 1, 1, fp) != 1) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + } + else + if (fread (ptr, 1, 8, fp) != 8) + fprintf (stderr, "get_binary_item: problem occured in fread in switch(%d)\n", type); + *double_val = *((double*) ptr) ; + *int_val = (int)(*double_val); + *uint_val = (unsigned int)(*double_val); + break; + default: + fprintf (stderr, "get_binary_item: bad type = %d\n", type); + exit (-1); + } + + /*printf("%d\n",*int_val) ; + printf("%u\n",*uint_val) ; + printf("%f\n",*double_val) ; +*/ +} + + +/****************************************************************************** +Extract the value of an item from an ascii word, and place the result +into an integer, an unsigned integer and a double. + +Entry: + word - word to extract value from + type - data type supposedly in the word + +Exit: + int_val - integer value + uint_val - unsigned integer value + double_val - double-precision floating point value +******************************************************************************/ + +void get_ascii_item( + char *word, + int type, + int *int_val, + unsigned int *uint_val, + double *double_val +) +{ + switch (type) { + case PLY_Int8: + case PLY_Uint8: + case PLY_Int16: + case PLY_Uint16: + case PLY_Int32: + *int_val = atoi (word); + *uint_val = *int_val; + *double_val = *int_val; + break; + + case PLY_Uint32: + *uint_val = strtoul (word, (char **) NULL, 10); + *int_val = *uint_val; + *double_val = *uint_val; + break; + + case PLY_Float32: + case PLY_Float64: + *double_val = atof (word); + *int_val = (int) *double_val; + *uint_val = (unsigned int) *double_val; + break; + + default: + fprintf (stderr, "get_ascii_item: bad type = %d\n", type); + exit (-1); + } +} + + +/****************************************************************************** +Store a value into a place being pointed to, guided by a data type. + +Entry: + item - place to store value + type - data type + int_val - integer version of value + uint_val - unsigned integer version of value + double_val - double version of value + +Exit: + item - pointer to stored value +******************************************************************************/ + +void store_item ( + char *item, + int type, + int int_val, + unsigned int uint_val, + double double_val +) +{ + unsigned char *puchar; + short int *pshort; + unsigned short int *pushort; + int *pint; + unsigned int *puint; + float *pfloat; + double *pdouble; + + switch (type) { + case PLY_Int8: + *item = int_val; + break; + case PLY_Uint8: + puchar = (unsigned char *) item; + *puchar = uint_val; + break; + case PLY_Int16: + pshort = (short *) item; + *pshort = int_val; + break; + case PLY_Uint16: + pushort = (unsigned short *) item; + *pushort = uint_val; + break; + case PLY_Int32: + pint = (int *) item; + *pint = int_val; + break; + case PLY_Uint32: + puint = (unsigned int *) item; + *puint = uint_val; + break; + case PLY_Float32: + pfloat = (float *) item; + *pfloat = (float) double_val; + break; + case PLY_Float64: + pdouble = (double *) item; + *pdouble = double_val; + break; + default: + fprintf (stderr, "store_item: bad type = %d\n", type); + exit (-1); + } +} + + +/****************************************************************************** +Add an element to a PLY file descriptor. + +Entry: + plyfile - PLY file descriptor + words - list of words describing the element + nwords - number of words in the list +******************************************************************************/ + +void add_element (PlyFile *plyfile, char **words, int nwords) +{ + PlyElement *elem; + + /* create the new element */ + elem = (PlyElement *) myalloc (sizeof (PlyElement)); + elem->name = strdup (words[1]); + elem->num = atoi (words[2]); + elem->nprops = 0; + + /* make room for new element in the object's list of elements */ + if (plyfile->num_elem_types == 0) + plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *)); + else + plyfile->elems = (PlyElement **) realloc (plyfile->elems, + sizeof (PlyElement *) * (plyfile->num_elem_types + 1)); + + /* add the new element to the object's list */ + plyfile->elems[plyfile->num_elem_types] = elem; + plyfile->num_elem_types++; +} + + +/****************************************************************************** +Return the type of a property, given the name of the property. + +Entry: + name - name of property type + +Exit: + returns integer code for property, or 0 if not found +******************************************************************************/ + +int get_prop_type(char *type_name) +{ + int i; + + /* try to match the type name */ + for (i = PLY_StartType + 1; i < PLY_EndType; i++) + if (equal_strings (type_name, type_names[i])) + return (i); + + /* see if we can match an old type name */ + for (i = PLY_StartType + 1; i < PLY_EndType; i++) + if (equal_strings (type_name, old_type_names[i])) + return (i); + + /* if we get here, we didn't find the type */ + return (0); +} + + +/****************************************************************************** +Add a property to a PLY file descriptor. + +Entry: + plyfile - PLY file descriptor + words - list of words describing the property + nwords - number of words in the list +******************************************************************************/ + +void add_property (PlyFile *plyfile, char **words, int nwords) +{ +// int prop_type; +// int count_type; + PlyProperty *prop; + PlyElement *elem; + + /* create the new property */ + + prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); + + if (equal_strings (words[1], "list")) { /* list */ + prop->count_external = get_prop_type (words[2]); + prop->external_type = get_prop_type (words[3]); + prop->name = strdup (words[4]); + prop->is_list = PLY_LIST; + } + else if (equal_strings (words[1], "string")) { /* string */ + prop->count_external = PLY_Int8; + prop->external_type = PLY_Int8; + prop->name = strdup (words[2]); + prop->is_list = PLY_STRING; + } + else { /* scalar */ + prop->external_type = get_prop_type (words[1]); + prop->name = strdup (words[2]); + prop->is_list = PLY_SCALAR; + } + + /* add this property to the list of properties of the current element */ + + elem = plyfile->elems[plyfile->num_elem_types - 1]; + + if (elem->nprops == 0) + elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *)); + else + elem->props = (PlyProperty **) realloc (elem->props, + sizeof (PlyProperty *) * (elem->nprops + 1)); + + elem->props[elem->nprops] = prop; + elem->nprops++; +} + + +/****************************************************************************** +Add a comment to a PLY file descriptor. + +Entry: + plyfile - PLY file descriptor + line - line containing comment +******************************************************************************/ + +void add_comment (PlyFile *plyfile, char *line) +{ + int i; + + /* skip over "comment" and leading spaces and tabs */ + i = 7; + while (line[i] == ' ' || line[i] == '\t') + i++; + + append_comment_ply (plyfile, &line[i]); +} + + +/****************************************************************************** +Add a some object information to a PLY file descriptor. + +Entry: + plyfile - PLY file descriptor + line - line containing text info +******************************************************************************/ + +void add_obj_info (PlyFile *plyfile, char *line) +{ + int i; + + /* skip over "obj_info" and leading spaces and tabs */ + i = 8; + while (line[i] == ' ' || line[i] == '\t') + i++; + + append_obj_info_ply (plyfile, &line[i]); +} + + +/****************************************************************************** +Copy a property. +******************************************************************************/ + +void copy_property(PlyProperty *dest, PlyProperty *src) +{ + dest->name = strdup (src->name); + dest->external_type = src->external_type; + dest->internal_type = src->internal_type; + dest->offset = src->offset; + + dest->is_list = src->is_list; + dest->count_external = src->count_external; + dest->count_internal = src->count_internal; + dest->count_offset = src->count_offset; +} + + +/****************************************************************************** +Allocate some memory. + +Entry: + size - amount of memory requested (in bytes) + lnum - line number from which memory was requested + fname - file name from which memory was requested +******************************************************************************/ + +static char *my_alloc(int size, int lnum, char *fname) +{ + char *ptr; + + ptr = (char *) malloc (size); + + if (ptr == 0) { + fprintf(stderr, "Memory allocation bombed on line %d in %s\n", lnum, fname); + } + + return (ptr); +} + + +/**** NEW STUFF ****/ +/**** NEW STUFF ****/ +/**** NEW STUFF ****/ +/**** NEW STUFF ****/ + + + +/****************************************************************************** +Given a file pointer, get ready to read PLY data from the file. + +Entry: + fp - the given file pointer + +Exit: + nelems - number of elements in object + elem_names - list of element names + returns a pointer to a PlyFile, used to refer to this file, or NULL if error +******************************************************************************/ + +PlyFile *read_ply(FILE *fp) +{ + PlyFile *ply; + int num_elems; + char **elem_names; + + ply = ply_read (fp, &num_elems, &elem_names); + + return (ply); +} + + +/****************************************************************************** +Given a file pointer, get ready to write PLY data to the file. + +Entry: + fp - the given file pointer + nelems - number of elements in object + elem_names - list of element names + file_type - file type, either ascii or binary + +Exit: + returns a pointer to a PlyFile, used to refer to this file, or NULL if error +******************************************************************************/ + +PlyFile *write_ply( + FILE *fp, + int nelems, + char **elem_names, + int file_type +) +{ + PlyFile *ply; + + ply = ply_write (fp, nelems, elem_names, file_type); + + return (ply); +} + + +/****************************************************************************** +Return a list of the names of the elements in a particular PLY file. + +Entry: + ply - PLY file whose element name list we want + +Exit: + num_elems - the number of element names in the list + returns the list of names +******************************************************************************/ + +char **get_element_list_ply(PlyFile *ply, int *num_elems) +{ + int i; + char **elist; + + /* create the list of element names */ + + elist = (char **) myalloc (sizeof (char *) * ply->num_elem_types); + for (i = 0; i < ply->num_elem_types; i++) + elist[i] = strdup (ply->elems[i]->name); + + /* return the number of elements and the list of element names */ + *num_elems = ply->num_elem_types; + return (elist); +} + + +/****************************************************************************** +Append a comment to a PLY file. + +Entry: + ply - file to append comment to + comment - the comment to append +******************************************************************************/ + +void append_comment_ply(PlyFile *ply, char *comment) +{ + /* (re)allocate space for new comment */ + if (ply->num_comments == 0) + ply->comments = (char **) myalloc (sizeof (char *)); + else + ply->comments = (char **) realloc (ply->comments, + sizeof (char *) * (ply->num_comments + 1)); + + /* add comment to list */ + ply->comments[ply->num_comments] = strdup (comment); + ply->num_comments++; +} + + +/****************************************************************************** +Copy the comments from one PLY file to another. + +Entry: + out_ply - destination file to copy comments to + in_ply - the source of the comments +******************************************************************************/ + +void copy_comments_ply(PlyFile *out_ply, PlyFile *in_ply) +{ + int i; + + for (i = 0; i < in_ply->num_comments; i++) + append_comment_ply (out_ply, in_ply->comments[i]); +} + + +/****************************************************************************** +Append object information (arbitrary text) to a PLY file. + +Entry: + ply - file to append object info to + obj_info - the object info to append +******************************************************************************/ + +void append_obj_info_ply(PlyFile *ply, char *obj_info) +{ + /* (re)allocate space for new info */ + if (ply->num_obj_info == 0) + ply->obj_info = (char **) myalloc (sizeof (char *)); + else + ply->obj_info = (char **) realloc (ply->obj_info, + sizeof (char *) * (ply->num_obj_info + 1)); + + /* add info to list */ + ply->obj_info[ply->num_obj_info] = strdup (obj_info); + ply->num_obj_info++; +} + + +/****************************************************************************** +Copy the object information from one PLY file to another. + +Entry: + out_ply - destination file to copy object information to + in_ply - the source of the object information +******************************************************************************/ + +void copy_obj_info_ply(PlyFile *out_ply, PlyFile *in_ply) +{ + int i; + + for (i = 0; i < in_ply->num_obj_info; i++) + append_obj_info_ply (out_ply, in_ply->obj_info[i]); +} + + +/****************************************************************************** +Close a PLY file. + +Entry: + plyfile - identifier of file to close +******************************************************************************/ + +void close_ply(PlyFile *plyfile) +{ + fclose (plyfile->fp); +} + + +/****************************************************************************** +Free the memory used by a PLY file. + +Entry: + plyfile - identifier of file +******************************************************************************/ + +void free_ply(PlyFile *plyfile) +{ + /* free up memory associated with the PLY file */ + free (plyfile); +} + + +/****************************************************************************** +Specify the index of the next element to be read in from a PLY file. + +Entry: + ply - file to read from + index - index of the element to be read + +Exit: + elem_count - the number of elements in the file + returns pointer to the name of this next element +******************************************************************************/ + +char *setup_element_read_ply (PlyFile *ply, int index, int *elem_count) +{ + PlyElement *elem; + + if (index < 0 || index > ply->num_elem_types) { + fprintf (stderr, "Warning: No element with index %d\n", index); + return (0); + } + + elem = ply->elems[index]; + + /* set this to be the current element */ + ply->which_elem = elem; + + /* return the number of such elements in the file and the element's name */ + *elem_count = elem->num; + return (elem->name); +} + + +/****************************************************************************** +Read one element from the file. This routine assumes that we're reading +the type of element specified in the last call to the routine +setup_element_read_ply(). + +Entry: + plyfile - file identifier + elem_ptr - pointer to location where the element information should be put +******************************************************************************/ + +void get_element_ply (PlyFile *plyfile, void *elem_ptr) +{ + if (plyfile->file_type == PLY_ASCII) + ascii_get_element (plyfile, (char *) elem_ptr); + else + binary_get_element (plyfile, (char *) elem_ptr); +} + + +/****************************************************************************** +Specify one of several properties of the current element that is to be +read from a file. This should be called (usually multiple times) before a +call to the routine get_element_ply(). + +Entry: + plyfile - file identifier + prop - property to add to those that will be returned +******************************************************************************/ + +void setup_property_ply( + PlyFile *plyfile, + PlyProperty *prop +) +{ + PlyElement *elem; + PlyProperty *prop_ptr; + int index; + + elem = plyfile->which_elem; + + /* deposit the property information into the element's description */ + + prop_ptr = find_property (elem, prop->name, &index); + if (prop_ptr == NULL) { + fprintf (stderr, "Warning: Can't find property '%s' in element '%s'\n", + prop->name, elem->name); + return; + } + prop_ptr->internal_type = prop->internal_type; + prop_ptr->offset = prop->offset; + prop_ptr->count_internal = prop->count_internal; + prop_ptr->count_offset = prop->count_offset; + + /* specify that the user wants this property */ + elem->store_prop[index] = STORE_PROP; +} + + +/****************************************************************************** +Specify that we want the "other" properties of the current element to be tucked +away within the user's structure. + +Entry: + plyfile - file identifier + offset - offset to where other_props will be stored inside user's structure + +Exit: + returns pointer to structure containing description of other_props +******************************************************************************/ + +PlyOtherProp *get_other_properties_ply( + PlyFile *plyfile, + int offset +) +{ + PlyOtherProp *other; + + other = get_other_properties (plyfile, plyfile->which_elem, offset); + return (other); +} + + +/****************************************************************************** +Describe which element is to be written next and state how many of them will +be written. + +Entry: + plyfile - file identifier + elem_name - name of element that information is being described + nelems - number of elements of this type to be written +******************************************************************************/ + +void describe_element_ply( + PlyFile *plyfile, + char *elem_name, + int nelems +) +{ +// int i; + PlyElement *elem; +// PlyProperty *prop; + + /* look for appropriate element */ + elem = find_element (plyfile, elem_name); + if (elem == NULL) { + fprintf(stderr,"describe_element_ply: can't find element '%s'\n",elem_name); + exit (-1); + } + + elem->num = nelems; + + /* now this element is the current element */ + plyfile->which_elem = elem; +} + + +/****************************************************************************** +Describe a property of an element. + +Entry: + plyfile - file identifier + prop - the new property +******************************************************************************/ + +void describe_property_ply( + PlyFile *plyfile, + PlyProperty *prop +) +{ + PlyElement *elem; + PlyProperty *elem_prop; + + elem = plyfile->which_elem; + + /* create room for new property */ + + if (elem->nprops == 0) { + elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *)); + elem->store_prop = (char *) myalloc (sizeof (char)); + elem->nprops = 1; + } + else { + elem->nprops++; + elem->props = (PlyProperty **) + realloc (elem->props, sizeof (PlyProperty *) * elem->nprops); + elem->store_prop = (char *) + realloc (elem->store_prop, sizeof (char) * elem->nprops); + } + + /* copy the new property */ + + elem_prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); + elem->props[elem->nprops - 1] = elem_prop; + elem->store_prop[elem->nprops - 1] = NAMED_PROP; + copy_property (elem_prop, prop); +} + + +/****************************************************************************** +Describe what the "other" properties are that are to be stored, and where +they are in an element. +******************************************************************************/ + +void describe_other_properties_ply( + PlyFile *plyfile, + PlyOtherProp *other, + int offset +) +{ + int i; + PlyElement *elem; + PlyProperty *prop; + + /* look for appropriate element */ + elem = find_element (plyfile, other->name); + if (elem == NULL) { + fprintf(stderr, "describe_other_properties_ply: can't find element '%s'\n", + other->name); + return; + } + + /* create room for other properties */ + + if (elem->nprops == 0) { + elem->props = (PlyProperty **) + myalloc (sizeof (PlyProperty *) * other->nprops); + elem->store_prop = (char *) myalloc (sizeof (char) * other->nprops); + elem->nprops = 0; + } + else { + int newsize; + newsize = elem->nprops + other->nprops; + elem->props = (PlyProperty **) + realloc (elem->props, sizeof (PlyProperty *) * newsize); + elem->store_prop = (char *) + realloc (elem->store_prop, sizeof (char) * newsize); + } + + /* copy the other properties */ + + for (i = 0; i < other->nprops; i++) { + prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); + copy_property (prop, other->props[i]); + elem->props[elem->nprops] = prop; + elem->store_prop[elem->nprops] = OTHER_PROP; + elem->nprops++; + } + + /* save other info about other properties */ + elem->other_size = other->size; + elem->other_offset = offset; +} + + +/****************************************************************************** +Pass along a pointer to "other" elements that we want to save in a given +PLY file. These other elements were presumably read from another PLY file. + +Entry: + plyfile - file pointer in which to store this other element info + other_elems - info about other elements that we want to store +******************************************************************************/ + +void describe_other_elements_ply ( + PlyFile *plyfile, + PlyOtherElems *other_elems +) +{ + int i; + OtherElem *other; + + /* ignore this call if there is no other element */ + if (other_elems == NULL) + return; + + /* save pointer to this information */ + plyfile->other_elems = other_elems; + + /* describe the other properties of this element */ + + for (i = 0; i < other_elems->num_elems; i++) { + other = &(other_elems->other_list[i]); + element_count_ply (plyfile, other->elem_name, other->elem_count); + describe_other_properties_ply (plyfile, other->other_props, + offsetof(OtherData,other_props)); + } +} + + + +/**** Property Propagation Rules ****/ + + +typedef struct RuleName { + int code; + char *name; +} RuleName; + +RuleName rule_name_list[] = { + { AVERAGE_RULE, "avg" }, + { RANDOM_RULE, "rnd" }, + { MINIMUM_RULE, "max" }, + { MAXIMUM_RULE, "min" }, + { MAJORITY_RULE, "major" }, + { SAME_RULE, "same" }, + { -1, "end_marker" }, +}; + + + +/****************************************************************************** +Initialize the property propagation rules for an element. Default is to +use averaging (AVERAGE_RULE) for creating all new properties. + +Entry: + ply - PLY object that this is for + elem_name - name of the element that we're making the rules for + +Exit: + returns pointer to the default rules +******************************************************************************/ + +PlyPropRules *init_rule_ply (PlyFile *ply, char *elem_name) +{ + int i,j; + PlyElement *elem; + PlyPropRules *rules; + PlyRuleList *list; + int found_prop; + + elem = find_element (ply, elem_name); + if (elem == NULL) { + fprintf (stderr, "init_rule_ply: Can't find element '%s'\n", elem_name); + exit (-1); + } + + rules = (PlyPropRules *) myalloc (sizeof (PlyPropRules)); + rules->elem = elem; + rules->rule_list = (int *) myalloc (sizeof(int) * elem->nprops); + rules->max_props = 0; + rules->nprops = 0; + + /* default is to use averaging rule */ + for (i = 0; i < elem->nprops; i++) + rules->rule_list[i] = AVERAGE_RULE; + + /* see if there are other rules we should use */ + + if (ply->rule_list == NULL) + return (rules); + + /* try to match the element, property and rule name */ + + for (list = ply->rule_list; list != NULL; list = list->next) { + + if (!equal_strings (list->element, elem->name)) + continue; + + found_prop = 0; + + for (i = 0; i < elem->nprops; i++) + if (equal_strings (list->property, elem->props[i]->name)) { + + found_prop = 1; + + /* look for matching rule name */ + for (j = 0; rule_name_list[j].code != -1; j++) + if (equal_strings (list->name, rule_name_list[j].name)) { + rules->rule_list[i] = rule_name_list[j].code; + break; + } + } + + if (!found_prop) { + fprintf (stderr, "Can't find property '%s' for rule '%s'\n", + list->property, list->name); + continue; + } + } + + return (rules); +} + + +/****************************************************************************** +Modify a property propagation rule. + +Entry: + rules - rules for the element + prop_name - name of the property whose rule we're modifying + rule_type - type of rule (MAXIMUM_RULE, MINIMUM_RULE, MAJORITY_RULE, etc.) +******************************************************************************/ + +void modify_rule_ply (PlyPropRules *rules, char *prop_name, int rule_type) +{ + int i; + PlyElement *elem = rules->elem; + + /* find the property and modify its rule type */ + + for (i = 0; i < elem->nprops; i++) + if (equal_strings (elem->props[i]->name, prop_name)) { + rules->rule_list[i] = rule_type; + return; + } + + /* we didn't find the property if we get here */ + fprintf (stderr, "modify_rule_ply: Can't find property '%s'\n", prop_name); + exit (-1); +} + + +/****************************************************************************** +Begin to create a set of properties from a set of propagation rules. + +Entry: + ply - PLY object whose rules we're preparing to use + rules - rules for the element +******************************************************************************/ + +void start_props_ply (PlyFile *ply, PlyPropRules *rules) +{ +// int i; +// int count; +// PlyElement *elem = rules->elem; + + /* save pointer to the rules in the PLY object */ + ply->current_rules = rules; + + /* get ready for new sets of properties to combine */ + rules->nprops = 0; +} + + +/****************************************************************************** +Remember a set of properties and their weights for creating a new set of +properties. + +Entry: + weight - weights for this set of properties + other_props - the properties to use +******************************************************************************/ + +void weight_props_ply (PlyFile *ply, float weight, void *other_props) +{ + PlyPropRules *rules = ply->current_rules; + + /* allocate space for properties and weights, if necessary */ + if (rules->max_props == 0) { + rules->max_props = 6; + rules->props = (void **) myalloc (sizeof (void *) * rules->max_props); + rules->weights = (float *) myalloc (sizeof (float) * rules->max_props); + } + if (rules->nprops == rules->max_props) { + rules->max_props *= 2; + rules->props = (void **) realloc (rules->props, + sizeof (void *) * rules->max_props); + rules->weights = (float *) realloc (rules->weights, + sizeof (float) * rules->max_props); + } + + /* remember these new properties and their weights */ + + rules->props[rules->nprops] = other_props; + rules->weights[rules->nprops] = weight; + rules->nprops++; +} + + +/****************************************************************************** +Return a pointer to a new set of properties that have been created using +a specified set of property combination rules and a given collection of +"other" properties. + +Exit: + returns a pointer to the new properties +******************************************************************************/ + +void *get_new_props_ply(PlyFile *ply) +{ + int i,j; + static double *vals; + static int max_vals = 0; + PlyPropRules *rules = ply->current_rules; + PlyElement *elem = rules->elem; + PlyProperty *prop; + char *data; + char *new_data; + void *ptr; + int offset; + int type; + double double_val; + int int_val; + unsigned int uint_val; + int random_pick; + + /* return NULL if we've got no "other" properties */ + if (elem->other_size == 0) { + return (NULL); + } + + /* create room for combined other properties */ + new_data = (char *) myalloc (sizeof (char) * elem->other_size); + + /* make sure there is enough room to store values we're to combine */ + + if (max_vals == 0) { + max_vals = rules->nprops; + vals = (double *) myalloc (sizeof (double) * rules->nprops); + } + if (rules->nprops >= max_vals) { + max_vals = rules->nprops; + vals = (double *) realloc (vals, sizeof (double) * rules->nprops); + } + + /* in case we need a random choice */ + random_pick = (int) floor (rules->nprops * ((double)rand()/ RAND_MAX)); + + /* calculate the combination for each "other" property of the element */ + + for (i = 0; i < elem->nprops; i++) { + + /* don't bother with properties we've been asked to store explicitly */ + if (elem->store_prop[i]) + continue; + + prop = elem->props[i]; + offset = prop->offset; + type = prop->external_type; + + /* collect together all the values we're to combine */ + + for (j = 0; j < rules->nprops; j++) { + data = (char *) rules->props[j]; + ptr = (void *) (data + offset); + get_stored_item ((void *) ptr, type, &int_val, &uint_val, &double_val); + vals[j] = double_val; + } + + /* calculate the combined value */ + + switch (rules->rule_list[i]) { + case AVERAGE_RULE: { + double sum = 0; + double weight_sum = 0; + for (j = 0; j < rules->nprops; j++) { + sum += vals[j] * rules->weights[j]; + weight_sum += rules->weights[j]; + } + double_val = sum / weight_sum; + break; + } + case MINIMUM_RULE: { + double_val = vals[0]; + for (j = 1; j < rules->nprops; j++) + if (double_val > vals[j]) + double_val = vals[j]; + break; + } + case MAXIMUM_RULE: { + double_val = vals[0]; + for (j = 1; j < rules->nprops; j++) + if (double_val < vals[j]) + double_val = vals[j]; + break; + } + case RANDOM_RULE: { + double_val = vals[random_pick]; + break; + } + case SAME_RULE: { + double_val = vals[0]; + for (j = 1; j < rules->nprops; j++) + if (double_val != vals[j]) { + fprintf (stderr, + "get_new_props_ply: Error combining properties that should be the same.\n"); + exit (-1); + } + break; + } + default: + fprintf (stderr, "get_new_props_ply: Bad rule = %d\n", + rules->rule_list[i]); + exit (-1); + } + + /* store the combined value */ + + int_val = (int) double_val; + uint_val = (unsigned int) double_val; + ptr = (void *) (new_data + offset); + store_item ((char *) ptr, type, int_val, uint_val, double_val); + } + + return ((void *) new_data); +} + + +/****************************************************************************** +Set the list of user-specified property combination rules. +******************************************************************************/ + +void set_prop_rules_ply (PlyFile *ply, PlyRuleList *prop_rules) +{ + ply->rule_list = prop_rules; +} + + +/****************************************************************************** +Append a property rule to a growing list of user-specified rules. + +Entry: + rule_list - current rule list + name - name of property combination rule + property - "element.property" says which property the rule affects + +Exit: + returns pointer to the new rule list +******************************************************************************/ + +PlyRuleList *append_prop_rule ( + PlyRuleList *rule_list, + char *name, + char *property +) +{ + PlyRuleList *rule; + PlyRuleList *rule_ptr; + char *str,*str2; + char *ptr; + + /* find . */ + str = strdup (property); + for (ptr = str; *ptr != '\0' && *ptr != '.'; ptr++) ; + + /* split string at . */ + if (*ptr == '.') { + *ptr = '\0'; + str2 = ptr + 1; + } + else { + fprintf (stderr, "Can't find property '%s' for rule '%s'\n", + property, name); + return (rule_list); + } + + rule = (PlyRuleList *) malloc (sizeof (PlyRuleList)); + rule->name = name; + rule->element = str; + rule->property = str2; + rule->next = NULL; + + /* either start rule list or append to it */ + + if (rule_list == NULL) + rule_list = rule; + else { /* append new rule to current list */ + rule_ptr = rule_list; + while (rule_ptr->next != NULL) + rule_ptr = rule_ptr->next; + rule_ptr->next = rule; + } + + /* return pointer to list */ + + return (rule_list); +} + + +/****************************************************************************** +See if a name matches the name of any property combination rules. + +Entry: + name - name of rule we're trying to match + +Exit: + returns 1 if we find a match, 0 if not +******************************************************************************/ + +int matches_rule_name (char *name) +{ + int i; + + for (i = 0; rule_name_list[i].code != -1; i++) + if (equal_strings (rule_name_list[i].name, name)) + return (1); + + return (0); +} + + diff --git a/cgogn/io/ply.h b/cgogn/io/ply.h new file mode 100644 index 00000000..c1c082eb --- /dev/null +++ b/cgogn/io/ply.h @@ -0,0 +1,257 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* version 0.1 * +* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +/* + +Header for PLY polygon files. + +- Greg Turk + +A PLY file contains a single polygonal _object_. + +An object is composed of lists of _elements_. Typical elements are +vertices, faces, edges and materials. + +Each type of element for a given object has one or more _properties_ +associated with the element type. For instance, a vertex element may +have as properties three floating-point values x,y,z and three unsigned +chars for red, green and blue. + +----------------------------------------------------------------------- + +Copyright (c) 1998 Georgia Institute of Technology. All rights reserved. + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose is hereby granted without fee, provided +that the above copyright notice and this permission notice appear in +all copies of this software and that you do not sell the software. + +THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND, +EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY +WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +*/ + +#ifndef __PLY_H__ +#define __PLY_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + + +#define PLY_ASCII 1 /* ascii PLY file */ +#define PLY_BINARY_BE 2 /* binary PLY file, big endian */ +#define PLY_BINARY_LE 3 /* binary PLY file, little endian */ + +#define PLY_OKAY 0 /* ply routine worked okay */ +#define PLY_ERROR -1 /* error in ply routine */ + +/* scalar data types supported by PLY format */ + +#define PLY_StartType 0 +#define PLY_Int8 1 +#define PLY_Int16 2 +#define PLY_Int32 3 +#define PLY_Uint8 4 +#define PLY_Uint16 5 +#define PLY_Uint32 6 +#define PLY_Float32 7 +#define PLY_Float64 8 +#define PLY_EndType 9 + +#define PLY_SCALAR 0 +#define PLY_LIST 1 +#define PLY_STRING 2 + + +typedef struct PlyProperty { /* description of a property */ + + char *name; /* property name */ + int external_type; /* file's data type */ + int internal_type; /* program's data type */ + int offset; /* offset bytes of prop in a struct */ + + int is_list; /* 0 = scalar, 1 = list, 2 = char string */ + int count_external; /* file's count type */ + int count_internal; /* program's count type */ + int count_offset; /* offset byte for list count */ + +} PlyProperty; + +typedef struct PlyElement { /* description of an element */ + char *name; /* element name */ + int num; /* number of elements in this object */ + int size; /* size of element (bytes) or -1 if variable */ + int nprops; /* number of properties for this element */ + PlyProperty **props; /* list of properties in the file */ + char *store_prop; /* flags: property wanted by user? */ + int other_offset; /* offset to un-asked-for props, or -1 if none*/ + int other_size; /* size of other_props structure */ +} PlyElement; + +typedef struct PlyOtherProp { /* describes other properties in an element */ + char *name; /* element name */ + int size; /* size of other_props */ + int nprops; /* number of properties in other_props */ + PlyProperty **props; /* list of properties in other_props */ +} PlyOtherProp; + +typedef struct OtherData { /* for storing other_props for an other element */ + void *other_props; +} OtherData; + +typedef struct OtherElem { /* data for one "other" element */ + char *elem_name; /* names of other elements */ + int elem_count; /* count of instances of each element */ + OtherData **other_data; /* actual property data for the elements */ + PlyOtherProp *other_props; /* description of the property data */ +} OtherElem; + +typedef struct PlyOtherElems { /* "other" elements, not interpreted by user */ + int num_elems; /* number of other elements */ + OtherElem *other_list; /* list of data for other elements */ +} PlyOtherElems; + +#define AVERAGE_RULE 1 +#define MAJORITY_RULE 2 +#define MINIMUM_RULE 3 +#define MAXIMUM_RULE 4 +#define SAME_RULE 5 +#define RANDOM_RULE 6 + +typedef struct PlyPropRules { /* rules for combining "other" properties */ + PlyElement *elem; /* element whose rules we are making */ + int *rule_list; /* types of rules (AVERAGE_PLY, MAJORITY_PLY, etc.) */ + int nprops; /* number of properties we're combining so far */ + int max_props; /* maximum number of properties we have room for now */ + void **props; /* list of properties we're combining */ + float *weights; /* list of weights of the properties */ +} PlyPropRules; + +typedef struct PlyRuleList { + char *name; /* name of the rule */ + char *element; /* name of element that rule applies to */ + char *property; /* name of property that rule applies to */ + struct PlyRuleList *next; /* pointer for linked list of rules */ +} PlyRuleList; + +typedef struct PlyFile { /* description of PLY file */ + FILE *fp; /* file pointer */ + int file_type; /* ascii or binary */ + float version; /* version number of file */ + int num_elem_types; /* number of element types of object */ + PlyElement **elems; /* list of elements */ + int num_comments; /* number of comments */ + char **comments; /* list of comments */ + int num_obj_info; /* number of items of object information */ + char **obj_info; /* list of object info items */ + PlyElement *which_elem; /* element we're currently reading or writing */ + PlyOtherElems *other_elems; /* "other" elements from a PLY file */ + PlyPropRules *current_rules; /* current propagation rules */ + PlyRuleList *rule_list; /* rule list from user */ +} PlyFile; + +/* memory allocation */ +/* +extern char *my_alloc(); +*/ +#define myalloc(mem_size) my_alloc((mem_size), __LINE__, __FILE__) + + +/* old routines */ + +#if 0 +extern PlyFile *ply_write(FILE *, int, char **, int); +extern PlyFile *ply_read(FILE *, int *, char ***); +extern PlyFile *ply_open_for_reading( char *, int *, char ***, int *, float *); +extern void ply_close(PlyFile *); +extern PlyOtherProp *ply_get_other_properties(PlyFile *, char *, int); +#endif + +extern void ply_describe_property(PlyFile *, char *, PlyProperty *); +extern void ply_get_property(PlyFile *, char *, PlyProperty *); +extern void ply_get_element(PlyFile *, void *); + + +/*** delcaration of routines ***/ + +PlyOtherElems *get_other_element_ply (PlyFile *); + +PlyFile *read_ply(FILE *); +PlyFile *write_ply(FILE *, int, char **, int); +extern PlyFile *open_for_writing_ply(char *, int, char **, int); +void close_ply(PlyFile *); +void free_ply(PlyFile *); + +void get_info_ply(PlyFile *, float *, int *); +void free_other_elements_ply (PlyOtherElems *); + +void append_comment_ply(PlyFile *, char *); +void append_obj_info_ply(PlyFile *, char *); +void copy_comments_ply(PlyFile *, PlyFile *); +void copy_obj_info_ply(PlyFile *, PlyFile *); +char **get_comments_ply(PlyFile *, int *); +char **get_obj_info_ply(PlyFile *, int *); + +char **get_element_list_ply(PlyFile *, int *); +void setup_property_ply(PlyFile *, PlyProperty *); +void get_element_ply (PlyFile *, void *); +char *setup_element_read_ply (PlyFile *, int, int *); +PlyOtherProp *get_other_properties_ply(PlyFile *, int); + +void element_count_ply(PlyFile *, char *, int); +void describe_element_ply(PlyFile *, char *, int); +void describe_property_ply(PlyFile *, PlyProperty *); +void describe_other_properties_ply(PlyFile *, PlyOtherProp *, int); +void describe_other_elements_ply ( PlyFile *, PlyOtherElems *); +void get_element_setup_ply(PlyFile *, char *, int, PlyProperty *); +PlyProperty **get_element_description_ply(PlyFile *, char *, int*, int*); +void element_layout_ply(PlyFile *, char *, int, int, PlyProperty *); + +void header_complete_ply(PlyFile *); +void put_element_setup_ply(PlyFile *, char *); +void put_element_ply(PlyFile *, void *); +void put_other_elements_ply(PlyFile *); + +PlyPropRules *init_rule_ply (PlyFile *, char *); +void modify_rule_ply (PlyPropRules *, char *, int); +void start_props_ply (PlyFile *, PlyPropRules *); +void weight_props_ply (PlyFile *, float, void *); +void *get_new_props_ply(PlyFile *); +void set_prop_rules_ply (PlyFile *, PlyRuleList *); +PlyRuleList *append_prop_rule (PlyRuleList *, char *, char *); +int matches_rule_name (char *); + +int equal_strings(char *, char *); +char *recreate_command_line (int, char *argv[]); + +#ifdef __cplusplus +} +#endif +#endif /* !__PLY_H__ */ + diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index fff6e8eb..2c82a940 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -43,7 +44,8 @@ enum SurfaceFileType { SurfaceFileType_UNKNOWN = 0, SurfaceFileType_OFF, - SurfaceFileType_OBJ + SurfaceFileType_OBJ, + SurfaceFileType_PLY }; inline SurfaceFileType get_file_type(const std::string& filename) @@ -53,6 +55,8 @@ inline SurfaceFileType get_file_type(const std::string& filename) return SurfaceFileType_OFF; if (extension == "obj") return SurfaceFileType_OBJ; + if (extension == "ply") + return SurfaceFileType_PLY; return SurfaceFileType_UNKNOWN; } @@ -142,6 +146,11 @@ class SurfaceImport case SurfaceFileType_OBJ : result = import_OBJ(fp); break; + case SurfaceFileType_PLY : + fp.close(); + result = import_ply(filename); + break; + } if (!result) @@ -258,6 +267,8 @@ class SurfaceImport template bool import_OFF(std::ifstream& fp) { + using Scalar = typename VEC3::Scalar; + std::string line; line.reserve(512); @@ -321,7 +332,7 @@ class SurfaceImport double y = read_double(); double z = read_double(); - VEC3 pos{x, y, z}; + VEC3 pos{Scalar(x), Scalar(y), Scalar(z)}; unsigned int vertex_id = vertex_attributes_.template insert_lines<1>(); (*position)[vertex_id] = pos; @@ -460,6 +471,8 @@ class SurfaceImport template bool import_OBJ(std::ifstream& fp) { + using Scalar = typename VEC3::Scalar; + ChunkArray* position = vertex_attributes_.template add_attribute("position"); @@ -487,7 +500,7 @@ class SurfaceImport oss >> y; oss >> z; - VEC3 pos{x, y, z}; + VEC3 pos{Scalar(x), Scalar(y), Scalar(z)}; unsigned int vertex_id = vertex_attributes_.template insert_lines<1>(); (*position)[vertex_id] = pos; @@ -557,6 +570,74 @@ class SurfaceImport return true; } + + + + template + bool import_ply(const std::string& filename) + { + + PlyImportData pid; + + if (! pid.read_file(filename) ) + { + std::cerr << "Unable to open file " << filename << std::endl; + return false; + } + + ChunkArray* position = vertex_attributes_.template add_attribute("position"); + ChunkArray* color; + if (pid.has_colors()) + { + color = vertex_attributes_.template add_attribute("color"); + } + + nb_vertices_ = pid.nb_vertices(); + nb_faces_ = pid.nb_faces(); + + + // read vertices position + std::vector vertices_id; + vertices_id.reserve(nb_vertices_); + + for (unsigned int i = 0; i < nb_vertices_; ++i) + { + VEC3 pos; + pid.vertex_position(i, pos); + + unsigned int vertex_id = vertex_attributes_.template insert_lines<1>(); + (*position)[vertex_id] = pos; + + vertices_id.push_back(vertex_id); + + if (pid.has_colors()) + { + VEC3 rgb; + pid.vertex_color_float32(i, rgb); + + (*color)[vertex_id] = pos; + } + } + + // read faces (vertex indices) + faces_nb_edges_.reserve(nb_faces_); + faces_vertex_indices_.reserve(nb_vertices_ * 8); + for (unsigned int i = 0; i < nb_faces_; ++i) + { + unsigned int n = pid.get_face_valence(i); + faces_nb_edges_.push_back(n); + int* indices = pid.get_face_indices(i); + for (unsigned int j = 0; j < n; ++j) + { + unsigned int index = (unsigned int)(indices[j]); + faces_vertex_indices_.push_back(vertices_id[index]); + } + } + + return true; + } + + }; #if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_SURFACE_IMPORT_CPP_)) From b75427056c8c51ee0ede3cc08fee7badf819cd3e Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Mon, 22 Feb 2016 14:55:56 +0100 Subject: [PATCH 131/402] include modification C++ compliant --- cgogn/io/import_ply_data.cpp | 4 ++-- cgogn/io/import_ply_data.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cgogn/io/import_ply_data.cpp b/cgogn/io/import_ply_data.cpp index 0bb63f10..03fde112 100644 --- a/cgogn/io/import_ply_data.cpp +++ b/cgogn/io/import_ply_data.cpp @@ -24,8 +24,8 @@ #define IO_IMPORT_PLY_DATA_CPP_ #include -#include -#include +#include +#include #include diff --git a/cgogn/io/import_ply_data.h b/cgogn/io/import_ply_data.h index 7984cb5e..49d9aa83 100644 --- a/cgogn/io/import_ply_data.h +++ b/cgogn/io/import_ply_data.h @@ -25,7 +25,7 @@ #ifndef _IMPORT_PLY_DATA_H #define _IMPORT_PLY_DATA_H -#include +#include #include #include From 6d2d5744ef57e163d133f67def5272097ba00c15 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Mon, 22 Feb 2016 16:49:31 +0100 Subject: [PATCH 132/402] End of CMap2 cleaning --- .../multithreading/bench_multithreading.cpp | 12 +- cgogn/core/cmap/cmap0.h | 2 - cgogn/core/cmap/cmap1.h | 6 +- cgogn/core/cmap/cmap2.h | 94 ++++----- cgogn/core/cmap/cmap3.h | 4 +- cgogn/core/cmap/map_base.h | 11 +- cgogn/core/cmap/map_base_data.h | 4 +- cgogn/geometry/algos/normal.h | 4 +- cgogn/geometry/tests/algos/algos_test.cpp | 118 +++++------ cgogn/geometry/tests/functions/area_test.cpp | 10 +- .../geometry/tests/functions/normal_test.cpp | 26 +-- .../tests/types/bounding_box_test.cpp | 58 +++--- cgogn/geometry/tests/types/plane_3d_test.cpp | 32 +-- cgogn/geometry/tests/types/vec_test.cpp | 189 +++++++++--------- cgogn/geometry/types/bounding_box.cpp | 4 +- cgogn/geometry/types/bounding_box.h | 4 +- cgogn/io/examples/cmap2_import.cpp | 3 +- cgogn/io/examples/cmap3_import.cpp | 4 +- cgogn/rendering/examples/simple_viewer.cpp | 8 +- cgogn/rendering/map_render.h | 10 +- 20 files changed, 296 insertions(+), 307 deletions(-) diff --git a/benchmarks/multithreading/bench_multithreading.cpp b/benchmarks/multithreading/bench_multithreading.cpp index c3620044..d9be7350 100644 --- a/benchmarks/multithreading/bench_multithreading.cpp +++ b/benchmarks/multithreading/bench_multithreading.cpp @@ -44,8 +44,8 @@ const cgogn::Orbit FACE = Face::ORBIT; const unsigned int ITERATIONS = 1u; -using Vec3 = Eigen::Vector3d; -//using Vec3 = cgogn::geometry::Vec_T>; +//using Vec3 = Eigen::Vector3d; +using Vec3 = cgogn::geometry::Vec_T>; template using VertexAttributeHandler = Map2::VertexAttributeHandler; @@ -127,8 +127,8 @@ static void BENCH_faces_normals_multi_threaded(benchmark::State& state) if (!cgogn::almost_equal_absolute(error.squaredNorm(), 0., 1e-9 )) { std::cerr << __FILE__ << ":" << __LINE__ << " : there was an error during computation of normals" << std::endl; - std::cerr << "face_normal " << face_normal[f] << std::endl; - std::cerr << "face_normal_mt " << face_normal_mt[f] << std::endl; +// std::cerr << "face_normal " << face_normal[f] << std::endl; +// std::cerr << "face_normal_mt " << face_normal_mt[f] << std::endl; } }); @@ -185,8 +185,8 @@ static void BENCH_vertices_normals_multi_threaded(benchmark::State& state) if (!cgogn::almost_equal_absolute(error.squaredNorm(), 0., 1e-9 )) { std::cerr << __FILE__ << ":" << __LINE__ << " : there was an error during computation of vertices normals" << std::endl; - std::cerr << "vertices_normal " << vertices_normal[v] << std::endl; - std::cerr << "vertices_normal_mt " << vertices_normal_mt[v] << std::endl; +// std::cerr << "vertices_normal " << vertices_normal[v] << std::endl; +// std::cerr << "vertices_normal_mt " << vertices_normal_mt[v] << std::endl; } }); diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index ba99f65c..a77dfea6 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -45,8 +45,6 @@ class CMap0_T : public MapBase template friend class DartMarker_T; template friend class DartMarkerStore; - static const Orbit VERTEX = Orbit::DART; - using Vertex = Cell; template diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 54bfd872..76271721 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -45,8 +45,8 @@ class CMap1_T : public CMap0_T template friend class DartMarker_T; template friend class DartMarkerStore; - using Vertex = Cell; - using Face = Cell; + using Vertex = Cell; + using Face = Cell; template using ChunkArray = typename Inherit::template ChunkArray; @@ -405,7 +405,7 @@ class CMap1_T : public CMap0_T { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); - foreach_dart_of_orbit(f, func); + foreach_dart_of_orbit(f, func); } }; diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index ba0d63de..47fe7c8a 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -51,17 +51,11 @@ class CMap2_T : public CMap1_T template friend class DartMarker_T; template friend class DartMarkerStore; -// static const Orbit DART = Orbit::DART; - static const Orbit VERTEX = Orbit::PHI21; - static const Orbit EDGE = Orbit::PHI2; - static const Orbit FACE = Orbit::PHI1; -// static const Orbit VOLUME = Orbit::PHI1_PHI2; - - using CDart = Cell ; - using Vertex = Cell ; - using Edge = Cell ; - using Face = Cell ; - using Volume = Cell; + using CDart = Cell; + using Vertex = Cell; + using Edge = Cell; + using Face = Cell; + using Volume = Cell; template using ChunkArray = typename Inherit::template ChunkArray; @@ -217,7 +211,7 @@ class CMap2_T : public CMap1_T const CDart nf = phi2(e); const CDart f = phi2(ne); - if (this->template is_embedded()) { + if (this->template is_embedded()) { this->new_embedding(ne); this->new_embedding(nf); } @@ -306,7 +300,7 @@ class CMap2_T : public CMap1_T CDart nd = this->phi_1(d); CDart ne = this->phi_1(e); - if (this->template is_embedded()) { + if (this->template is_embedded()) { this->new_embedding(nd); this->new_embedding(ne); } @@ -374,7 +368,7 @@ class CMap2_T : public CMap1_T Face f = add_face_topo(size); - if (this->template is_embedded()) + if (this->template is_embedded()) foreach_dart_of_orbit(f, [this] (CDart d) { this->new_embedding(d); @@ -445,35 +439,35 @@ class CMap2_T : public CMap1_T close_hole_topo(d); const Face new_face = phi2(d); - if (this->template is_orbit_embedded()) - foreach_dart_of_orbit(new_face, [this] (Dart d) + if (this->template is_embedded()) + foreach_dart_of_orbit(new_face, [this] (CDart d) { - this->template new_embedding(d); + this->new_embedding(d); }); - if (this->template is_orbit_embedded()) - foreach_dart_of_orbit(new_face, [this] (Dart fd) + if (this->template is_embedded()) + foreach_dart_of_orbit(new_face, [this] (Vertex v) { - this->template copy_embedding(fd, this->phi1(phi2(fd))); + this->copy_embedding(v, Vertex(this->phi1(phi2(v)))); }); if (this->template is_embedded()) - foreach_dart_of_orbit(new_face, [this] (Dart fd) + foreach_dart_of_orbit(new_face, [this] (Edge e) { - this->template copy_embedding(fd, phi2(fd)); + this->copy_embedding(e, Edge(phi2(e))); }); if (this->template is_embedded()) { - this->template new_orbit_embedding(new_face); + this->new_orbit_embedding(new_face); } - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) { - const unsigned int idx = this->template get_embedding(d); - foreach_dart_of_orbit(new_face, [this, idx] (Dart fd) + const unsigned int idx = this->template get_embedding(Volume(d)); + foreach_dart_of_orbit(new_face, [this, idx] (Volume v) { - this->template set_embedding(fd, idx); + this->set_embedding(v, idx); }); } } @@ -562,7 +556,7 @@ class CMap2_T : public CMap1_T case Orbit::PHI2_PHI3: case Orbit::PHI1_PHI3: case Orbit::PHI21_PHI31: - default: cgogn_assert_not_reached("Cells of this dimension are not handled"); break; + default: cgogn_assert_not_reached("Orbit not supported in a CMap2"); break; } } @@ -640,7 +634,7 @@ class CMap2_T : public CMap1_T case Orbit::PHI2_PHI3: case Orbit::PHI1_PHI3: case Orbit::PHI21_PHI31: - default: cgogn_assert_not_reached("Cells of this dimension are not handled"); break; + default: cgogn_assert_not_reached("Orbit not supported in a CMap2"); break; } } @@ -651,75 +645,73 @@ class CMap2_T : public CMap1_T public: template - inline void foreach_incident_edge(Vertex v, const FUNC& f) const + inline void foreach_incident_edge(Vertex v, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); - foreach_dart_of_orbit(v, f); + foreach_dart_of_orbit(v, func); } template - inline void foreach_incident_face(Vertex v, const FUNC& f) const + inline void foreach_incident_face(Vertex v, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); - foreach_dart_of_orbit(v, f); + foreach_dart_of_orbit(v, func); } template - inline void foreach_incident_vertex(Edge e, const FUNC& f) const + inline void foreach_incident_vertex(Edge e, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); - f(e.dart); - f(phi2(e.dart)); + foreach_dart_of_orbit(e, func); } template - inline void foreach_incident_face(Edge e, const FUNC& f) const + inline void foreach_incident_face(Edge e, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); - f(e.dart); - f(phi2(e.dart)); + foreach_dart_of_orbit(e, func); } template inline void foreach_incident_vertex(Face f, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); - foreach_dart_of_orbit(f, func); + foreach_dart_of_orbit(f, func); } template inline void foreach_incident_edge(Face f, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); - foreach_dart_of_orbit(f, func); + foreach_dart_of_orbit(f, func); } template - inline void foreach_incident_vertex(Volume v, const FUNC& f) const + inline void foreach_incident_vertex(Volume w, const FUNC& f) const { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); DartMarkerStore marker(*this); - foreach_dart_of_orbit(v, [&] (Dart d) + foreach_dart_of_orbit(w, [&] (Vertex v) { - if (!marker.is_marked(d)) + if (!marker.is_marked(v)) { - marker.template mark_orbit(d); - f(d); + marker.template mark_orbit(v); + f(v); } }); } template - inline void foreach_incident_edge(Volume v, const FUNC& f) const + inline void foreach_incident_edge(Volume w, const FUNC& f) const { static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); DartMarkerStore marker(*this); - foreach_dart_of_orbit(v, [&] (Dart d) + foreach_dart_of_orbit(w, [&] (Edge e) { - if (!marker.is_marked(d)) + if (!marker.is_marked(e)) { - marker.template mark_orbit(d); - f(d); + marker.template mark_orbit(e); + f(e); } }); } diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index fdb68d38..98d0b0f6 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -39,6 +39,8 @@ class CMap3_T : public CMap2_T { public: + static const int PRIM_SIZE = 1; + using MapTraits = MAP_TRAITS; using MapType = MAP_TYPE; using Inherit = CMap2_T; @@ -49,8 +51,6 @@ class CMap3_T : public CMap2_T template friend class DartMarker_T; template friend class DartMarkerStore; - static const int PRIM_SIZE = 1; - static const Orbit DART = Orbit::DART; static const Orbit VERTEX = Orbit::PHI21_PHI31; static const Orbit EDGE = Orbit::PHI2_PHI3; diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 62dd1e54..e689cd37 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -296,7 +296,7 @@ class MapBase : public MapBaseData else { std::lock_guard lock(this->mark_attributes_mutex_[ORBIT]); - if (!this->template is_orbit_embedded()) + if (!this->template is_embedded>()) create_embedding(); ChunkArray* ca = this->attributes_[ORBIT].add_marker_attribute(); return ca; @@ -311,7 +311,8 @@ class MapBase : public MapBaseData inline void release_mark_attribute(ChunkArray* ca) { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - cgogn_message_assert(this->template is_orbit_embedded(), "Invalid parameter: orbit not embedded"); + cgogn_message_assert(this->template is_embedded>(), + "Invalid parameter: orbit not embedded"); this->mark_attributes_[ORBIT][this->get_current_thread_index()].push_back(ca); } @@ -327,7 +328,7 @@ class MapBase : public MapBaseData inline void create_embedding() { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - cgogn_message_assert(!this->template is_orbit_embedded(), "Invalid parameter: orbit is already embedded"); + cgogn_message_assert(!this->template is_embedded>(), "Invalid parameter: orbit is already embedded"); std::ostringstream oss; oss << "EMB_" << orbit_name(ORBIT); @@ -497,7 +498,7 @@ class MapBase : public MapBaseData template bool same_cell(Cell c1, Cell c2) const { - if (this->template is_orbit_embedded()) + if (this->template is_embedded>()) return this->get_embedding(c1) == this->get_embedding(c2); const ConcreteMap* cmap = to_concrete(); @@ -737,7 +738,7 @@ class MapBase : public MapBaseData case AUTO : if (is_topo_cache_enabled()) foreach_cell_topo_cache(f); - else if (this->template is_orbit_embedded()) + else if (this->template is_embedded()) foreach_cell_cell_marking(f); else foreach_cell_dart_marking(f); diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index d00a4c84..69374427 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -257,7 +257,7 @@ class MapBaseData : public MapGen inline unsigned int get_embedding(Cell c) const { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - cgogn_message_assert(is_orbit_embedded(), "Invalid parameter: orbit not embedded"); + cgogn_message_assert(is_embedded>(), "Invalid parameter: orbit not embedded"); cgogn_message_assert((*embeddings_[ORBIT])[c.dart.index] != EMBNULL, "get_embedding result is EMBNULL"); return (*embeddings_[ORBIT])[c.dart.index]; @@ -269,7 +269,7 @@ class MapBaseData : public MapGen inline void set_embedding(Cell c, unsigned int emb) { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - cgogn_message_assert(is_orbit_embedded(), "Invalid parameter: orbit not embedded"); + cgogn_message_assert(is_embedded>(), "Invalid parameter: orbit not embedded"); cgogn_message_assert(emb != EMBNULL,"cannot set an embedding to EMBNULL."); const unsigned int old = (*embeddings_[ORBIT])[c.dart.index]; diff --git a/cgogn/geometry/algos/normal.h b/cgogn/geometry/algos/normal.h index 6f4d82b7..453b49c3 100644 --- a/cgogn/geometry/algos/normal.h +++ b/cgogn/geometry/algos/normal.h @@ -80,7 +80,7 @@ inline VEC3 vertex_normal(const MAP& map, Cell v, const typename M { using Scalar = typename VEC3::Scalar; - VEC3 n{0,0,0}; + VEC3 n{Scalar{0}, Scalar{0}, Scalar{0}}; const VEC3& p = position[v.dart]; map.foreach_incident_face(v, [&] (Cell f) { @@ -101,7 +101,7 @@ inline VEC3 vertex_normal(const MAP& map, Cell v, const typename M { using Scalar = typename VEC3::Scalar; - VEC3 n{0,0,0}; + VEC3 n{Scalar{0}, Scalar{0} ,Scalar{0}}; const VEC3& p = position[v.dart]; map.foreach_incident_face(v, [&] (Cell f) { diff --git a/cgogn/geometry/tests/algos/algos_test.cpp b/cgogn/geometry/tests/algos/algos_test.cpp index 029d96fa..c9236acc 100644 --- a/cgogn/geometry/tests/algos/algos_test.cpp +++ b/cgogn/geometry/tests/algos/algos_test.cpp @@ -37,7 +37,7 @@ #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) using StdArray = cgogn::geometry::Vec_T>; -using EigenVec3d = Eigen::Vector3d; +//using EigenVec3d = Eigen::Vector3d; using CMap2 = cgogn::CMap2; template @@ -48,20 +48,20 @@ TEST(Algos_TEST, TriangleArea) { CMap2 map; cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); - VertexAttributeHandler vertex_position = map.get_attribute("position"); + VertexAttributeHandler vertex_position = map.get_attribute("position"); const double area = cgogn::geometry::triangle_area(map, *map.begin(), vertex_position); const double cf_area = cgogn::geometry::convex_face_area(map, *map.begin(), vertex_position); EXPECT_DOUBLE_EQ(area, 12.5); EXPECT_DOUBLE_EQ(cf_area, 12.5); } { - CMap2 map; - cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); - VertexAttributeHandler vertex_position = map.get_attribute("position"); - const double area = cgogn::geometry::triangle_area(map, *map.begin(), vertex_position); - const double cf_area = cgogn::geometry::convex_face_area(map, *map.begin(), vertex_position); - EXPECT_DOUBLE_EQ(area, 12.5); - EXPECT_DOUBLE_EQ(cf_area, 12.5); +// CMap2 map; +// cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); +// VertexAttributeHandler vertex_position = map.get_attribute("position"); +// const double area = cgogn::geometry::triangle_area(map, *map.begin(), vertex_position); +// const double cf_area = cgogn::geometry::convex_face_area(map, *map.begin(), vertex_position); +// EXPECT_DOUBLE_EQ(area, 12.5); +// EXPECT_DOUBLE_EQ(cf_area, 12.5); } } @@ -70,16 +70,16 @@ TEST(Algos_TEST, QuadArea) { CMap2 map; cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); - VertexAttributeHandler vertex_position = map.get_attribute("position"); + VertexAttributeHandler vertex_position = map.get_attribute("position"); const double area = cgogn::geometry::convex_face_area(map, *map.begin(), vertex_position); EXPECT_DOUBLE_EQ(area, 10); } { - CMap2 map; - cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); - VertexAttributeHandler vertex_position = map.get_attribute("position"); - const double area = cgogn::geometry::convex_face_area(map, *map.begin(), vertex_position); - EXPECT_DOUBLE_EQ(area, 10); +// CMap2 map; +// cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); +// VertexAttributeHandler vertex_position = map.get_attribute("position"); +// const double area = cgogn::geometry::convex_face_area(map, *map.begin(), vertex_position); +// EXPECT_DOUBLE_EQ(area, 10); } } @@ -89,21 +89,21 @@ TEST(Algos_TEST, TriangleCentroid) { CMap2 map; cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); - VertexAttributeHandler vertex_position = map.get_attribute("position"); - const StdArray centroid = cgogn::geometry::centroid(map, cgogn::Cell(*map.begin()), vertex_position); + VertexAttributeHandler vertex_position = map.get_attribute("position"); + const StdArray centroid = cgogn::geometry::centroid(map, CMap2::Face(*map.begin()), vertex_position); EXPECT_DOUBLE_EQ(centroid[0], 5.0/3.0); EXPECT_DOUBLE_EQ(centroid[1], 5.0/3.0); EXPECT_DOUBLE_EQ(centroid[2], 0); } { - CMap2 map; - cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); - VertexAttributeHandler vertex_position = map.get_attribute("position"); - const EigenVec3d centroid = cgogn::geometry::centroid(map, cgogn::Cell(*map.begin()), vertex_position); - EXPECT_DOUBLE_EQ(centroid[0], 5.0/3.0); - EXPECT_DOUBLE_EQ(centroid[1], 5.0/3.0); - EXPECT_DOUBLE_EQ(centroid[2], 0); +// CMap2 map; +// cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); +// VertexAttributeHandler vertex_position = map.get_attribute("position"); +// const EigenVec3d centroid = cgogn::geometry::centroid(map, CMap2::Face(*map.begin()), vertex_position); +// EXPECT_DOUBLE_EQ(centroid[0], 5.0/3.0); +// EXPECT_DOUBLE_EQ(centroid[1], 5.0/3.0); +// EXPECT_DOUBLE_EQ(centroid[2], 0); } } @@ -112,21 +112,21 @@ TEST(Algos_TEST, QuadCentroid) { CMap2 map; cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); - VertexAttributeHandler vertex_position = map.get_attribute("position"); - const StdArray centroid = cgogn::geometry::centroid(map, cgogn::Cell(*map.begin()), vertex_position); + VertexAttributeHandler vertex_position = map.get_attribute("position"); + const StdArray centroid = cgogn::geometry::centroid(map, CMap2::Face(*map.begin()), vertex_position); EXPECT_DOUBLE_EQ(centroid[0], 2.5); EXPECT_DOUBLE_EQ(centroid[1], 1); EXPECT_DOUBLE_EQ(centroid[2], 0); } { - CMap2 map; - cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); - VertexAttributeHandler vertex_position = map.get_attribute("position"); - const EigenVec3d centroid = cgogn::geometry::centroid(map, cgogn::Cell(*map.begin()), vertex_position); - EXPECT_DOUBLE_EQ(centroid[0], 2.5); - EXPECT_DOUBLE_EQ(centroid[1], 1); - EXPECT_DOUBLE_EQ(centroid[2], 0); +// CMap2 map; +// cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); +// VertexAttributeHandler vertex_position = map.get_attribute("position"); +// const EigenVec3d centroid = cgogn::geometry::centroid(map, CMap2::Face(*map.begin()), vertex_position); +// EXPECT_DOUBLE_EQ(centroid[0], 2.5); +// EXPECT_DOUBLE_EQ(centroid[1], 1); +// EXPECT_DOUBLE_EQ(centroid[2], 0); } } @@ -135,9 +135,9 @@ TEST(Algos_TEST, TriangleNormal) { CMap2 map; cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); - VertexAttributeHandler vertex_position = map.get_attribute("position"); - const StdArray& n1 = cgogn::geometry::triangle_normal(map, cgogn::Cell(*map.begin()), vertex_position); - const StdArray& n2 = cgogn::geometry::face_normal(map, cgogn::Cell(*map.begin()), vertex_position); + VertexAttributeHandler vertex_position = map.get_attribute("position"); + const StdArray& n1 = cgogn::geometry::triangle_normal(map, CMap2::Face(*map.begin()), vertex_position); + const StdArray& n2 = cgogn::geometry::face_normal(map, CMap2::Face(*map.begin()), vertex_position); EXPECT_TRUE(cgogn::almost_equal_relative(n1[0], n2[0])); EXPECT_TRUE(cgogn::almost_equal_relative(n1[1], n2[1])); EXPECT_TRUE(cgogn::almost_equal_relative(n1[2], n2[2])); @@ -148,19 +148,19 @@ TEST(Algos_TEST, TriangleNormal) EXPECT_TRUE(cgogn::almost_equal_relative(cross[2], 0.)); } { - CMap2 map; - cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); - VertexAttributeHandler vertex_position = map.get_attribute("position"); - const EigenVec3d& n1 = cgogn::geometry::triangle_normal(map, cgogn::Cell(*map.begin()), vertex_position); - const EigenVec3d& n2 = cgogn::geometry::face_normal(map, cgogn::Cell(*map.begin()), vertex_position); - EXPECT_TRUE(cgogn::almost_equal_relative(n1[0], n2[0])); - EXPECT_TRUE(cgogn::almost_equal_relative(n1[1], n2[1])); - EXPECT_TRUE(cgogn::almost_equal_relative(n1[2], n2[2])); - - const EigenVec3d& cross = n1.cross(EigenVec3d(0,0,1)); - EXPECT_TRUE(cgogn::almost_equal_relative(cross[0], 0.)); - EXPECT_TRUE(cgogn::almost_equal_relative(cross[1], 0.)); - EXPECT_TRUE(cgogn::almost_equal_relative(cross[2], 0.)); +// CMap2 map; +// cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); +// VertexAttributeHandler vertex_position = map.get_attribute("position"); +// const EigenVec3d& n1 = cgogn::geometry::triangle_normal(map, CMap2::Face(*map.begin()), vertex_position); +// const EigenVec3d& n2 = cgogn::geometry::face_normal(map, CMap2::Face(*map.begin()), vertex_position); +// EXPECT_TRUE(cgogn::almost_equal_relative(n1[0], n2[0])); +// EXPECT_TRUE(cgogn::almost_equal_relative(n1[1], n2[1])); +// EXPECT_TRUE(cgogn::almost_equal_relative(n1[2], n2[2])); + +// const EigenVec3d& cross = n1.cross(EigenVec3d(0,0,1)); +// EXPECT_TRUE(cgogn::almost_equal_relative(cross[0], 0.)); +// EXPECT_TRUE(cgogn::almost_equal_relative(cross[1], 0.)); +// EXPECT_TRUE(cgogn::almost_equal_relative(cross[2], 0.)); } } @@ -169,21 +169,21 @@ TEST(Algos_TEST, QuadNormal) { CMap2 map; cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); - VertexAttributeHandler vertex_position = map.get_attribute("position"); - const StdArray& n1 = cgogn::geometry::face_normal(map, cgogn::Cell(*map.begin()), vertex_position); + VertexAttributeHandler vertex_position = map.get_attribute("position"); + const StdArray& n1 = cgogn::geometry::face_normal(map, CMap2::Face(*map.begin()), vertex_position); const StdArray& cross = n1.cross(StdArray(0.,0.,1.)); EXPECT_TRUE(cgogn::almost_equal_relative(cross[0], 0.)); EXPECT_TRUE(cgogn::almost_equal_relative(cross[1], 0.)); EXPECT_TRUE(cgogn::almost_equal_relative(cross[2], 0.)); } { - CMap2 map; - cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); - VertexAttributeHandler vertex_position = map.get_attribute("position"); - const EigenVec3d& n1 = cgogn::geometry::triangle_normal(map, cgogn::Cell(*map.begin()), vertex_position); - const EigenVec3d& cross = n1.cross(EigenVec3d(0,0,1)); - EXPECT_TRUE(cgogn::almost_equal_relative(cross[0], 0.)); - EXPECT_TRUE(cgogn::almost_equal_relative(cross[1], 0.)); - EXPECT_TRUE(cgogn::almost_equal_relative(cross[2], 0.)); +// CMap2 map; +// cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); +// VertexAttributeHandler vertex_position = map.get_attribute("position"); +// const EigenVec3d& n1 = cgogn::geometry::triangle_normal(map, CMap2::Face(*map.begin()), vertex_position); +// const EigenVec3d& cross = n1.cross(EigenVec3d(0,0,1)); +// EXPECT_TRUE(cgogn::almost_equal_relative(cross[0], 0.)); +// EXPECT_TRUE(cgogn::almost_equal_relative(cross[1], 0.)); +// EXPECT_TRUE(cgogn::almost_equal_relative(cross[2], 0.)); } } diff --git a/cgogn/geometry/tests/functions/area_test.cpp b/cgogn/geometry/tests/functions/area_test.cpp index adc43199..8591000e 100644 --- a/cgogn/geometry/tests/functions/area_test.cpp +++ b/cgogn/geometry/tests/functions/area_test.cpp @@ -28,7 +28,7 @@ #include using StdArray = cgogn::geometry::Vec_T>; -using EigenVec3d = Eigen::Vector3d; +//using EigenVec3d = Eigen::Vector3d; TEST(Area_TEST, TriangleArea) { @@ -39,9 +39,9 @@ TEST(Area_TEST, TriangleArea) EXPECT_DOUBLE_EQ(cgogn::geometry::triangle_area(p0,p1,p2), 2.0); } { - EigenVec3d p0(0,0,0); - EigenVec3d p1(2,0,0); - EigenVec3d p2(0,2,0); - EXPECT_DOUBLE_EQ(cgogn::geometry::triangle_area(p0,p1,p2), 2.0); +// EigenVec3d p0(0,0,0); +// EigenVec3d p1(2,0,0); +// EigenVec3d p2(0,2,0); +// EXPECT_DOUBLE_EQ(cgogn::geometry::triangle_area(p0,p1,p2), 2.0); } } diff --git a/cgogn/geometry/tests/functions/normal_test.cpp b/cgogn/geometry/tests/functions/normal_test.cpp index 200e35ea..1fa1b70b 100644 --- a/cgogn/geometry/tests/functions/normal_test.cpp +++ b/cgogn/geometry/tests/functions/normal_test.cpp @@ -29,7 +29,7 @@ #include using StdArray = cgogn::geometry::Vec_T>; -using EigenVec3d = Eigen::Vector3d; +//using EigenVec3d = Eigen::Vector3d; TEST(Normal_TEST, TriangleNormal) { @@ -49,17 +49,17 @@ TEST(Normal_TEST, TriangleNormal) EXPECT_DOUBLE_EQ(n.dot(p2-p1), 0.); } { - EigenVec3d p0(1,3,-5); - EigenVec3d p1(7,-4,0.1); - EigenVec3d p2(-15,-2,15); - EigenVec3d n = cgogn::geometry::triangle_normal(p0,p1,p2); -// EXPECT_TRUE(cgogn::almost_equal_relative(n.dot(p1-p0),0.)); // is false ! - EXPECT_TRUE(cgogn::almost_equal_absolute(n.dot(p1-p0), 0., 1e-8)); - EXPECT_TRUE(cgogn::almost_equal_relative(n.dot(p2-p0), 0.)); - EXPECT_TRUE(cgogn::almost_equal_relative(n.dot(p2-p1), 0.)); -// EXPECT_DOUBLE_EQ(n.dot(p1-p0),0); // is false ! - EXPECT_NEAR(n.dot(p1-p0), 0., 1e-8); - EXPECT_DOUBLE_EQ(n.dot(p2-p0), 0.); - EXPECT_DOUBLE_EQ(n.dot(p2-p1), 0.); +// EigenVec3d p0(1,3,-5); +// EigenVec3d p1(7,-4,0.1); +// EigenVec3d p2(-15,-2,15); +// EigenVec3d n = cgogn::geometry::triangle_normal(p0,p1,p2); +//// EXPECT_TRUE(cgogn::almost_equal_relative(n.dot(p1-p0),0.)); // is false ! +// EXPECT_TRUE(cgogn::almost_equal_absolute(n.dot(p1-p0), 0., 1e-8)); +// EXPECT_TRUE(cgogn::almost_equal_relative(n.dot(p2-p0), 0.)); +// EXPECT_TRUE(cgogn::almost_equal_relative(n.dot(p2-p1), 0.)); +//// EXPECT_DOUBLE_EQ(n.dot(p1-p0),0); // is false ! +// EXPECT_NEAR(n.dot(p1-p0), 0., 1e-8); +// EXPECT_DOUBLE_EQ(n.dot(p2-p0), 0.); +// EXPECT_DOUBLE_EQ(n.dot(p2-p1), 0.); } } diff --git a/cgogn/geometry/tests/types/bounding_box_test.cpp b/cgogn/geometry/tests/types/bounding_box_test.cpp index 3fee62ff..70c49a90 100644 --- a/cgogn/geometry/tests/types/bounding_box_test.cpp +++ b/cgogn/geometry/tests/types/bounding_box_test.cpp @@ -27,14 +27,14 @@ #include using StdArray = cgogn::geometry::Vec_T>; -using EigenVec3d = Eigen::Vector3d; +//using EigenVec3d = Eigen::Vector3d; using BoundingBox_Array = cgogn::geometry::BoundingBox; -using BoundingBox_Eigen = cgogn::geometry::BoundingBox; +//using BoundingBox_Eigen = cgogn::geometry::BoundingBox; TEST(BoundingBox_TEST, NameOfType) { EXPECT_EQ(cgogn::name_of_type(BoundingBox_Array()), "cgogn::geometry::BoundingBox>>"); - EXPECT_EQ(cgogn::name_of_type(BoundingBox_Eigen()), "cgogn::geometry::BoundingBox>"); +// EXPECT_EQ(cgogn::name_of_type(BoundingBox_Eigen()), "cgogn::geometry::BoundingBox>"); } TEST(BoundingBox_TEST, Basics) @@ -55,17 +55,17 @@ TEST(BoundingBox_TEST, Basics) EXPECT_EQ(bb.center(), StdArray({0.,0.,0.})); } { - BoundingBox_Eigen bb; - bb.add_point(EigenVec3d(0.5,0.4,0.3)); - bb.add_point(EigenVec3d(-1,2,-3)); - bb.add_point(EigenVec3d(1,-2,3)); - - EXPECT_EQ(bb.min(), EigenVec3d(-1,-2,-3)); - EXPECT_EQ(bb.max(), EigenVec3d(1,2,3)); - EXPECT_EQ(bb.max_size(), 6); - EXPECT_EQ(bb.min_size(), 2); - EXPECT_TRUE(cgogn::almost_equal_relative(bb.diag_size(), std::sqrt(2.0*2+4*4+6*6))); - EXPECT_EQ(bb.center(), EigenVec3d(0,0,0)); +// BoundingBox_Eigen bb; +// bb.add_point(EigenVec3d(0.5,0.4,0.3)); +// bb.add_point(EigenVec3d(-1,2,-3)); +// bb.add_point(EigenVec3d(1,-2,3)); + +// EXPECT_EQ(bb.min(), EigenVec3d(-1,-2,-3)); +// EXPECT_EQ(bb.max(), EigenVec3d(1,2,3)); +// EXPECT_EQ(bb.max_size(), 6); +// EXPECT_EQ(bb.min_size(), 2); +// EXPECT_TRUE(cgogn::almost_equal_relative(bb.diag_size(), std::sqrt(2.0*2+4*4+6*6))); +// EXPECT_EQ(bb.center(), EigenVec3d(0,0,0)); } } @@ -95,26 +95,26 @@ TEST(BoundingBox_TEST, testing) EXPECT_FALSE(bb.ray_intersect(StdArray({-9.,-9.,-9.}), StdArray({1.,-1.,0.}))); } { - BoundingBox_Eigen bb; - bb.add_point(EigenVec3d(0.5,0.4,0.3)); - bb.add_point(EigenVec3d(-1,2,-3)); - bb.add_point(EigenVec3d(1,-2,3)); +// BoundingBox_Eigen bb; +// bb.add_point(EigenVec3d(0.5,0.4,0.3)); +// bb.add_point(EigenVec3d(-1,2,-3)); +// bb.add_point(EigenVec3d(1,-2,3)); - EXPECT_TRUE(bb.contains(EigenVec3d(1,1,1))); +// EXPECT_TRUE(bb.contains(EigenVec3d(1,1,1))); - BoundingBox_Eigen bb2; - bb2.add_point(EigenVec3d(0,0,0)); - bb2.add_point(EigenVec3d(4,5,2)); +// BoundingBox_Eigen bb2; +// bb2.add_point(EigenVec3d(0,0,0)); +// bb2.add_point(EigenVec3d(4,5,2)); - EXPECT_TRUE(bb.intersects(bb2)); +// EXPECT_TRUE(bb.intersects(bb2)); - BoundingBox_Eigen bb3; - bb3.add_point(EigenVec3d(0,0,0)); - bb3.add_point(EigenVec3d(1,1,1)); +// BoundingBox_Eigen bb3; +// bb3.add_point(EigenVec3d(0,0,0)); +// bb3.add_point(EigenVec3d(1,1,1)); - EXPECT_TRUE(bb.contains(bb3)); +// EXPECT_TRUE(bb.contains(bb3)); - EXPECT_TRUE(bb.ray_intersect(EigenVec3d(-9,-9,-9), EigenVec3d(1,1,1))); - EXPECT_FALSE(bb.ray_intersect(EigenVec3d(-9,-9,-9), EigenVec3d(1,-1,0))); +// EXPECT_TRUE(bb.ray_intersect(EigenVec3d(-9,-9,-9), EigenVec3d(1,1,1))); +// EXPECT_FALSE(bb.ray_intersect(EigenVec3d(-9,-9,-9), EigenVec3d(1,-1,0))); } } diff --git a/cgogn/geometry/tests/types/plane_3d_test.cpp b/cgogn/geometry/tests/types/plane_3d_test.cpp index 156bb91e..8867d4cd 100644 --- a/cgogn/geometry/tests/types/plane_3d_test.cpp +++ b/cgogn/geometry/tests/types/plane_3d_test.cpp @@ -26,14 +26,14 @@ #include using StdArray = cgogn::geometry::Vec_T>; -using EigenVec3d = Eigen::Vector3d; +//using EigenVec3d = Eigen::Vector3d; using Plane3D_Array = cgogn::geometry::Plane3D; -using Plane3D_Eigen = cgogn::geometry::Plane3D; +//using Plane3D_Eigen = cgogn::geometry::Plane3D; TEST(Plane3D_TEST, NameOfType) { EXPECT_EQ(cgogn::name_of_type(Plane3D_Array(StdArray(),0.)), "cgogn::geometry::Plane3D>>"); - EXPECT_EQ(cgogn::name_of_type(Plane3D_Eigen(EigenVec3d(),0.)), "cgogn::geometry::Plane3D>"); +// EXPECT_EQ(cgogn::name_of_type(Plane3D_Eigen(EigenVec3d(),0.)), "cgogn::geometry::Plane3D>"); } TEST(Plane3D_TEST, Project) @@ -47,12 +47,12 @@ TEST(Plane3D_TEST, Project) EXPECT_EQ(p[2], 12.); } { - Plane3D_Eigen plane(EigenVec3d{4,0,0}, EigenVec3d{0,0,0}); - EigenVec3d p{5,8,12}; - plane.project(p); - EXPECT_EQ(p[0], 0.); - EXPECT_EQ(p[1], 8.); - EXPECT_EQ(p[2], 12.); +// Plane3D_Eigen plane(EigenVec3d{4,0,0}, EigenVec3d{0,0,0}); +// EigenVec3d p{5,8,12}; +// plane.project(p); +// EXPECT_EQ(p[0], 0.); +// EXPECT_EQ(p[1], 8.); +// EXPECT_EQ(p[2], 12.); } } @@ -68,12 +68,12 @@ TEST(Plane3D_TEST, Orient) EXPECT_EQ(plane.orient(p3), cgogn::geometry::Orientation3D::ON); } { - Plane3D_Eigen plane(EigenVec3d{0,0,15}, EigenVec3d{0,0,0}); - EigenVec3d p1{546854,864,12}; - EigenVec3d p2{-5,886486,-12}; - EigenVec3d p3{44552,7,0}; - EXPECT_EQ(plane.orient(p1), cgogn::geometry::Orientation3D::OVER); - EXPECT_EQ(plane.orient(p2), cgogn::geometry::Orientation3D::UNDER); - EXPECT_EQ(plane.orient(p3), cgogn::geometry::Orientation3D::ON); +// EigenVec3d p1{546854,864,12}; +// EigenVec3d p2{-5,886486,-12}; +// EigenVec3d p3{44552,7,0}; +// EXPECT_EQ(plane.orient(p1), cgogn::geometry::Orientation3D::OVER); +// EXPECT_EQ(plane.orient(p2), cgogn::geometry::Orientation3D::UNDER); +// Plane3D_Eigen plane(EigenVec3d{0,0,15}, EigenVec3d{0,0,0}); +// EXPECT_EQ(plane.orient(p3), cgogn::geometry::Orientation3D::ON); } } diff --git a/cgogn/geometry/tests/types/vec_test.cpp b/cgogn/geometry/tests/types/vec_test.cpp index f8b7c31a..e3cc6e83 100644 --- a/cgogn/geometry/tests/types/vec_test.cpp +++ b/cgogn/geometry/tests/types/vec_test.cpp @@ -27,38 +27,38 @@ #include using StdArray = cgogn::geometry::Vec_T>; -using EigenVec3d = Eigen::Vector3d; +//using EigenVec3d = Eigen::Vector3d; TEST(VEC_OP_TEST, CGOGN_Typename) { EXPECT_EQ(cgogn::name_of_type(StdArray()),"cgogn::geometry::Vec_T>"); - EXPECT_EQ(cgogn::name_of_type(EigenVec3d()), "Eigen::Matrix"); +// EXPECT_EQ(cgogn::name_of_type(EigenVec3d()), "Eigen::Matrix"); } TEST(VEC_OP_TEST, Constructor) { StdArray vec1{0.,0.,0.}; - EigenVec3d vec2 = {0.,0.,0.}; EXPECT_EQ(vec1[0],0); EXPECT_EQ(vec1[1],0); EXPECT_EQ(vec1[2],0); - EXPECT_EQ(vec2[0],0); - EXPECT_EQ(vec2[1],0); - EXPECT_EQ(vec2[2],0); +// EigenVec3d vec2 = {0.,0.,0.}; +// EXPECT_EQ(vec2[0],0); +// EXPECT_EQ(vec2[1],0); +// EXPECT_EQ(vec2[2],0); } TEST(VEC_OP_TEST, CopyConstructor) { StdArray vec1a = {1.,2., 3.}; StdArray vec1b(vec1a); - EigenVec3d vec2a = {1.,2., 3.}; - EigenVec3d vec2b(vec2a); EXPECT_EQ(vec1a[0], vec1b[0]); EXPECT_EQ(vec1a[1], vec1b[1]); EXPECT_EQ(vec1a[2], vec1b[2]); - EXPECT_EQ(vec2a[0], vec2b[0]); - EXPECT_EQ(vec2a[1], vec2b[1]); - EXPECT_EQ(vec2a[2], vec2b[2]); +// EigenVec3d vec2a = {1.,2., 3.}; +// EigenVec3d vec2b(vec2a); +// EXPECT_EQ(vec2a[0], vec2b[0]); +// EXPECT_EQ(vec2a[1], vec2b[1]); +// EXPECT_EQ(vec2a[2], vec2b[2]); } TEST(VEC_OP_TEST, AssignConstructor) @@ -66,32 +66,31 @@ TEST(VEC_OP_TEST, AssignConstructor) StdArray vec1a = {1.,2., 3.}; StdArray vec1b; vec1b = vec1a; - EigenVec3d vec2a = {1.,2., 3.}; - EigenVec3d vec2b; - vec2b = vec2a; - EXPECT_EQ(vec1a[0], vec1b[0]); EXPECT_EQ(vec1a[1], vec1b[1]); EXPECT_EQ(vec1a[2], vec1b[2]); - EXPECT_EQ(vec2a[0], vec2b[0]); - EXPECT_EQ(vec2a[1], vec2b[1]); - EXPECT_EQ(vec2a[2], vec2b[2]); + +// EigenVec3d vec2a = {1.,2., 3.}; +// EigenVec3d vec2b; +// vec2b = vec2a; +// EXPECT_EQ(vec2a[0], vec2b[0]); +// EXPECT_EQ(vec2a[1], vec2b[1]); +// EXPECT_EQ(vec2a[2], vec2b[2]); } TEST(VEC_OP_TEST, UnaryMinus) { StdArray vec1a = {1.,2., 3.}; StdArray vec1b = -vec1a; - - EigenVec3d vec2a = {1.,2., 3.}; - EigenVec3d vec2b = -vec2a; - EXPECT_EQ(vec1a[0], -vec1b[0]); EXPECT_EQ(vec1a[1], -vec1b[1]); EXPECT_EQ(vec1a[2], -vec1b[2]); - EXPECT_EQ(vec2a[0], -vec2b[0]); - EXPECT_EQ(vec2a[1], -vec2b[1]); - EXPECT_EQ(vec2a[2], -vec2b[2]); + +// EigenVec3d vec2a = {1.,2., 3.}; +// EigenVec3d vec2b = -vec2a; +// EXPECT_EQ(vec2a[0], -vec2b[0]); +// EXPECT_EQ(vec2a[1], -vec2b[1]); +// EXPECT_EQ(vec2a[2], -vec2b[2]); } TEST(VEC_OP_TEST, PlusAssign) @@ -106,12 +105,12 @@ TEST(VEC_OP_TEST, PlusAssign) } { - EigenVec3d a = {1.,2., 3.}; - EigenVec3d b = {1.,2., 3.}; - b += a; - EXPECT_EQ(b[0], 2); - EXPECT_EQ(b[1], 4); - EXPECT_EQ(b[2], 6); +// EigenVec3d a = {1.,2., 3.}; +// EigenVec3d b = {1.,2., 3.}; +// b += a; +// EXPECT_EQ(b[0], 2); +// EXPECT_EQ(b[1], 4); +// EXPECT_EQ(b[2], 6); } } @@ -127,12 +126,12 @@ TEST(VEC_OP_TEST, MinusAssign) } { - EigenVec3d a = {-1.,-2., -3.}; - EigenVec3d b = {1.,2., 3.}; - b -= a; - EXPECT_EQ(b[0], 2); - EXPECT_EQ(b[1], 4); - EXPECT_EQ(b[2], 6); +// EigenVec3d a = {-1.,-2., -3.}; +// EigenVec3d b = {1.,2., 3.}; +// b -= a; +// EXPECT_EQ(b[0], 2); +// EXPECT_EQ(b[1], 4); +// EXPECT_EQ(b[2], 6); } } @@ -147,11 +146,11 @@ TEST(VEC_OP_TEST, MultAssign) } { - EigenVec3d a = {1.,2., 3.}; - a *= 2; - EXPECT_EQ(a[0], 2); - EXPECT_EQ(a[1], 4); - EXPECT_EQ(a[2], 6); +// EigenVec3d a = {1.,2., 3.}; +// a *= 2; +// EXPECT_EQ(a[0], 2); +// EXPECT_EQ(a[1], 4); +// EXPECT_EQ(a[2], 6); } } @@ -166,11 +165,11 @@ TEST(VEC_OP_TEST, DivAssign) } { - EigenVec3d a{2.,4., 6.}; - a /= 2; - EXPECT_EQ(a[0], 1); - EXPECT_EQ(a[1], 2); - EXPECT_EQ(a[2], 3); +// EigenVec3d a{2.,4., 6.}; +// a /= 2; +// EXPECT_EQ(a[0], 1); +// EXPECT_EQ(a[1], 2); +// EXPECT_EQ(a[2], 3); } } @@ -186,12 +185,12 @@ TEST(VEC_OP_TEST, Plus) } { - EigenVec3d a = {1.,2., 3.}; - EigenVec3d b = {1.,2., 3.}; - EigenVec3d c = a+b; - EXPECT_EQ(c[0], 2); - EXPECT_EQ(c[1], 4); - EXPECT_EQ(c[2], 6); +// EigenVec3d a = {1.,2., 3.}; +// EigenVec3d b = {1.,2., 3.}; +// EigenVec3d c = a+b; +// EXPECT_EQ(c[0], 2); +// EXPECT_EQ(c[1], 4); +// EXPECT_EQ(c[2], 6); } } @@ -207,12 +206,12 @@ TEST(VEC_OP_TEST, Minus) } { - EigenVec3d a = {1.,2., 3.}; - EigenVec3d b = {-1.,-2., -3.}; - EigenVec3d c = a-b; - EXPECT_EQ(c[0], 2); - EXPECT_EQ(c[1], 4); - EXPECT_EQ(c[2], 6); +// EigenVec3d a = {1.,2., 3.}; +// EigenVec3d b = {-1.,-2., -3.}; +// EigenVec3d c = a-b; +// EXPECT_EQ(c[0], 2); +// EXPECT_EQ(c[1], 4); +// EXPECT_EQ(c[2], 6); } } @@ -231,25 +230,25 @@ TEST(VEC_OP_TEST, MultScalar) } { - EigenVec3d a = {1.,2., 3.}; - EigenVec3d c = a*2; - EigenVec3d d = 2*a; - EXPECT_EQ(c[0], 2); - EXPECT_EQ(c[1], 4); - EXPECT_EQ(c[2], 6); - EXPECT_EQ(d[0], 2); - EXPECT_EQ(d[1], 4); - EXPECT_EQ(d[2], 6); +// EigenVec3d a = {1.,2., 3.}; +// EigenVec3d c = a*2; +// EigenVec3d d = 2*a; +// EXPECT_EQ(c[0], 2); +// EXPECT_EQ(c[1], 4); +// EXPECT_EQ(c[2], 6); +// EXPECT_EQ(d[0], 2); +// EXPECT_EQ(d[1], 4); +// EXPECT_EQ(d[2], 6); } } TEST(VEC_OP_TEST, Norm2) { StdArray vec1a = {1.,2., 3.}; - EigenVec3d vec2a = {1.,2., 3.}; - EXPECT_EQ(vec1a.squaredNorm(), 14.); - EXPECT_EQ(vec2a.squaredNorm(), 14.); + +// EigenVec3d vec2a = {1.,2., 3.}; +// EXPECT_EQ(vec2a.squaredNorm(), 14.); } TEST(VEC_OP_TEST, Norm) @@ -260,8 +259,8 @@ TEST(VEC_OP_TEST, Norm) } { - EigenVec3d a = {3.,-4., 0.}; - EXPECT_EQ(a.norm(), 5.); +// EigenVec3d a = {3.,-4., 0.}; +// EXPECT_EQ(a.norm(), 5.); } } @@ -277,12 +276,12 @@ TEST(VEC_OP_TEST, Normalize) } { - EigenVec3d a = {3.,-4., 0.}; - a.normalize(); - EXPECT_DOUBLE_EQ(a[0], 3./5.); - EXPECT_DOUBLE_EQ(a[1], -4./5.); - EXPECT_DOUBLE_EQ(a[2], 0.); - EXPECT_DOUBLE_EQ(a.norm(), 1.); +// EigenVec3d a = {3.,-4., 0.}; +// a.normalize(); +// EXPECT_DOUBLE_EQ(a[0], 3./5.); +// EXPECT_DOUBLE_EQ(a[1], -4./5.); +// EXPECT_DOUBLE_EQ(a[2], 0.); +// EXPECT_DOUBLE_EQ(a.norm(), 1.); } } @@ -315,26 +314,24 @@ TEST(VEC_OP_TEST, CrossProduct) } { - EigenVec3d a = {1.,2., 3.}; - EigenVec3d b = {3.,2., 1.}; - EigenVec3d c = a.cross(b); - EXPECT_EQ(c[0], -4.); - EXPECT_EQ(c[1], 8.); - EXPECT_EQ(c[2], -4.); +// EigenVec3d a = {1.,2., 3.}; +// EigenVec3d b = {3.,2., 1.}; +// EigenVec3d c = a.cross(b); +// EXPECT_EQ(c[0], -4.); +// EXPECT_EQ(c[1], 8.); +// EXPECT_EQ(c[2], -4.); } } TEST(VEC_OP_TEST, Equality) { StdArray vec1a = {1.,2., 3.}; - EigenVec3d vec2a = {1.,2., 3.}; - StdArray vec1b = {1.,2., 3.}; - EigenVec3d vec2b = {1.,2., 3.}; - - EXPECT_TRUE(vec1a == vec1b); - EXPECT_TRUE(vec2a == vec2b); + +// EigenVec3d vec2a = {1.,2., 3.}; +// EigenVec3d vec2b = {1.,2., 3.}; +// EXPECT_TRUE(vec2a == vec2b); } TEST(VEC_OP_TEST, DivScalar) @@ -348,10 +345,10 @@ TEST(VEC_OP_TEST, DivScalar) } { - EigenVec3d a = {2. ,4., 6.}; - EigenVec3d c = a/2; - EXPECT_EQ(c[0], 1); - EXPECT_EQ(c[1], 2); - EXPECT_EQ(c[2], 3); +// EigenVec3d a = {2. ,4., 6.}; +// EigenVec3d c = a/2; +// EXPECT_EQ(c[0], 1); +// EXPECT_EQ(c[1], 2); +// EXPECT_EQ(c[2], 3); } } diff --git a/cgogn/geometry/types/bounding_box.cpp b/cgogn/geometry/types/bounding_box.cpp index e7392540..3317ec7b 100644 --- a/cgogn/geometry/types/bounding_box.cpp +++ b/cgogn/geometry/types/bounding_box.cpp @@ -32,8 +32,8 @@ namespace cgogn namespace geometry { -template class CGOGN_GEOMETRY_API BoundingBox; -template class CGOGN_GEOMETRY_API BoundingBox; +//template class CGOGN_GEOMETRY_API BoundingBox; +//template class CGOGN_GEOMETRY_API BoundingBox; template class CGOGN_GEOMETRY_API BoundingBox>>; template class CGOGN_GEOMETRY_API BoundingBox>>; diff --git a/cgogn/geometry/types/bounding_box.h b/cgogn/geometry/types/bounding_box.h index 7bad8f82..6793d21d 100644 --- a/cgogn/geometry/types/bounding_box.h +++ b/cgogn/geometry/types/bounding_box.h @@ -389,8 +389,8 @@ std::istream& operator>>(std::istream& in, BoundingBox& bb) } #if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(GEOMETRY_BOUNDING_BOX_CPP_)) -extern template class CGOGN_GEOMETRY_API BoundingBox; -extern template class CGOGN_GEOMETRY_API BoundingBox; +//extern template class CGOGN_GEOMETRY_API BoundingBox; +//extern template class CGOGN_GEOMETRY_API BoundingBox; extern template class CGOGN_GEOMETRY_API BoundingBox>>; extern template class CGOGN_GEOMETRY_API BoundingBox>>; #endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(GEOMETRY_BOUNDING_BOX_CPP_)) diff --git a/cgogn/io/examples/cmap2_import.cpp b/cgogn/io/examples/cmap2_import.cpp index eca85c62..0dcbcff5 100644 --- a/cgogn/io/examples/cmap2_import.cpp +++ b/cgogn/io/examples/cmap2_import.cpp @@ -18,7 +18,8 @@ struct MyMapTraits : public cgogn::DefaultMapTraits using Map2 = cgogn::CMap2; -using Vec3 = Eigen::Vector3d; +//using Vec3 = Eigen::Vector3d; +using Vec3 = cgogn::geometry::Vec_T>; template using VertexAttributeHandler = Map2::VertexAttributeHandler; diff --git a/cgogn/io/examples/cmap3_import.cpp b/cgogn/io/examples/cmap3_import.cpp index 9b3a7e4e..fa12afe7 100644 --- a/cgogn/io/examples/cmap3_import.cpp +++ b/cgogn/io/examples/cmap3_import.cpp @@ -11,8 +11,8 @@ using Map3 = cgogn::CMap3; -using Vec3 = Eigen::Vector3d; -//using Vec3 = std::array; +//using Vec3 = Eigen::Vector3d; +using Vec3 = cgogn::geometry::Vec_T>; template using VertexAttributeHandler = Map3::VertexAttributeHandler; diff --git a/cgogn/rendering/examples/simple_viewer.cpp b/cgogn/rendering/examples/simple_viewer.cpp index b8d30db4..1004f9e8 100644 --- a/cgogn/rendering/examples/simple_viewer.cpp +++ b/cgogn/rendering/examples/simple_viewer.cpp @@ -42,8 +42,8 @@ #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) using Map2 = cgogn::CMap2; -using Vec3 = Eigen::Vector3d; -//using Vec3 = cgogn::geometry::Vec_T>; +//using Vec3 = Eigen::Vector3d; +using Vec3 = cgogn::geometry::Vec_T>; template using VertexAttributeHandler = Map2::VertexAttributeHandler; @@ -89,8 +89,8 @@ void Viewer::import(const std::string& surfaceMesh) { cgogn::io::import_surface(map_, surfaceMesh); - vertex_position_ = map_.get_attribute("position"); - vertex_normal_ = map_.add_attribute("normal"); + vertex_position_ = map_.get_attribute("position"); + vertex_normal_ = map_.add_attribute("normal"); cgogn::geometry::compute_normal_vertices(map_, vertex_position_, vertex_normal_); cgogn::geometry::compute_bounding_box(vertex_position_, bb_); diff --git a/cgogn/rendering/map_render.h b/cgogn/rendering/map_render.h index 3b3a62da..00a5dea4 100644 --- a/cgogn/rendering/map_render.h +++ b/cgogn/rendering/map_render.h @@ -87,8 +87,8 @@ class MapRender // table_indices.reserve(m.get_nb_darts()/2); m.foreach_cell([&] (typename MAP::Edge e) { - table_indices.push_back(m.template get_embedding(e.dart)); - table_indices.push_back(m.template get_embedding(m.phi1(e.dart))); + table_indices.push_back(m.template get_embedding(e.dart)); + table_indices.push_back(m.template get_embedding(m.phi1(e.dart))); }); } @@ -102,12 +102,12 @@ class MapRender Dart d = f; Dart d1 = m.phi1(d); Dart d2 = m.phi1(d1); - unsigned int d_e = m.template get_embedding(d); - unsigned int d1_e = m.template get_embedding(d1); + unsigned int d_e = m.template get_embedding(d); + unsigned int d1_e = m.template get_embedding(d1); unsigned int d2_e; do { - d2_e = m.template get_embedding(d2); + d2_e = m.template get_embedding(d2); table_indices.push_back(d_e); table_indices.push_back(d1_e); From f2e1234c99e181656d82ddd35a4199ecda1eb4b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Mon, 22 Feb 2016 17:36:09 +0100 Subject: [PATCH 133/402] added CGOGN_PATH (avoid bug when CGoGN is included in another project) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- CMakeLists.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 12b93c2d..d693ac85 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,8 @@ if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release") endif() - +#### CGoGN PATH +set(CGOGN_PATH "${CMAKE_CURRENT_SOURCE_DIR}") #### Here are located the FindPackages that we need list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules") @@ -27,7 +28,7 @@ include(cmake/EnableCoverageReport.cmake) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) -set(CGOGN_SOURCE_DIR ${CMAKE_SOURCE_DIR}/cgogn) +set(CGOGN_SOURCE_DIR ${CGOGN_PATH}/cgogn) ### External Templates option(CGOGN_EXTERNAL_TEMPLATES "Use external templates to reduce compile time" OFF) @@ -36,7 +37,7 @@ if(${CGOGN_EXTERNAL_TEMPLATES}) endif() #### ThirdParty options -set(CGOGN_THIRDPARTY_DIR ${CMAKE_SOURCE_DIR}/thirdparty) +set(CGOGN_THIRDPARTY_DIR ${CGOGN_PATH}/thirdparty) option(CGOGN_PROVIDE_EIGEN "Use the version of eigen that is packaged with CGoGN." ON) option(CGOGN_PROVIDE_TINYXML2 "Use the version of tinyxml2 that is packaged with CGoGN." ON) option(CGOGN_BUILD_TESTS "Build cgogn unit tests using google test framework." ON) From 785c7c764a326298eb4c1825420d7cb4e6a18bfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Mon, 22 Feb 2016 17:44:43 +0100 Subject: [PATCH 134/402] fixed compilation with EXTERN_TEMPLATES MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/cmap0.cpp | 12 ++++++------ cgogn/core/cmap/cmap0.h | 4 ++-- cgogn/core/cmap/cmap1.cpp | 8 ++++---- cgogn/core/cmap/cmap1.h | 8 ++++---- cgogn/core/cmap/cmap2.cpp | 16 ++++++++-------- cgogn/core/cmap/cmap2.h | 16 ++++++++-------- 6 files changed, 32 insertions(+), 32 deletions(-) diff --git a/cgogn/core/cmap/cmap0.cpp b/cgogn/core/cmap/cmap0.cpp index 51c4b83a..e6eda691 100644 --- a/cgogn/core/cmap/cmap0.cpp +++ b/cgogn/core/cmap/cmap0.cpp @@ -29,11 +29,11 @@ namespace cgogn { - template class CGOGN_CORE_API CMap0_T>; - template class CGOGN_CORE_API DartMarker>; - template class CGOGN_CORE_API DartMarkerStore>; - template class CGOGN_CORE_API DartMarkerNoUnmark>; - template class CGOGN_CORE_API CellMarker, Orbit::DART>; - template class CGOGN_CORE_API CellMarkerStore, Orbit::DART>; + template class CGOGN_CORE_API CMap0_T>; + template class CGOGN_CORE_API DartMarker>; + template class CGOGN_CORE_API DartMarkerStore>; + template class CGOGN_CORE_API DartMarkerNoUnmark>; + template class CGOGN_CORE_API CellMarker, CMap0::Vertex::ORBIT>; + template class CGOGN_CORE_API CellMarkerStore, CMap0::Vertex::ORBIT>; } // namespace cgogn diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index a77dfea6..b90f277b 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -156,8 +156,8 @@ extern template class CGOGN_CORE_API CMap0_T>; extern template class CGOGN_CORE_API DartMarkerStore>; extern template class CGOGN_CORE_API DartMarkerNoUnmark>; -extern template class CGOGN_CORE_API CellMarker, Vertex::ORBIT>; -extern template class CGOGN_CORE_API CellMarkerStore, Vertex::ORBIT>; +extern template class CGOGN_CORE_API CellMarker, CMap0::Vertex::ORBIT>; +extern template class CGOGN_CORE_API CellMarkerStore, CMap0::Vertex::ORBIT>; #endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_MAP_MAP0_CPP_)) } // namespace cgogn diff --git a/cgogn/core/cmap/cmap1.cpp b/cgogn/core/cmap/cmap1.cpp index 6f588f7a..6558862f 100644 --- a/cgogn/core/cmap/cmap1.cpp +++ b/cgogn/core/cmap/cmap1.cpp @@ -33,9 +33,9 @@ namespace cgogn template class CGOGN_CORE_API DartMarker>; template class CGOGN_CORE_API DartMarkerStore>; template class CGOGN_CORE_API DartMarkerNoUnmark>; - template class CGOGN_CORE_API CellMarker, Orbit::DART>; - template class CGOGN_CORE_API CellMarker, Orbit::PHI1>; - template class CGOGN_CORE_API CellMarkerStore, Orbit::DART>; - template class CGOGN_CORE_API CellMarkerStore, Orbit::PHI1>; + template class CGOGN_CORE_API CellMarker, CMap1::Vertex::ORBIT>; + template class CGOGN_CORE_API CellMarker, CMap1::Face::ORBIT>; + template class CGOGN_CORE_API CellMarkerStore, CMap1::Vertex::ORBIT>; + template class CGOGN_CORE_API CellMarkerStore, CMap1::Face::ORBIT>; } // namespace cgogn diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 76271721..2ea5125b 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -423,10 +423,10 @@ extern template class CGOGN_CORE_API CMap1_T>; extern template class CGOGN_CORE_API DartMarkerStore>; extern template class CGOGN_CORE_API DartMarkerNoUnmark>; -extern template class CGOGN_CORE_API CellMarker, Vertex::ORBIT>; -extern template class CGOGN_CORE_API CellMarker, Face::ORBIT>; -extern template class CGOGN_CORE_API CellMarkerStore, Vertex::ORBIT>; -extern template class CGOGN_CORE_API CellMarkerStore, Face::ORBIT>; +extern template class CGOGN_CORE_API CellMarker, CMap1::Vertex::ORBIT>; +extern template class CGOGN_CORE_API CellMarker, CMap1::Face::ORBIT>; +extern template class CGOGN_CORE_API CellMarkerStore, CMap1::Vertex::ORBIT>; +extern template class CGOGN_CORE_API CellMarkerStore, CMap1::Face::ORBIT>; #endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_MAP_MAP1_CPP_)) } // namespace cgogn diff --git a/cgogn/core/cmap/cmap2.cpp b/cgogn/core/cmap/cmap2.cpp index aaef2d8f..c477312f 100644 --- a/cgogn/core/cmap/cmap2.cpp +++ b/cgogn/core/cmap/cmap2.cpp @@ -33,13 +33,13 @@ namespace cgogn template class CGOGN_CORE_API DartMarker>; template class CGOGN_CORE_API DartMarkerStore>; template class CGOGN_CORE_API DartMarkerNoUnmark>; - template class CGOGN_CORE_API CellMarker, Orbit::PHI21>; - template class CGOGN_CORE_API CellMarker, Orbit::PHI2>; - template class CGOGN_CORE_API CellMarker, Orbit::PHI1>; - template class CGOGN_CORE_API CellMarker, Orbit::PHI1_PHI2>; - template class CGOGN_CORE_API CellMarkerStore, Orbit::PHI21>; - template class CGOGN_CORE_API CellMarkerStore, Orbit::PHI2>; - template class CGOGN_CORE_API CellMarkerStore, Orbit::PHI1>; - template class CGOGN_CORE_API CellMarkerStore, Orbit::PHI1_PHI2>; + template class CGOGN_CORE_API CellMarker, CMap2::Vertex::ORBIT>; + template class CGOGN_CORE_API CellMarker, CMap2::Edge::ORBIT>; + template class CGOGN_CORE_API CellMarker, CMap2::Face::ORBIT>; + template class CGOGN_CORE_API CellMarker, CMap2::Volume::ORBIT>; + template class CGOGN_CORE_API CellMarkerStore, CMap2::Vertex::ORBIT>; + template class CGOGN_CORE_API CellMarkerStore, CMap2::Edge::ORBIT>; + template class CGOGN_CORE_API CellMarkerStore, CMap2::Face::ORBIT>; + template class CGOGN_CORE_API CellMarkerStore, CMap2::Volume::ORBIT>; } // namespace cgogn diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 47fe7c8a..6fc37229 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -826,14 +826,14 @@ extern template class CGOGN_CORE_API CMap2_T>; extern template class CGOGN_CORE_API DartMarkerStore>; extern template class CGOGN_CORE_API DartMarkerNoUnmark>; -extern template class CGOGN_CORE_API CellMarker, Vertex::ORBIT>; -extern template class CGOGN_CORE_API CellMarker, Edge::ORBIT>; -extern template class CGOGN_CORE_API CellMarker, Face::ORBIT>; -extern template class CGOGN_CORE_API CellMarker, Volume::ORBIT>; -extern template class CGOGN_CORE_API CellMarkerStore, Vertex::ORBIT>; -extern template class CGOGN_CORE_API CellMarkerStore, Edge::ORBIT>; -extern template class CGOGN_CORE_API CellMarkerStore, Face::ORBIT>; -extern template class CGOGN_CORE_API CellMarkerStore, Volume::ORBIT>; +extern template class CGOGN_CORE_API CellMarker, CMap2::Vertex::ORBIT>; +extern template class CGOGN_CORE_API CellMarker, CMap2::Edge::ORBIT>; +extern template class CGOGN_CORE_API CellMarker, CMap2::Face::ORBIT>; +extern template class CGOGN_CORE_API CellMarker, CMap2::Volume::ORBIT>; +extern template class CGOGN_CORE_API CellMarkerStore, CMap2::Vertex::ORBIT>; +extern template class CGOGN_CORE_API CellMarkerStore, CMap2::Edge::ORBIT>; +extern template class CGOGN_CORE_API CellMarkerStore, CMap2::Face::ORBIT>; +extern template class CGOGN_CORE_API CellMarkerStore, CMap2::Volume::ORBIT>; #endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_MAP_MAP2_CPP_)) } // namespace cgogn From e4b6b28782910b434610faf4faa3de53819cd4d4 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Mon, 22 Feb 2016 17:49:09 +0100 Subject: [PATCH 135/402] To merge Etienne --- cgogn/core/basic/dart_marker.h | 20 ++------------------ cgogn/core/cmap/cmap2.h | 4 ++-- cgogn/core/cmap/cmap3.h | 10 +++++----- cgogn/core/cmap/map_base.h | 8 ++++---- cgogn/core/examples/map/map.cpp | 11 +++++++---- 5 files changed, 20 insertions(+), 33 deletions(-) diff --git a/cgogn/core/basic/dart_marker.h b/cgogn/core/basic/dart_marker.h index 8bf027e2..5f39b709 100644 --- a/cgogn/core/basic/dart_marker.h +++ b/cgogn/core/basic/dart_marker.h @@ -32,23 +32,8 @@ namespace cgogn { -//class CGOGN_CORE_API DartMarkerGen -//{ -//public: -// using Self = DartMarkerGen; -// DartMarkerGen() -// {} - -// virtual ~DartMarkerGen(); - -// DartMarkerGen(const Self& dm) = delete; -// DartMarkerGen(Self&& dm) = delete; -// DartMarkerGen& operator=(Self&& dm) = delete; -// DartMarkerGen& operator=(const Self& dm) = delete; -//}; - template -class DartMarker_T // : public DartMarkerGen +class DartMarker_T { public: @@ -63,13 +48,12 @@ class DartMarker_T // : public DartMarkerGen public: DartMarker_T(const MAP& map) : -// Inherit(), map_(const_cast(map)) { mark_attribute_ = map_.get_topology_mark_attribute(); } - virtual ~DartMarker_T() // override + virtual ~DartMarker_T() { if (MapGen::is_alive(&map_)) map_.release_topology_mark_attribute(mark_attribute_); diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 47fe7c8a..a470432d 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -717,11 +717,11 @@ class CMap2_T : public CMap1_T } template - inline void foreach_incident_face(Volume v, const FUNC& f) const + inline void foreach_incident_face(Volume w, const FUNC& f) const { static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); DartMarkerStore marker(*this); - foreach_dart_of_orbit(v, [&] (Dart d) + foreach_dart_of_orbit(w, [&] (Dart d) { if (!marker.is_marked(d)) { diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 98d0b0f6..3b5c2857 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -421,13 +421,13 @@ class CMap3_T : public CMap2_T { f((*marked_darts)[i]); - Dart d2 = this->phi2((*marked_darts)[i]); - Dart d21 = this->phi1(d2); // turn in volume - Dart d23 = phi3(d2); // change volume + Dart d1 = this->phi1((*marked_darts)[i]); + Dart d21 = this->phi2(d1); // turn in volume + Dart d31 = phi3(d1); // change volume if(!marker.is_marked(d21)) marker.mark(d21); - if(!marker.is_marked(d23)) - marker.mark(d23); + if(!marker.is_marked(d31)) + marker.mark(d31); } } diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index e689cd37..ef4acee6 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -495,15 +495,15 @@ class MapBase : public MapBaseData * @param c1 first cell to compare * @param c2 second cell to compare */ - template - bool same_cell(Cell c1, Cell c2) const + template + bool same_cell(CellType c1, CellType c2) const { - if (this->template is_embedded>()) + if (this->template is_embedded()) return this->get_embedding(c1) == this->get_embedding(c2); const ConcreteMap* cmap = to_concrete(); bool result = false; - cmap->template foreach_dart_of_orbit_until(c1, [&] (Dart d) -> bool + cmap->foreach_dart_of_orbit_until(c1, [&] (Dart d) -> bool { if (d == c2.dart) { diff --git a/cgogn/core/examples/map/map.cpp b/cgogn/core/examples/map/map.cpp index 67f28d20..985858ee 100644 --- a/cgogn/core/examples/map/map.cpp +++ b/cgogn/core/examples/map/map.cpp @@ -56,13 +56,16 @@ void fonc_non_const(typename MAP::template VertexAttributeHandler& ah) template int test1(MAP& map) { + using Vertex = typename MAP::Vertex; + using Face = typename MAP::Face; + // add an attribute on vertex of map with - typename MAP::template VertexAttributeHandler ah = map.template add_attribute("floats"); + typename MAP::template VertexAttributeHandler ah = map.template add_attribute("floats"); - typename MAP::template FaceAttributeHandler ahf = map.template add_attribute("floats"); + typename MAP::template FaceAttributeHandler ahf = map.template add_attribute("floats"); // get attribute and change type (dangerous!) - typename MAP::template VertexAttributeHandler ahf2 = map.template get_attribute_force_type("floats"); + typename MAP::template VertexAttributeHandler ahf2 = map.template get_attribute_force_type("floats"); map.remove_attribute(ahf); std::cout << "ahf valid : " << std::boolalpha << ahf.is_valid() << std::endl; @@ -100,7 +103,7 @@ int test1(MAP& map) std::cout << "End Darts" << std::endl; std::cout << "Vertices :" << std::endl; - map.foreach_cell([&] (typename MAP::Vertex v) + map.foreach_cell([&] (Vertex v) { std::cout << v << std::endl; ah[v] = 2.0f; From 71b18b2d8206288c90d312fcd8e512413aa48473 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Mon, 22 Feb 2016 18:27:07 +0100 Subject: [PATCH 136/402] has_degree function --- cgogn/core/cmap/cmap1.h | 15 ++++++++++++--- cgogn/io/map_export.h | 7 ------- cgogn/rendering/map_render.h | 5 ++--- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 748a2600..5d1d8bbc 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -173,7 +173,6 @@ class CMap1_T : public MapBase */ inline Dart add_dart() { - CGOGN_CHECK_CONCRETE_TYPE; unsigned int di = this->add_topology_element(); Dart d(di); (*phi1_)[di] = d; @@ -328,9 +327,19 @@ class CMap1_T : public MapBase return this->nb_darts(f); } - inline bool is_triangle(Face f) + + inline bool has_degree(Face f, unsigned int degree) { - return (f.dart == phi1(phi1(phi1(f.dart)))); + Dart it = f.dart ; + for (unsigned int i=1;i ids = map.template add_attribute("indices"); - std::chrono::time_point start, end; - start = std::chrono::system_clock::now(); - ids.set_all_container_values(UINT_MAX); - end = std::chrono::system_clock::now(); - std::chrono::duration elapsed_seconds = end - start; - std::cout << "set_all_container_values: " << elapsed_seconds.count() << "s\n"; - unsigned int count = 0; static const unsigned int BUFFER_SZ = 1024*1024; diff --git a/cgogn/rendering/map_render.h b/cgogn/rendering/map_render.h index 0ea0f23a..bc4045c3 100644 --- a/cgogn/rendering/map_render.h +++ b/cgogn/rendering/map_render.h @@ -93,7 +93,6 @@ class MapRender }); } -// template template void init_triangles(MAP& m, std::vector& table_indices, const typename MAP::template VertexAttributeHandler& position) { @@ -101,7 +100,7 @@ class MapRender // table_indices.reserve(m.get_nb_darts()/3); m.template foreach_cell([&] (typename MAP::Face f) { - if (m.is_triangle(f)) + if (m.has_degree(f,3)) { table_indices.push_back(m.template get_embedding(f.dart)); table_indices.push_back(m.template get_embedding(m.phi1(f.dart))); @@ -109,7 +108,7 @@ class MapRender } else { - cgogn::geometry::compute_ear_triangulation(m,f,position,table_indices); +cgogn::geometry::compute_ear_triangulation(m,f,position,table_indices); } }); } From 55984cf21c516718c142d93b3cce92a410c68a38 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Mon, 22 Feb 2016 18:31:11 +0100 Subject: [PATCH 137/402] has_degree ... --- cgogn/geometry/algos/ear_triangulation.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cgogn/geometry/algos/ear_triangulation.h b/cgogn/geometry/algos/ear_triangulation.h index f725baa7..dfba5244 100644 --- a/cgogn/geometry/algos/ear_triangulation.h +++ b/cgogn/geometry/algos/ear_triangulation.h @@ -245,7 +245,7 @@ class EarTriangulation positions_(position), ears_(cmp_VP) { - if (map_.is_triangle(f)) + if (map_.has_degree(f,3)) { face_ = f; nb_verts_ = 3; @@ -437,7 +437,7 @@ static void apply_ear_triangulations(MAP& map, const typename MAP::template Vert { map.template foreach_cell([&] (typename MAP::Face f) { - if (!map.is_triangle(f)) + if (!map.has_degree(f,3)) { EarTriangulation tri(map, f, position); tri.triangulate(); From 52b42fb2c084c199cfec3cba53e62f324972c23e Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Mon, 22 Feb 2016 18:32:18 +0100 Subject: [PATCH 138/402] To merge Etienne --- cgogn/core/cmap/cmap2.h | 63 +++++++++++++++++++++++++-------- cgogn/core/cmap/map_base.h | 4 --- cgogn/geometry/algos/area.h | 3 +- cgogn/geometry/algos/centroid.h | 3 +- 4 files changed, 52 insertions(+), 21 deletions(-) diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 1f1ce42f..850432c6 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -207,13 +207,13 @@ class CMap2_T : public CMap1_T { CGOGN_CHECK_CONCRETE_TYPE; - const CDart ne = cut_edge_topo(e); - const CDart nf = phi2(e); - const CDart f = phi2(ne); + const Dart ne = cut_edge_topo(e); + const Dart nf = phi2(e); + const Dart f = phi2(ne); if (this->template is_embedded()) { - this->new_embedding(ne); - this->new_embedding(nf); + this->new_embedding(CDart(ne)); + this->new_embedding(CDart(nf)); } if (this->template is_embedded()) @@ -297,34 +297,34 @@ class CMap2_T : public CMap1_T CGOGN_CHECK_CONCRETE_TYPE; cut_face_topo(d,e); - CDart nd = this->phi_1(d); - CDart ne = this->phi_1(e); + Dart nd = this->phi_1(d); + Dart ne = this->phi_1(e); if (this->template is_embedded()) { - this->new_embedding(nd); - this->new_embedding(ne); + this->new_embedding(CDart(nd)); + this->new_embedding(CDart(ne)); } if (this->template is_embedded()) { - this->copy_embedding(Vertex(nd.dart), e); - this->copy_embedding(Vertex(ne.dart), d); + this->copy_embedding(Vertex(nd), e); + this->copy_embedding(Vertex(ne), d); } if (this->template is_embedded()) { - this->new_orbit_embedding(Edge(nd.dart)); + this->new_orbit_embedding(Edge(nd)); } if (this->template is_embedded()) { - this->copy_embedding(Face(nd.dart), Face(d.dart)); - this->new_orbit_embedding(Face(ne.dart)); + this->copy_embedding(Face(nd), Face(d.dart)); + this->new_orbit_embedding(Face(ne)); } if (this->template is_embedded()) { - unsigned int idx = this->copy_embedding(Volume(nd.dart), Volume(d.dart)); + unsigned int idx = this->copy_embedding(Volume(nd), Volume(d.dart)); this->set_embedding(Volume(ne), idx); } } @@ -644,6 +644,39 @@ class CMap2_T : public CMap1_T public: + template + inline void foreach_incident_cell(CellIn c, const FUNC& func) const + { + using CellOut = typename function_traits::template arg<0>::type; + + static_assert((CellIn::ORBIT == Vertex::ORBIT && CellOut::ORBIT == Edge::ORBIT) || + (CellIn::ORBIT == Vertex::ORBIT && CellOut::ORBIT == Face::ORBIT) || + (CellIn::ORBIT == Edge::ORBIT && CellOut::ORBIT == Vertex::ORBIT) || + (CellIn::ORBIT == Edge::ORBIT && CellOut::ORBIT == Face::ORBIT) || + (CellIn::ORBIT == Face::ORBIT && CellOut::ORBIT == Vertex::ORBIT) || + (CellIn::ORBIT == Face::ORBIT && CellOut::ORBIT == Edge::ORBIT) || + (CellIn::ORBIT == Volume::ORBIT && CellOut::ORBIT == Vertex::ORBIT) || + (CellIn::ORBIT == Volume::ORBIT && CellOut::ORBIT == Edge::ORBIT) || + (CellIn::ORBIT == Volume::ORBIT && CellOut::ORBIT == Face::ORBIT) + , "Undefined incidence relation"); + + if (CellIn::ORBIT == Volume::ORBIT) { + DartMarkerStore marker(*this); + foreach_dart_of_orbit(c, [&] (CellOut d) + { + if (!marker.is_marked(d)) + { + marker.template mark_orbit(d); + func(d); + } + }); + + } + else { + foreach_dart_of_orbit(c, func); + } + } + template inline void foreach_incident_edge(Vertex v, const FUNC& func) const { diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index ef4acee6..428c0b16 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -403,10 +403,6 @@ class MapBase : public MapBaseData ConcreteMap* cmap = to_concrete(); foreach_cell([cmap, &counter] (Cell c) { - // Je ne comprends pas cet algo ?! (David) - // foreach_cell passe une seule fois par cellule ? => counter[c] est toujours nul - // En plus le brin c pourrait être n'importe quel brin de la cellule - // donc on peut passer plusieurs fois par la cellule, en comptant des brins distincts if (counter[c] > 0) cmap->new_orbit_embedding(c); counter[c]++; diff --git a/cgogn/geometry/algos/area.h b/cgogn/geometry/algos/area.h index 5ba8bd0b..8c1ef42e 100644 --- a/cgogn/geometry/algos/area.h +++ b/cgogn/geometry/algos/area.h @@ -52,7 +52,8 @@ inline typename VEC3_T::Scalar convex_face_area(const MAP& map, typename MAP::Fa { typename VEC3_T::Scalar area{0}; VEC3_T center = centroid(map, f, position); - map.foreach_incident_edge(f, [&] (typename MAP::Edge e) +// map.foreach_incident_edge(f, [&] (typename MAP::Edge e) + map.foreach_incident_cell(f, [&] (typename MAP::Edge e) { area += triangle_area(center, position[e.dart], position[map.phi1(e.dart)]); }); diff --git a/cgogn/geometry/algos/centroid.h b/cgogn/geometry/algos/centroid.h index 5feb5eea..d77c0165 100644 --- a/cgogn/geometry/algos/centroid.h +++ b/cgogn/geometry/algos/centroid.h @@ -38,7 +38,8 @@ inline T centroid(const MAP& map, Cell c, const typename MAP::template Ve T result; result.setZero(); unsigned int count = 0; - map.foreach_incident_vertex(c, [&] (typename MAP::Vertex v) +// map.foreach_incident_vertex(c, [&] (typename MAP::Vertex v) + map.foreach_incident_cell(c, [&] (typename MAP::Vertex v) { result += attribute[v]; ++count; From 01305b73a87b65b0b02e96f4ff58682aac1fcbb5 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Mon, 22 Feb 2016 18:51:10 +0100 Subject: [PATCH 139/402] Debug Test CMap1 --- cgogn/core/tests/cmap/cmap1_test.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cgogn/core/tests/cmap/cmap1_test.cpp b/cgogn/core/tests/cmap/cmap1_test.cpp index f4d925fc..4bcb037a 100644 --- a/cgogn/core/tests/cmap/cmap1_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_test.cpp @@ -50,6 +50,8 @@ class CMap1Test: public ::testing::Test TEST_F(CMap1Test, addFace) { + cmap_.add_attribute("int"); + Face f = cmap_.add_face(10); cmap_.split_vertex(Vertex(f.dart)); From ad289d3936f8d08d1549e901f471f513e05e3bb2 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Mon, 22 Feb 2016 19:52:01 +0100 Subject: [PATCH 140/402] Update cmap2.h Bug correction --- cgogn/core/cmap/cmap2.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 850432c6..708990fd 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -372,22 +372,23 @@ class CMap2_T : public CMap1_T foreach_dart_of_orbit(f, [this] (CDart d) { this->new_embedding(d); + this->new_embedding(phi2(d)); }); if (this->template is_embedded()) foreach_dart_of_orbit(f, [this] (Vertex v) { - this->new_embedding(v); + this->new_orbit_embedding(v); }); if (this->template is_embedded()) foreach_dart_of_orbit(f, [this] (Edge e) { - this->new_embedding(e); + this->new_orbit_embedding(e); }); if (this->template is_embedded()) - this->new_embedding(f); + this->new_orbit_embedding(f); if (this->template is_embedded()) this->new_orbit_embedding(Volume(f.dart)); From 21ba33c6bffbd0362e5bf4524565375149b2bd98 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Tue, 23 Feb 2016 00:06:00 +0100 Subject: [PATCH 141/402] Removed foreach_incident_cell Signed-off-by: Etienne Schmitt --- cgogn/core/cmap/cmap2.h | 33 --------------------------------- cgogn/geometry/algos/area.h | 3 +-- cgogn/geometry/algos/centroid.h | 3 +-- 3 files changed, 2 insertions(+), 37 deletions(-) diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 708990fd..c677f095 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -645,39 +645,6 @@ class CMap2_T : public CMap1_T public: - template - inline void foreach_incident_cell(CellIn c, const FUNC& func) const - { - using CellOut = typename function_traits::template arg<0>::type; - - static_assert((CellIn::ORBIT == Vertex::ORBIT && CellOut::ORBIT == Edge::ORBIT) || - (CellIn::ORBIT == Vertex::ORBIT && CellOut::ORBIT == Face::ORBIT) || - (CellIn::ORBIT == Edge::ORBIT && CellOut::ORBIT == Vertex::ORBIT) || - (CellIn::ORBIT == Edge::ORBIT && CellOut::ORBIT == Face::ORBIT) || - (CellIn::ORBIT == Face::ORBIT && CellOut::ORBIT == Vertex::ORBIT) || - (CellIn::ORBIT == Face::ORBIT && CellOut::ORBIT == Edge::ORBIT) || - (CellIn::ORBIT == Volume::ORBIT && CellOut::ORBIT == Vertex::ORBIT) || - (CellIn::ORBIT == Volume::ORBIT && CellOut::ORBIT == Edge::ORBIT) || - (CellIn::ORBIT == Volume::ORBIT && CellOut::ORBIT == Face::ORBIT) - , "Undefined incidence relation"); - - if (CellIn::ORBIT == Volume::ORBIT) { - DartMarkerStore marker(*this); - foreach_dart_of_orbit(c, [&] (CellOut d) - { - if (!marker.is_marked(d)) - { - marker.template mark_orbit(d); - func(d); - } - }); - - } - else { - foreach_dart_of_orbit(c, func); - } - } - template inline void foreach_incident_edge(Vertex v, const FUNC& func) const { diff --git a/cgogn/geometry/algos/area.h b/cgogn/geometry/algos/area.h index 8c1ef42e..5ba8bd0b 100644 --- a/cgogn/geometry/algos/area.h +++ b/cgogn/geometry/algos/area.h @@ -52,8 +52,7 @@ inline typename VEC3_T::Scalar convex_face_area(const MAP& map, typename MAP::Fa { typename VEC3_T::Scalar area{0}; VEC3_T center = centroid(map, f, position); -// map.foreach_incident_edge(f, [&] (typename MAP::Edge e) - map.foreach_incident_cell(f, [&] (typename MAP::Edge e) + map.foreach_incident_edge(f, [&] (typename MAP::Edge e) { area += triangle_area(center, position[e.dart], position[map.phi1(e.dart)]); }); diff --git a/cgogn/geometry/algos/centroid.h b/cgogn/geometry/algos/centroid.h index d77c0165..5feb5eea 100644 --- a/cgogn/geometry/algos/centroid.h +++ b/cgogn/geometry/algos/centroid.h @@ -38,8 +38,7 @@ inline T centroid(const MAP& map, Cell c, const typename MAP::template Ve T result; result.setZero(); unsigned int count = 0; -// map.foreach_incident_vertex(c, [&] (typename MAP::Vertex v) - map.foreach_incident_cell(c, [&] (typename MAP::Vertex v) + map.foreach_incident_vertex(c, [&] (typename MAP::Vertex v) { result += attribute[v]; ++count; From 21e662563b395ecf990cead2ddf6509506db409a Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Tue, 23 Feb 2016 00:11:58 +0100 Subject: [PATCH 142/402] Fixed Map2 Import and various improvements. Signed-off-by: Etienne Schmitt --- cgogn/core/cmap/cmap1.h | 2 +- cgogn/core/cmap/cmap2.h | 27 +++++++++++++-------------- cgogn/core/cmap/cmap2_builder.h | 8 ++++---- cgogn/core/cmap/cmap3.h | 2 +- cgogn/core/cmap/map_base.h | 10 ++++------ cgogn/core/tests/cmap/cmap1_test.cpp | 8 +++++--- cgogn/io/surface_import.h | 22 +++++++++++----------- cgogn/multiresolution/cph/ihcmap2.h | 2 +- 8 files changed, 40 insertions(+), 41 deletions(-) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 2ea5125b..35974d58 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -347,7 +347,7 @@ class CMap1_T : public CMap0_T switch (ORBIT) { - case Orbit::DART: this->foreach_dart_of_DART(c, f); break; + case Orbit::DART: f(c.dart); break; case Orbit::PHI1: foreach_dart_of_PHI1(c, f); break; case Orbit::PHI2: case Orbit::PHI1_PHI2: diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index c677f095..4f01ca22 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -207,40 +207,39 @@ class CMap2_T : public CMap1_T { CGOGN_CHECK_CONCRETE_TYPE; - const Dart ne = cut_edge_topo(e); + const Vertex v = cut_edge_topo(e); const Dart nf = phi2(e); - const Dart f = phi2(ne); + const Dart f = phi2(v); if (this->template is_embedded()) { - this->new_embedding(CDart(ne)); + this->new_embedding(CDart(v)); this->new_embedding(CDart(nf)); } if (this->template is_embedded()) { - const unsigned int idx = this->new_embedding(Vertex(ne)); - this->set_embedding(Vertex(nf), idx); + this->new_embedding(Vertex(v)); } if (this->template is_embedded()) { this->copy_embedding(Edge(nf), e); - this->new_orbit_embedding(Edge(ne)); + this->new_orbit_embedding(Edge(v)); } if (this->template is_embedded()) { - this->copy_embedding(Face(ne), Face(e)); + this->copy_embedding(Face(v), Face(e)); this->copy_embedding(Face(nf), Face(f)); } if (this->template is_embedded()) { - this->copy_embedding(Volume(ne),Volume(e)); + this->copy_embedding(Volume(v),Volume(e)); this->copy_embedding(Volume(nf), Volume(e)); } - return Vertex(ne); + return v; } protected: @@ -324,8 +323,8 @@ class CMap2_T : public CMap1_T if (this->template is_embedded()) { - unsigned int idx = this->copy_embedding(Volume(nd), Volume(d.dart)); - this->set_embedding(Volume(ne), idx); + this->copy_embedding(Volume(nd), Volume(d.dart)); + this->copy_embedding(Volume(ne), Volume(d.dart)); } } @@ -366,7 +365,7 @@ class CMap2_T : public CMap1_T { CGOGN_CHECK_CONCRETE_TYPE; - Face f = add_face_topo(size); + const Face f = add_face_topo(size); if (this->template is_embedded()) foreach_dart_of_orbit(f, [this] (CDart d) @@ -549,7 +548,7 @@ class CMap2_T : public CMap1_T switch (ORBIT) { - case Orbit::DART: this->foreach_dart_of_DART(c, f); break; + case Orbit::DART: f(c.dart); break; case Orbit::PHI1: this->foreach_dart_of_PHI1(c, f); break; case Orbit::PHI2: foreach_dart_of_PHI2(c, f); break; case Orbit::PHI1_PHI2: foreach_dart_of_PHI1_PHI2(c, f); break; @@ -627,7 +626,7 @@ class CMap2_T : public CMap1_T switch (ORBIT) { - case Orbit::DART: this->foreach_dart_of_DART(c, f); break; + case Orbit::DART: f(c.dart); break; case Orbit::PHI1: this->foreach_dart_of_PHI1_until(c, f); break; case Orbit::PHI2: foreach_dart_of_PHI2_until(c, f); break; case Orbit::PHI1_PHI2: foreach_dart_of_PHI1_PHI2_until(c, f); break; diff --git a/cgogn/core/cmap/cmap2_builder.h b/cgogn/core/cmap/cmap2_builder.h index c863c5c9..04c0649d 100644 --- a/cgogn/core/cmap/cmap2_builder.h +++ b/cgogn/core/cmap/cmap2_builder.h @@ -63,9 +63,9 @@ class CMap2Builder_T } template - inline void set_embedding(Dart d, unsigned int emb) + inline void set_embedding(Cell c, unsigned int emb) { - map_.template set_embedding(d, emb); + map_.set_embedding(c, emb); } inline void phi2_sew(Dart d, Dart e) @@ -78,9 +78,9 @@ class CMap2Builder_T map_.phi2_unsew(d); } - inline Dart add_face_topo(unsigned int nb_edges) + inline Dart add_face_topo_parent(unsigned int nb_edges) { - return map_.add_face_topo(nb_edges); + return map_.CMap2::Inherit::add_face_topo(nb_edges); } inline void close_map() diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 3b5c2857..b7b152f5 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -478,7 +478,7 @@ class CMap3_T : public CMap2_T switch (ORBIT) { - case Orbit::DART: this->foreach_dart_of_DART(c, f); break; + case Orbit::DART: f(c.dart); break; case Orbit::PHI1: this->foreach_dart_of_PHI1(c, f); break; case Orbit::PHI2: this->foreach_dart_of_PHI2(c, f); break; case Orbit::PHI1_PHI2: this->foreach_dart_of_PHI1_PHI2(c, f); break; diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 9516609f..f03b028f 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -154,9 +154,9 @@ class MapBase : public MapBaseData inline unsigned int add_topology_element() { - unsigned int idx = this->topology_.template insert_lines(); + const unsigned int idx = this->topology_.template insert_lines(); this->topology_.init_markers_of_line(idx); - for (unsigned int orbit = 0; orbit < NB_ORBITS; ++orbit) + for (unsigned int orbit = 0u; orbit < NB_ORBITS; ++orbit) { if (this->embeddings_[orbit]) (*this->embeddings_[orbit])[idx] = EMBNULL; @@ -359,11 +359,9 @@ class MapBase : public MapBaseData } template - inline unsigned int copy_embedding(Cell c, Cell d) + inline void copy_embedding(Cell dest, Cell src) { - unsigned int emb = this->template get_embedding(d.dart); - this->template set_embedding(c.dart, emb); - return emb; + this->set_embedding(dest, this->get_embedding(src)); } // template diff --git a/cgogn/core/tests/cmap/cmap1_test.cpp b/cgogn/core/tests/cmap/cmap1_test.cpp index 4bcb037a..b331760c 100644 --- a/cgogn/core/tests/cmap/cmap1_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_test.cpp @@ -50,13 +50,15 @@ class CMap1Test: public ::testing::Test TEST_F(CMap1Test, addFace) { - cmap_.add_attribute("int"); - + cmap_.add_attribute("int_f"); + cmap_.add_attribute("int_v"); Face f = cmap_.add_face(10); - cmap_.split_vertex(Vertex(f.dart)); + cmap_.cut_edge(f.dart); + EXPECT_TRUE(is_well_embedded(cmap_)); + EXPECT_TRUE(is_well_embedded(cmap_)); EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); EXPECT_TRUE(is_container_well_referenced(cmap_)); diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index 54c8edcb..13c0e613 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -63,6 +63,7 @@ class SurfaceImport using Self = SurfaceImport; using Map = CMap2; + using Vertex = typename Map::Vertex; static const unsigned int CHUNK_SIZE = MAP_TRAITS::CHUNK_SIZE; @@ -153,7 +154,6 @@ class SurfaceImport void create_map(Map& map) { using MapBuilder = cgogn::CMap2Builder_T; - const Orbit VERTEX = Map::Vertex::ORBIT; if (this->nb_vertices_ == 0u) return; @@ -161,11 +161,11 @@ class SurfaceImport MapBuilder mbuild(map); map.clear_and_remove_attributes(); - mbuild.template create_embedding(); - mbuild.template swap_chunk_array_container(this->vertex_attributes_); + mbuild.template create_embedding(); + mbuild.template swap_chunk_array_container(this->vertex_attributes_); VertexAttributeHandler> darts_per_vertex = - map.template add_attribute, VERTEX>("darts_per_vertex"); + map.template add_attribute, Vertex::ORBIT>("darts_per_vertex"); unsigned int faces_vertex_index = 0; std::vector vertices_buffer; @@ -193,11 +193,11 @@ class SurfaceImport nbe = static_cast(vertices_buffer.size()); if (nbe > 2) { - Dart d = mbuild.add_face_topo(nbe); - for (unsigned int j = 0; j < nbe; ++j) + Dart d = mbuild.add_face_topo_parent(nbe); + for (unsigned int j = 0u; j < nbe; ++j) { - unsigned int vertex_index = vertices_buffer[j]; - mbuild.template set_embedding(d, vertex_index); + const unsigned int vertex_index = vertices_buffer[j]; + mbuild.set_embedding(Vertex(d), vertex_index); darts_per_vertex[vertex_index].push_back(d); d = map.phi1(d); } @@ -211,7 +211,7 @@ class SurfaceImport { if (map.phi2(d) == d) { - unsigned int vertex_index = map.template get_embedding(d); + unsigned int vertex_index = map.get_embedding(Vertex(d)); std::vector& next_vertex_darts = darts_per_vertex[map.phi1(d)]; bool phi2_found = false; @@ -221,7 +221,7 @@ class SurfaceImport it != next_vertex_darts.end() && !phi2_found; ++it) { - if (map.template get_embedding(map.phi1(*it)) == vertex_index) + if (map.get_embedding(Vertex(map.phi1(*it))) == vertex_index) { if (map.phi2(*it) == *it) { @@ -247,7 +247,7 @@ class SurfaceImport mbuild.close_map(); if (need_vertex_unicity_check) - map.template enforce_unique_orbit_embedding(); + map.template enforce_unique_orbit_embedding(); map.remove_attribute(darts_per_vertex); this->clear(); diff --git a/cgogn/multiresolution/cph/ihcmap2.h b/cgogn/multiresolution/cph/ihcmap2.h index 28889c6b..bdfbcb09 100644 --- a/cgogn/multiresolution/cph/ihcmap2.h +++ b/cgogn/multiresolution/cph/ihcmap2.h @@ -354,7 +354,7 @@ class IHCMap2_T : public CMap2_T, public CPH2 "Orbit not supported in a CMap2"); switch (ORBIT) { - case Orbit::DART: this->foreach_dart_of_DART(c, f); break; + case Orbit::DART: f(c.dart); break; case Orbit::PHI1: foreach_dart_of_PHI1(c, f); break; case Orbit::PHI2: foreach_dart_of_PHI2(c, f); break; case Orbit::PHI1_PHI2: foreach_dart_of_PHI1_PHI2(c, f); break; From 84fc2416c87a8a16554589fb9dd5436da4b3a011 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Tue, 23 Feb 2016 00:13:41 +0100 Subject: [PATCH 143/402] fixed typos. Signed-off-by: Etienne Schmitt --- cgogn/core/cmap/cmap2.h | 2 +- cgogn/core/tests/cmap/cmap1_test.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 4f01ca22..ae8906d6 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -371,7 +371,7 @@ class CMap2_T : public CMap1_T foreach_dart_of_orbit(f, [this] (CDart d) { this->new_embedding(d); - this->new_embedding(phi2(d)); + this->new_embedding(CDart(phi2(d))); }); if (this->template is_embedded()) diff --git a/cgogn/core/tests/cmap/cmap1_test.cpp b/cgogn/core/tests/cmap/cmap1_test.cpp index b331760c..882d9f83 100644 --- a/cgogn/core/tests/cmap/cmap1_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_test.cpp @@ -54,7 +54,7 @@ TEST_F(CMap1Test, addFace) cmap_.add_attribute("int_v"); Face f = cmap_.add_face(10); - cmap_.cut_edge(f.dart); + cmap_.split_vertex(f.dart); EXPECT_TRUE(is_well_embedded(cmap_)); From 9d0131b0ca48ce31b5231989842672b22792d55f Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Tue, 23 Feb 2016 00:33:51 +0100 Subject: [PATCH 144/402] remove explicit template parameters when possible. Signed-off-by: Etienne Schmitt --- cgogn/core/cmap/cmap2.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index ae8906d6..e2adef66 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -721,7 +721,7 @@ class CMap2_T : public CMap1_T { static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); DartMarkerStore marker(*this); - foreach_dart_of_orbit(w, [&] (Dart d) + foreach_dart_of_orbit(w, [&] (Dart d) { if (!marker.is_marked(d)) { @@ -749,7 +749,7 @@ class CMap2_T : public CMap1_T foreach_dart_of_orbit(v, [this, &f] (Dart vd) { Dart vd1 = this->phi1(vd); - this->foreach_dart_of_orbit(vd, [&f, vd, vd1] (Dart fd) + this->foreach_dart_of_orbit(Face(vd), [&f, vd, vd1] (Dart fd) { // skip Vertex v itself and its first successor around current face if (fd != vd && fd != vd1) @@ -764,7 +764,7 @@ class CMap2_T : public CMap1_T static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); foreach_dart_of_orbit(e, [&f, this] (Dart ed) { - this->foreach_dart_of_orbit(ed, [&f, ed] (Dart vd) + this->foreach_dart_of_orbit(Vertex(ed), [&f, ed] (Dart vd) { // skip Edge e itself if (vd != ed) @@ -779,7 +779,7 @@ class CMap2_T : public CMap1_T static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); foreach_dart_of_orbit(e, [&f, this] (Dart ed) { - this->foreach_dart_of_orbit(ed, [&f, ed] (Dart fd) + this->foreach_dart_of_orbit(Face(ed), [&f, ed] (Dart fd) { // skip Edge e itself if (fd != ed) @@ -795,7 +795,7 @@ class CMap2_T : public CMap1_T foreach_dart_of_orbit(f, [this, &func] (Dart fd) { Dart fd1 = this->phi2(this->phi_1(fd)); - this->foreach_dart_of_orbit(fd, [&func, fd, fd1] (Dart vd) + this->foreach_dart_of_orbit(Vertex(fd), [&func, fd, fd1] (Dart vd) { // skip Face f itself and its first successor around current vertex if (vd != fd && vd != fd1) From 97506832471adeb2f661d7aa6574c9b4bd52d402 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Tue, 23 Feb 2016 01:20:53 +0100 Subject: [PATCH 145/402] Removed foreach_dart_of_DART Signed-off-by: Etienne Schmitt --- cgogn/core/cmap/cmap0.h | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index b90f277b..cecd568e 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -127,18 +127,11 @@ class CMap0_T : public MapBase *******************************************************************************/ protected: - - template - inline void foreach_dart_of_DART(Dart d, const FUNC& f) const - { - f(d); - } - template inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const { static_assert(ORBIT == Orbit::DART, "Orbit not supported in a CMap0"); - this->foreach_dart_of_DART(c, f); + f(c.dart); } }; From 482904108731b404d462e3ca03d417d72b34e840 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Tue, 23 Feb 2016 01:21:19 +0100 Subject: [PATCH 146/402] some work on cmap3 Signed-off-by: Etienne Schmitt --- cgogn/core/cmap/cmap3.h | 118 ++++++++++++++--------------- cgogn/core/cmap/cmap3_builder.h | 3 +- cgogn/core/cmap/map_base.h | 7 +- cgogn/io/examples/cmap3_import.cpp | 11 +-- cgogn/io/volume_import.h | 12 +-- 5 files changed, 75 insertions(+), 76 deletions(-) diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index b7b152f5..04d0b0ce 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -51,16 +51,14 @@ class CMap3_T : public CMap2_T template friend class DartMarker_T; template friend class DartMarkerStore; - static const Orbit DART = Orbit::DART; - static const Orbit VERTEX = Orbit::PHI21_PHI31; - static const Orbit EDGE = Orbit::PHI2_PHI3; - static const Orbit FACE = Orbit::PHI1_PHI3; - static const Orbit VOLUME = Orbit::PHI1_PHI2; - - using Vertex = Cell; - using Edge = Cell; - using Face = Cell; - using Volume = Cell; + using CDart = typename Inherit::CDart; + using Vertex = Cell; + using Edge = Cell; + using Face = Cell; + using Volume = Cell; + using Vertex2 = typename Inherit::Vertex; + using Edge2 = typename Inherit::Edge; + using Face2 = typename Inherit::Face; template using ChunkArray = typename Inherit::template ChunkArray; @@ -70,13 +68,13 @@ class CMap3_T : public CMap2_T template using AttributeHandler = typename Inherit::template AttributeHandler; template - using VertexAttributeHandler = AttributeHandler; + using VertexAttributeHandler = AttributeHandler; template - using EdgeAttributeHandler = AttributeHandler; + using EdgeAttributeHandler = AttributeHandler; template - using FaceAttributeHandler = AttributeHandler; + using FaceAttributeHandler = AttributeHandler; template - using VolumeAttributeHandler = AttributeHandler; + using VolumeAttributeHandler = AttributeHandler; using DartMarker = typename cgogn::DartMarker; using DartMarkerStore = typename cgogn::DartMarkerStore; @@ -188,7 +186,7 @@ class CMap3_T : public CMap2_T // creation of triangles around circunference and storing vertices for (unsigned int i = 0u; i < n; ++i) { - m_tableVertDarts.push_back(this->add_face_topo(3u)); + m_tableVertDarts.push_back(this->Inherit::Inherit::add_face_topo(3u)); } // sewing the triangles @@ -203,7 +201,7 @@ class CMap3_T : public CMap2_T this->phi2_sew(this->phi1(m_tableVertDarts[0ul]), this->phi_1(m_tableVertDarts[n-1u])); //sewing the bottom face - Dart base = this->add_face_topo(n); + Dart base = this->Inherit::Inherit::add_face_topo(n); const Dart dres = base; for(unsigned int i = 0u; i < n; ++i) { @@ -228,7 +226,7 @@ class CMap3_T : public CMap2_T // creation of quads around circunference and storing vertices for (unsigned int i = 0u; i < n; ++i) { - m_tableVertDarts.emplace_back(this->add_face_topo(4)); + m_tableVertDarts.emplace_back(this->Inherit::Inherit::add_face_topo(4)); } // storing a dart from the vertex pointed by phi1(phi1(d)) @@ -248,8 +246,8 @@ class CMap3_T : public CMap2_T this->phi2_sew(this->phi1(m_tableVertDarts[0]), this->phi_1(m_tableVertDarts[n-1u])); //sewing the top & bottom faces - Dart top = this->add_face_topo(n); - Dart bottom = this->add_face_topo(n); + Dart top = this->Inherit::Inherit::add_face_topo(n); + Dart bottom = this->Inherit::Inherit::add_face_topo(n); const Dart dres = top; for(unsigned int i = 0u; i < n; ++i) { @@ -283,7 +281,7 @@ class CMap3_T : public CMap2_T Dart it = visitedFaces[i]; Dart f = it; - const Dart b = this->add_face_topo(this->degree(Face(f))); + const Dart b = this->Inherit::Inherit::add_face_topo(this->degree(Face(f))); boundary_marker.template mark_orbit(b); ++count; @@ -338,59 +336,59 @@ class CMap3_T : public CMap2_T close_hole_topo(d); const Volume new_volume = phi3(d); - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) foreach_dart_of_orbit(new_volume, [this] (Dart d) { - this->template new_embedding(d); + this->new_embedding(CDart(d)); }); - if (this->template is_orbit_embedded()) - Inherit::foreach_incident_vertex(new_volume, [this] (Cell v) + if (this->template is_embedded()) + Inherit::foreach_incident_vertex(new_volume, [this] (Vertex2 v) { this->new_orbit_embedding(v); }); - if (this->template is_orbit_embedded()) - Inherit::foreach_incident_edge(new_volume, [this] (Cell e) + if (this->template is_embedded()) + Inherit::foreach_incident_edge(new_volume, [this] (Edge2 e) { this->new_orbit_embedding(e); }); - if (this->template is_orbit_embedded()) // cmap2 faces + if (this->template is_embedded()) { - Inherit::foreach_incident_face(new_volume, [this] (Cell f) + Inherit::foreach_incident_face(new_volume, [this] (Face2 f) { this->new_orbit_embedding(f); }); } - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) { - foreach_dart_of_orbit(new_volume, [this] (Dart wd) + foreach_dart_of_orbit(new_volume, [this] (Dart wd) { - this->template copy_embedding(wd, this->phi1(phi3(wd))); + this->copy_embedding(Vertex(wd), Vertex(this->phi1(phi3(wd)))); }); } - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) { - foreach_dart_of_orbit(new_volume, [this] (Dart wd) + foreach_dart_of_orbit(new_volume, [this] (Dart wd) { - this->template copy_embedding(wd, phi3(wd)); + this->copy_embedding(Edge(wd), Edge(phi3(wd))); }); } - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) { - foreach_dart_of_orbit(new_volume, [this] (Dart wd) + foreach_dart_of_orbit(new_volume, [this] (Dart wd) { - this->template copy_embedding(wd, phi3(wd)); + this->copy_embedding(Face(wd), Face(phi3(wd))); }); } - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) { - this->template new_orbit_embedding(new_volume); + this->new_orbit_embedding(new_volume); } } } @@ -711,14 +709,14 @@ class CMap3_T : public CMap2_T { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); DartMarker marker_vertex(*this); - marker_vertex.mark_orbit(v); + marker_vertex.mark_orbit(v); foreach_incident_face(v, [&] (Face inc_face) { foreach_incident_vertex(inc_face, [&] (Vertex vertex_of_face) { if (!marker_vertex.is_marked(vertex_of_face)) { - marker_vertex.mark_orbit(vertex_of_face); + marker_vertex.mark_orbit(vertex_of_face); f(vertex_of_face); } }); @@ -730,14 +728,14 @@ class CMap3_T : public CMap2_T { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); DartMarker marker_vertex(*this); - marker_vertex.mark_orbit(v); + marker_vertex.mark_orbit(v); foreach_incident_volume(v, [&] (Volume inc_vol) { foreach_incident_vertex(inc_vol, [&] (Vertex inc_vert) { if (!marker_vertex.is_marked(inc_vert)) { - marker_vertex.mark_orbit(inc_vert); + marker_vertex.mark_orbit(inc_vert); f(inc_vert); } }); @@ -763,14 +761,14 @@ class CMap3_T : public CMap2_T { static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); DartMarker marker_edge(*this); - marker_edge.mark_orbit(e); + marker_edge.mark_orbit(e); foreach_incident_face(e, [&] (Face inc_face) { foreach_incident_edge(inc_face, [&] (Edge inc_edge) { if (!marker_edge.is_marked(inc_edge)) { - marker_edge.mark_orbit(inc_edge); + marker_edge.mark_orbit(inc_edge); f(inc_edge); } }); @@ -782,14 +780,14 @@ class CMap3_T : public CMap2_T { static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); DartMarker marker_edge(*this); - marker_edge.mark_orbit(e); + marker_edge.mark_orbit(e); foreach_incident_volume(e, [&] (Volume inc_vol) { foreach_incident_edge(inc_vol, [&] (Edge inc_edge) { if (!marker_edge.is_marked(inc_edge)) { - marker_edge.mark_orbit(inc_edge); + marker_edge.mark_orbit(inc_edge); f(inc_edge); } }); @@ -801,14 +799,14 @@ class CMap3_T : public CMap2_T { static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); DartMarker marker_face(*this); - marker_face.mark_orbit(f); + marker_face.mark_orbit(f); foreach_incident_vertex(f, [&] (Vertex v) { foreach_incident_face(f, [&](Face inc_fac) { if (!marker_face.is_marked(inc_fac)) { - marker_face.mark_orbit(inc_fac); + marker_face.mark_orbit(inc_fac); func(inc_fac); } }); @@ -834,21 +832,21 @@ class CMap3_T : public CMap2_T { static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); DartMarker marker_face(*this); - marker_face.mark_orbit(f); - foreach_incident_face(f.dart, [&] (Face inc_face) + marker_face.mark_orbit(f); + foreach_incident_face(Volume(f.dart), [&] (Face inc_face) { if (!marker_face.is_marked(inc_face)) { - marker_face.mark_orbit((inc_face)); + marker_face.mark_orbit((inc_face)); func(inc_face); } }); - foreach_incident_face(phi3(f), [&] (Face inc_face) + foreach_incident_face(Volume(phi3(f)), [&] (Face inc_face) { if (!marker_face.is_marked(inc_face)) { - marker_face.mark_orbit((inc_face)); + marker_face.mark_orbit((inc_face)); func(inc_face); } }); @@ -859,14 +857,14 @@ class CMap3_T : public CMap2_T { static_assert(check_func_parameter_type(FUNC, Volume), "Wrong function cell parameter type"); DartMarker marker_volume(*this); - marker_volume.mark_orbit(v); + marker_volume.mark_orbit(v); foreach_incident_vertex(v, [&] (Vertex inc_vert) { foreach_incident_volume(inc_vert, [&](Volume inc_vol) { if (!marker_volume.is_marked(inc_vol)) { - marker_volume.mark_orbit(inc_vol); + marker_volume.mark_orbit(inc_vol); f(inc_vol); } }); @@ -878,14 +876,14 @@ class CMap3_T : public CMap2_T { static_assert(check_func_parameter_type(FUNC, Volume), "Wrong function cell parameter type"); DartMarker marker_volume(*this); - marker_volume.mark_orbit(v); + marker_volume.mark_orbit(v); foreach_incident_edge(v, [&] (Edge inc_edge) { foreach_incident_volume(inc_edge, [&] (Volume inc_vol) { if (!marker_volume.is_marked(inc_vol)) { - marker_volume.mark_orbit(inc_vol); + marker_volume.mark_orbit(inc_vol); f(inc_vol); } }); @@ -897,14 +895,14 @@ class CMap3_T : public CMap2_T { static_assert(check_func_parameter_type(FUNC, Volume), "Wrong function cell parameter type"); DartMarker marker_volume(*this); - marker_volume.mark_orbit(v); + marker_volume.mark_orbit(v); foreach_incident_face(v, [&] (Edge inc_face) { foreach_incident_volume(inc_face, [&] (Volume inc_vol) { if (!marker_volume.is_marked(inc_vol)) { - marker_volume.mark_orbit(inc_vol); + marker_volume.mark_orbit(inc_vol); f(inc_vol); } }); diff --git a/cgogn/core/cmap/cmap3_builder.h b/cgogn/core/cmap/cmap3_builder.h index f321872b..e2e4c846 100644 --- a/cgogn/core/cmap/cmap3_builder.h +++ b/cgogn/core/cmap/cmap3_builder.h @@ -36,6 +36,7 @@ class CMap3Builder_T using Self = CMap3Builder_T; using CMap3 = cgogn::CMap3; + using Vertex = typename CMap3::Vertex; template using ChunkArrayContainer = typename CMap3::template ChunkArrayContainer; @@ -66,7 +67,7 @@ class CMap3Builder_T { map_.foreach_dart_of_PHI21(d, [&] (Dart dit) { - map_.template set_embedding(dit, emb); + map_.template set_embedding(Vertex(dit), emb); }); } diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index f03b028f..b23ec235 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -376,10 +376,9 @@ class MapBase : public MapBaseData template inline unsigned int new_orbit_embedding(Cell c) { - unsigned int emb = add_attribute_element(); - ConcreteMap* cmap = to_concrete(); - cmap->foreach_dart_of_orbit(c, [cmap, emb] (Dart d) { - cmap->template set_embedding(d, emb); + const unsigned int emb = add_attribute_element(); + to_concrete()->foreach_dart_of_orbit(c, [this, emb] (Dart d) { + this->template set_embedding(d, emb); }); return emb; } diff --git a/cgogn/io/examples/cmap3_import.cpp b/cgogn/io/examples/cmap3_import.cpp index fa12afe7..94e839f3 100644 --- a/cgogn/io/examples/cmap3_import.cpp +++ b/cgogn/io/examples/cmap3_import.cpp @@ -19,6 +19,7 @@ using VertexAttributeHandler = Map3::VertexAttributeHandler; template using FaceAttributeHandler = Map3::FaceAttributeHandler; + int main(int argc, char** argv) { std::string volumeMesh; @@ -40,12 +41,12 @@ int main(int argc, char** argv) std::chrono::time_point start, end; start = std::chrono::system_clock::now(); - VertexAttributeHandler vertex_position = map.get_attribute("position"); + VertexAttributeHandler vertex_position = map.get_attribute("position"); - map.enable_topo_cache(); - map.enable_topo_cache(); - map.enable_topo_cache(); - map.enable_topo_cache(); + map.enable_topo_cache(); + map.enable_topo_cache(); + map.enable_topo_cache(); + map.enable_topo_cache(); unsigned int nbw = 0u; diff --git a/cgogn/io/volume_import.h b/cgogn/io/volume_import.h index e80b15ab..45d15051 100644 --- a/cgogn/io/volume_import.h +++ b/cgogn/io/volume_import.h @@ -54,6 +54,7 @@ class VolumeImport using Self = VolumeImport; using Map = CMap3; + using Vertex = typename Map::Vertex; static const unsigned int CHUNK_SIZE = MAP_TRAITS::CHUNK_SIZE; @@ -135,7 +136,6 @@ class VolumeImport bool create_map(Map& map) { - const Orbit VERTEX = Map::VERTEX; using Face = typename Map::Face; if (this->nb_vertices_ == 0u) @@ -144,9 +144,9 @@ class VolumeImport MapBuilder mbuild(map); map.clear_and_remove_attributes(); - mbuild.template create_embedding(); - mbuild.template swap_chunk_array_container(this->vertex_attributes_); - VertexAttributeHandler> darts_per_vertex = map.template add_attribute, VERTEX>("darts_per_vertex"); + mbuild.template create_embedding(); + mbuild.template swap_chunk_array_container(this->vertex_attributes_); + VertexAttributeHandler> darts_per_vertex = map.template add_attribute, Vertex::ORBIT>("darts_per_vertex"); unsigned int index = 0u; // buffer for tempo faces (used to remove degenerated edges) @@ -297,8 +297,8 @@ class VolumeImport Dart good_dart; for(auto it = vec.begin(); it != vec.end() && good_dart.is_nil(); ++it) { - if(map.template get_embedding(map.phi1(*it)) == map.template get_embedding(d) && - map.template get_embedding(map.phi_1(*it)) == map.template get_embedding(map.phi1(map.phi1(d)))) + if(map.get_embedding(Vertex(map.phi1(*it))) == map.get_embedding(Vertex(d)) && + map.get_embedding(Vertex(map.phi_1(*it))) == map.get_embedding(Vertex(map.phi1(map.phi1(d))))) { good_dart = *it; } From fc462061b5f5cafcb981bc65428e526aacef6291 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Tue, 23 Feb 2016 17:12:33 +0100 Subject: [PATCH 147/402] small fix. Signed-off-by: Etienne Schmitt --- cgogn/core/utils/definitions.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cgogn/core/utils/definitions.h b/cgogn/core/utils/definitions.h index 41079635..52840b57 100644 --- a/cgogn/core/utils/definitions.h +++ b/cgogn/core/utils/definitions.h @@ -140,7 +140,6 @@ #define CGOGN_LITTLE_ENDIAN 1234 #define CGOGN_BIG_ENDIAN 4321 -#define CGOGN_ENDIANNESS 0 #if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \ defined(__BYTE_ORDER__) && __BYTE_ORDER__ ==__ORDER_BIG_ENDIAN__ || \ @@ -160,7 +159,7 @@ defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) #define CGOGN_ENDIANNESS CGOGN_LITTLE_ENDIAN #else -#error "Unable to determine the architecture." +#define CGOGN_ENDIANNESS 0 #endif #endif From bc53123fa97285930f50b2753776795f671dbe99 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Tue, 23 Feb 2016 17:18:58 +0100 Subject: [PATCH 148/402] added inclusion.h Signed-off-by: Etienne Schmitt --- cgogn/geometry/CMakeLists.txt | 1 + cgogn/geometry/algos/ear_triangulation.h | 6 +-- cgogn/geometry/functions/inclusion.h | 65 ++++++++++++++++++++++++ cgogn/geometry/functions/orientation.h | 26 ---------- 4 files changed, 69 insertions(+), 29 deletions(-) create mode 100644 cgogn/geometry/functions/inclusion.h diff --git a/cgogn/geometry/CMakeLists.txt b/cgogn/geometry/CMakeLists.txt index 63713b62..3631febf 100644 --- a/cgogn/geometry/CMakeLists.txt +++ b/cgogn/geometry/CMakeLists.txt @@ -12,6 +12,7 @@ set(HEADER_FILES functions/area.h functions/normal.h functions/orientation.h + functions/inclusion.h types/bounding_box.h types/eigen.h types/geometry_traits.h diff --git a/cgogn/geometry/algos/ear_triangulation.h b/cgogn/geometry/algos/ear_triangulation.h index c06833e2..0a4b7dd0 100644 --- a/cgogn/geometry/algos/ear_triangulation.h +++ b/cgogn/geometry/algos/ear_triangulation.h @@ -24,11 +24,11 @@ #ifndef GEOMETRY_ALGOS_EAR_TRIANGULATION_H_ #define GEOMETRY_ALGOS_EAR_TRIANGULATION_H_ -#include -#include - #include +#include +#include + namespace cgogn { diff --git a/cgogn/geometry/functions/inclusion.h b/cgogn/geometry/functions/inclusion.h new file mode 100644 index 00000000..691b3712 --- /dev/null +++ b/cgogn/geometry/functions/inclusion.h @@ -0,0 +1,65 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef GEOMETRY_INCLUSION_H_ +#define GEOMETRY_INCLUSION_H_ + +#include +#include + +namespace cgogn +{ + +namespace geometry +{ + + +template +inline bool in_triangle(const VEC3_T& P, const VEC3_T& normal, const VEC3_T& Ta, const VEC3_T& Tb, const VEC3_T& Tc) +{ + using Scalar = typename vector_traits::Scalar; + static const auto triple_positive = [] (const VEC3_T& U, const VEC3_T& V, const VEC3_T& W) -> bool + { + return U.dot(V.cross(W)) >= Scalar(0); + }; + + if (triple_positive(P-Ta, Tb-Ta, normal) || + triple_positive(P-Tb, Tc-Tb, normal) || + triple_positive(P-Tc, Ta-Tc, normal) ) + return false; + + return true; +} + +template +inline bool in_triangle(const VEC3_T& P, const VEC3_T& Ta, const VEC3_T& Tb, const VEC3_T& Tc) +{ + return in_triangle(P, triangle_normal(Ta, Tb, Tc), Ta, Tb,Tc ); +} + + +} // namespace geometry + +} // namespace cgogn + +#endif // GEOMETRY_INCLUSION_H_ diff --git a/cgogn/geometry/functions/orientation.h b/cgogn/geometry/functions/orientation.h index 542a318d..daf595aa 100644 --- a/cgogn/geometry/functions/orientation.h +++ b/cgogn/geometry/functions/orientation.h @@ -25,8 +25,6 @@ #define GEOMETRY_ORIENTATION_H_ #include -#include -#include namespace cgogn { @@ -63,30 +61,6 @@ Orientation3D test_orientation_3D(const VEC3_T& P, const VEC3_T& N, const VEC3_T return Plane3D(N, PP).orient(P); } -template -inline bool in_triangle(const VEC3_T& P, const VEC3_T& normal, const VEC3_T& Ta, const VEC3_T& Tb, const VEC3_T& Tc) -{ - using Scalar = typename vector_traits::Scalar; - static const auto triple_positive = [] (const VEC3_T& U, const VEC3_T& V, const VEC3_T& W) -> bool - { - return U.dot(V.cross(W)) >= Scalar(0); - }; - - if (triple_positive(P-Ta, Tb-Ta, normal) || - triple_positive(P-Tb, Tc-Tb, normal) || - triple_positive(P-Tc, Ta-Tc, normal) ) - return false; - - return true; -} - -template -inline bool in_triangle(const VEC3_T& P, const VEC3_T& Ta, const VEC3_T& Tb, const VEC3_T& Tc) -{ - return in_triangle(P, triangle_normal(Ta, Tb, Tc), Ta, Tb,Tc ); -} - - } // namespace geometry } // namespace cgogn From f25aff733b375fcbebac57e9d679afdd5132e7b7 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Tue, 23 Feb 2016 17:35:56 +0100 Subject: [PATCH 149/402] Clean new_embedding() + Nettoyage CHP --- cgogn/core/basic/dart.h | 26 ++++-- cgogn/core/cmap/cmap0.h | 2 +- cgogn/core/cmap/cmap1.h | 18 ++-- cgogn/core/cmap/cmap2.h | 22 ++--- cgogn/core/cmap/cmap3.h | 8 +- cgogn/core/cmap/map_base.h | 47 +++------- cgogn/core/cmap/map_base_data.h | 18 ++-- cgogn/core/cmap/sanity_check.h | 4 +- cgogn/core/tests/basic/cell_test.cpp | 9 -- cgogn/core/tests/basic/dart_test.cpp | 96 ++++++++++++-------- cgogn/multiresolution/cph/ihcmap2.h | 30 +++--- cgogn/multiresolution/cph/ihcmap2_adaptive.h | 12 +-- cgogn/multiresolution/cph/ihcmap2_regular.h | 8 +- 13 files changed, 151 insertions(+), 149 deletions(-) diff --git a/cgogn/core/basic/dart.h b/cgogn/core/basic/dart.h index cc2c1340..8b682073 100644 --- a/cgogn/core/basic/dart.h +++ b/cgogn/core/basic/dart.h @@ -108,21 +108,31 @@ struct Dart */ inline bool operator!=(Dart rhs) const { return index != rhs.index; } +// To remove // operator < is needed if we want to use std::set - inline bool operator<(Dart rhs) const { return index < rhs.index; } - /** - * \brief Prints a dart to a stream. - * \param[out] out the stream to print on - * \param[in] rhs the dart to print - */ - inline friend std::ostream& operator<<(std::ostream &out, const Dart& rhs) { return out << rhs.index; } +// inline bool operator<(Dart rhs) const { return index < rhs.index; } +// /** +// * \brief Prints a dart to a stream. +// * \param[out] out the stream to print on +// * \param[in] rhs the dart to print +// */ + + // -1 should be less system dependent + inline friend std::ostream& operator<<(std::ostream &out, const Dart& rhs) { + if (rhs.is_nil()) + return out << -1; + else + return out << rhs.index; + } /** * \brief Reads a dart from a stream. * \param[in] in the stream to read from * \param[out] rhs the dart read */ - inline friend std::istream& operator>>(std::istream &in, Dart& rhs) { in >> rhs.index; return in; } + inline friend std::istream& operator>>(std::istream &in, Dart& rhs) { + in >> rhs.index; return in; + } }; } // namespace cgogn diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index cecd568e..1fc3cb5d 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -107,7 +107,7 @@ class CMap0_T : public MapBase Vertex v = this->add_dart(); if (this->template is_embedded()) - this->new_embedding(v); + this->new_orbit_embedding(v); return v; } diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 35974d58..56a75b5b 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -211,7 +211,7 @@ class CMap1_T : public CMap0_T Vertex nv = split_vertex_topo(v); if (this->template is_embedded()) - this->new_embedding(nv); + this->new_orbit_embedding(nv); if (this->template is_embedded()) this->copy_embedding(Face(nv.dart), Face(v.dart)); @@ -222,7 +222,7 @@ class CMap1_T : public CMap0_T /** * \brief Remove a vertex from its face and delete it. * @param v : a vertex - * The vertex that preceeds v in the face is linked its successor. + * The vertex that preceeds v in the face is linked to the successor of v. */ inline void remove_vertex(Vertex v) { @@ -268,7 +268,7 @@ class CMap1_T : public CMap0_T if (this->template is_embedded()) foreach_dart_of_orbit(f, [this] (Vertex v) { - this->new_embedding(v); + this->new_orbit_embedding(v); }); if (this->template is_embedded()) this->new_orbit_embedding(f); @@ -283,12 +283,12 @@ class CMap1_T : public CMap0_T inline void remove_face(Face f) { Dart d = f.dart; - Dart e = phi1(d); - while(e != d) + Dart it = phi1(d); + while(it != d) { - Dart f = phi1(e); - this->remove_dart(e); - e = f; + Dart next = phi1(it); + this->remove_dart(it); + it = next; } this->remove_dart(d); @@ -319,7 +319,7 @@ class CMap1_T : public CMap0_T inline unsigned int degree(Face f) const { - return this->nb_darts(f); + return this->nb_darts_of_orbit(f); } /******************************************************************************* diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index e2adef66..65b2f64a 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -208,17 +208,17 @@ class CMap2_T : public CMap1_T CGOGN_CHECK_CONCRETE_TYPE; const Vertex v = cut_edge_topo(e); - const Dart nf = phi2(e); - const Dart f = phi2(v); + const Dart nf = phi2(e); + const Dart f = phi2(v); if (this->template is_embedded()) { - this->new_embedding(CDart(v)); - this->new_embedding(CDart(nf)); + this->new_orbit_embedding(CDart(v)); + this->new_orbit_embedding(CDart(nf)); } if (this->template is_embedded()) { - this->new_embedding(Vertex(v)); + this->new_orbit_embedding(Vertex(v)); } if (this->template is_embedded()) @@ -300,8 +300,8 @@ class CMap2_T : public CMap1_T Dart ne = this->phi_1(e); if (this->template is_embedded()) { - this->new_embedding(CDart(nd)); - this->new_embedding(CDart(ne)); + this->new_orbit_embedding(CDart(nd)); + this->new_orbit_embedding(CDart(ne)); } if (this->template is_embedded()) @@ -370,8 +370,8 @@ class CMap2_T : public CMap1_T if (this->template is_embedded()) foreach_dart_of_orbit(f, [this] (CDart d) { - this->new_embedding(d); - this->new_embedding(CDart(phi2(d))); + this->new_orbit_embedding(d); + this->new_orbit_embedding(CDart(phi2(d))); }); if (this->template is_embedded()) @@ -442,7 +442,7 @@ class CMap2_T : public CMap1_T if (this->template is_embedded()) foreach_dart_of_orbit(new_face, [this] (CDart d) { - this->new_embedding(d); + this->new_orbit_embedding(d); }); if (this->template is_embedded()) @@ -483,7 +483,7 @@ class CMap2_T : public CMap1_T inline unsigned int degree(Vertex v) const { - return this->nb_darts(v); + return this->nb_darts_of_orbit(v); } /******************************************************************************* diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 04d0b0ce..1099e4a6 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -51,7 +51,7 @@ class CMap3_T : public CMap2_T template friend class DartMarker_T; template friend class DartMarkerStore; - using CDart = typename Inherit::CDart; + using CDart = Cell; using Vertex = Cell; using Edge = Cell; using Face = Cell; @@ -339,7 +339,7 @@ class CMap3_T : public CMap2_T if (this->template is_embedded()) foreach_dart_of_orbit(new_volume, [this] (Dart d) { - this->new_embedding(CDart(d)); + this->new_orbit_embedding(CDart(d)); }); if (this->template is_embedded()) @@ -466,8 +466,8 @@ class CMap3_T : public CMap2_T template inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const { - static_assert(check_func_parameter_type(FUNC, Dart), - "Wrong function parameter type"); +// static_assert(check_func_parameter_type(FUNC, Dart), +// "Wrong function parameter type"); static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || ORBIT == Orbit::PHI2 || ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21 || diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index b23ec235..e7fe101f 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -222,7 +222,7 @@ class MapBase : public MapBaseData { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - if (!this->template is_orbit_embedded()) + if (!this->template is_embedded>()) create_embedding(); ChunkArray* ca = this->attributes_[ORBIT].template add_attribute(attribute_name); return AttributeHandler(this, ca); @@ -351,10 +351,12 @@ class MapBase : public MapBaseData } template - inline unsigned int new_embedding(Cell c) + inline unsigned int new_orbit_embedding(Cell c) { - unsigned int emb = add_attribute_element(); - this->template set_embedding(c.dart, emb); + const unsigned int emb = add_attribute_element(); + to_concrete()->foreach_dart_of_orbit(c, [this, emb] (Cell d) { + this->set_embedding(d, emb); + }); return emb; } @@ -364,25 +366,6 @@ class MapBase : public MapBaseData this->set_embedding(dest, this->get_embedding(src)); } -// template -// inline void set_orbit_embedding(Cell c, unsigned int emb) -// { -// ConcreteMap* cmap = to_concrete(); -// cmap->foreach_dart_of_orbit(c, [cmap, emb] (Dart d) { -// cmap->template set_embedding(d, emb); -// }); -// } - - template - inline unsigned int new_orbit_embedding(Cell c) - { - const unsigned int emb = add_attribute_element(); - to_concrete()->foreach_dart_of_orbit(c, [this, emb] (Dart d) { - this->template set_embedding(d, emb); - }); - return emb; - } - public: /** @@ -392,7 +375,7 @@ class MapBase : public MapBaseData void enforce_unique_orbit_embedding() { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - cgogn_message_assert(this->template is_orbit_embedded(), "Invalid parameter: orbit not embedded"); + cgogn_message_assert(this->template is_embedded>(), "Invalid parameter: orbit not embedded"); AttributeHandler counter = add_attribute("__tmp_counter"); for (unsigned int& i : counter) i = 0; @@ -523,7 +506,7 @@ class MapBase : public MapBaseData template unsigned int nb_cells() const { - if (this->template is_orbit_embedded()) + if (this->template is_embedded>()) return this->attributes_[ORBIT].size(); else { @@ -537,7 +520,7 @@ class MapBase : public MapBaseData * \brief return the number of darts in the given cell */ template - unsigned int nb_darts(Cell c) const + unsigned int nb_darts_of_orbit(Cell c) const { const ConcreteMap* cmap = to_concrete(); unsigned int result = 0u; @@ -742,8 +725,8 @@ class MapBase : public MapBaseData template inline void parallel_foreach_cell(const FUNC& f) const { - using cell_type = typename function_traits::template arg<0>::type; - static const Orbit ORBIT = cell_type::ORBIT; + using CellType = typename function_traits::template arg<0>::type; + static const Orbit ORBIT = CellType::ORBIT; static_assert(check_func_ith_parameter_type(FUNC, 1, unsigned int), "Wrong function second parameter type"); switch (STRATEGY) @@ -760,7 +743,7 @@ class MapBase : public MapBaseData case AUTO : if (is_topo_cache_enabled()) parallel_foreach_cell_topo_cache(f); - else if (this->template is_orbit_embedded()) + else if (this->template is_embedded()) parallel_foreach_cell_cell_marking(f); else parallel_foreach_cell_dart_marking(f); @@ -776,8 +759,8 @@ class MapBase : public MapBaseData template void foreach_cell_until(const FUNC& f) const { - using cell_type = typename function_traits::template arg<0>::type; - static const Orbit ORBIT = cell_type::ORBIT; + using CellType = typename function_traits::template arg<0>::type; + static const Orbit ORBIT = CellType::ORBIT; static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); switch (STRATEGY) @@ -794,7 +777,7 @@ class MapBase : public MapBaseData case AUTO : if (is_topo_cache_enabled()) foreach_cell_until_topo_cache(f); - else if (this->template is_orbit_embedded()) + else if (this->template is_embedded()) foreach_cell_until_cell_marking(f); else foreach_cell_until_dart_marking(f); diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index 69374427..d4fb0e16 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -239,12 +239,12 @@ class MapBaseData : public MapGen public: - template - inline bool is_orbit_embedded() const - { - static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - return embeddings_[ORBIT] != nullptr; - } +// template +// inline bool is_orbit_embedded() const +// { +// static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); +// return embeddings_[ORBIT] != nullptr; +// } template inline bool is_embedded() const @@ -275,11 +275,11 @@ class MapBaseData : public MapGen const unsigned int old = (*embeddings_[ORBIT])[c.dart.index]; // ref_line() is done before unref_line() to avoid deleting the indexed line if old == emb - this->attributes_[ORBIT].ref_line(emb); // ref the new emb + attributes_[ORBIT].ref_line(emb); // ref the new emb if (old != EMBNULL) - this->attributes_[ORBIT].unref_line(old); // unref the old emb + attributes_[ORBIT].unref_line(old); // unref the old emb - (*this->embeddings_[ORBIT])[c.dart.index] = emb; // affect the embedding to the dart + (*embeddings_[ORBIT])[c.dart.index] = emb; // affect the embedding to the dart } /******************************************************************************* diff --git a/cgogn/core/cmap/sanity_check.h b/cgogn/core/cmap/sanity_check.h index 38052708..fe1fe85b 100644 --- a/cgogn/core/cmap/sanity_check.h +++ b/cgogn/core/cmap/sanity_check.h @@ -57,7 +57,7 @@ template bool is_orbit_embedding_unique(MAP& map) { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - cgogn_message_assert(map.template is_orbit_embedded(), "Invalid parameter: orbit not embedded"); + cgogn_message_assert(map.template is_embedded>(), "Invalid parameter: orbit not embedded"); typename MAP::template AttributeHandler counter = map.template add_attribute("__tmp_counter"); for (unsigned int& i : counter) i = 0; @@ -89,7 +89,7 @@ template bool is_container_well_referenced(MAP& map) { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - cgogn_message_assert(map.template is_orbit_embedded(), "Invalid parameter: orbit not embedded"); + cgogn_message_assert(map.template is_embedded>(), "Invalid parameter: orbit not embedded"); typename MAP::template AttributeHandler counter = map.template add_attribute("__tmp_counter"); diff --git a/cgogn/core/tests/basic/cell_test.cpp b/cgogn/core/tests/basic/cell_test.cpp index f377a8b2..da88d8f5 100644 --- a/cgogn/core/tests/basic/cell_test.cpp +++ b/cgogn/core/tests/basic/cell_test.cpp @@ -28,15 +28,6 @@ namespace cgogn { -// TEST(CellTest, Equality) -// { -// Cell v1(); -// Cell v2(); - -// v1 != v2; - -// // EXPECT_EQ(10u, d.index); -// } const Dart dglobal(10u); const Dart dmax(std::numeric_limits::max()); diff --git a/cgogn/core/tests/basic/dart_test.cpp b/cgogn/core/tests/basic/dart_test.cpp index eceab653..2361e52d 100644 --- a/cgogn/core/tests/basic/dart_test.cpp +++ b/cgogn/core/tests/basic/dart_test.cpp @@ -28,76 +28,94 @@ namespace cgogn { -TEST(DartTest, DefaultConstructor) +class DartTest : public ::testing::Test { - Dart d; - EXPECT_EQ(std::numeric_limits::max(), d.index); -} -TEST(DartTest, Constructor) +public: + + DartTest() : d10a_(10u), d10b_(10u), d20a_(20u), + dMax_(std::numeric_limits::max()) {} + + // virtual void TearDown() {} + + const Dart dNil_; + const Dart d10a_; + const Dart d10b_; + const Dart d20a_; + const Dart dMax_; +}; + +TEST_F(DartTest, DefaultConstructor) { - Dart d(10u); - EXPECT_EQ(10u, d.index); + EXPECT_EQ(std::numeric_limits::max(), dNil_.index); } -TEST(DartTest, OutOfLimitConstructor) +TEST_F(DartTest, Constructor) { - Dart d1(std::numeric_limits::max()); - Dart d2; - EXPECT_EQ(d1.index, d2.index); + EXPECT_EQ(10u, d10a_.index); + EXPECT_EQ(dNil_.index, dMax_.index); } -TEST(DartTest, CopyConstructor) +TEST_F(DartTest, CopyConstructor) { - Dart d(20u); - Dart dcopy(d); - EXPECT_EQ(d.index, dcopy.index); + Dart d1(d10a_); + Dart d2(dNil_); + EXPECT_EQ(d1.index, d10a_.index); + EXPECT_EQ(d2.index, dNil_.index); } -TEST(DartTest, IsNil) +TEST_F(DartTest, IsNil) { - Dart d; - EXPECT_TRUE(d.is_nil()); + EXPECT_TRUE(dNil_.is_nil()); + EXPECT_TRUE(dMax_.is_nil()); + EXPECT_FALSE(d10a_.is_nil()); } -TEST(DartTest, Assignation) +TEST_F(DartTest, Assignation) { - Dart d1(10u); - Dart d2; - d2 = d1; - EXPECT_EQ(d2.index, d1.index); + Dart d1 = d10a_; + Dart d2 = dNil_; + EXPECT_EQ(d1.index, d10a_.index); + EXPECT_EQ(d2.index, dNil_.index); } -TEST(DartTest, Equality) +TEST_F(DartTest, Equality) { - Dart d1(10u); - Dart d2(10u); - EXPECT_EQ(d2.index, d1.index); + EXPECT_TRUE(d10a_ == d10a_); + EXPECT_TRUE(d10a_ == d10b_); + EXPECT_TRUE(dNil_ == dMax_); + EXPECT_FALSE(d10a_ == dNil_); + EXPECT_FALSE(d10a_ == d20a_); } -TEST(DartTest, Difference) +TEST_F(DartTest, Difference) { - Dart d1(10u); - Dart d2(100u); - EXPECT_EQ(10u, d1.index); - EXPECT_EQ(100u, d2.index); + EXPECT_TRUE(d10a_ != d20a_); + EXPECT_TRUE(d10a_ != dNil_); + EXPECT_FALSE(d10a_ != d10a_); + EXPECT_FALSE(d10a_ != d10b_); } -TEST(DartTest, PrintingOut) +TEST_F(DartTest, PrintingOut) { - Dart d(10u); std::ostringstream s; - s << "d=" << d; - EXPECT_EQ(0, strcmp(s.str().c_str(), "d=10")); + s << d10a_; + EXPECT_STREQ(s.str().c_str(), "10"); + std::ostringstream t; + t << dNil_; + EXPECT_STREQ(t.str().c_str(), "-1"); } -TEST(DartTest, ReadingIn) +TEST_F(DartTest, ReadingIn) { Dart d; std::istringstream s("10"); s >> d; - - EXPECT_EQ(10u, d.index); + EXPECT_TRUE(d == d10a_); + Dart e; + std::istringstream t("-1"); + t >> e; + EXPECT_TRUE(e == dNil_); } } // namespace cgogn diff --git a/cgogn/multiresolution/cph/ihcmap2.h b/cgogn/multiresolution/cph/ihcmap2.h index bdfbcb09..40a3d8cc 100644 --- a/cgogn/multiresolution/cph/ihcmap2.h +++ b/cgogn/multiresolution/cph/ihcmap2.h @@ -75,11 +75,11 @@ class IHCMap2_T : public CMap2_T, public CPH2 // static const Orbit FACE = Inherit_CMAP::FACE; // static const Orbit VOLUME = Inherit_CMAP::VOLUME; - using Vertex0 = Cell ; - using Vertex2 = Cell ; - using Edge2 = Cell ; - using Face2 = Cell ; - using Volume2 = Cell; + using CDart = typename Inherit_CMAP::CDart; + using Vertex = typename Inherit_CMAP::Vertex; + using Edge = typename Inherit_CMAP::Edge; + using Face = typename Inherit_CMAP::Face; + using Volume = typename Inherit_CMAP::Volume; template @@ -221,7 +221,7 @@ class IHCMap2_T : public CMap2_T, public CPH2 // inline unsigned int get_embedding_cph(Cell c) const // { // static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); -// cgogn_message_assert(Inherit::is_orbit_embedded(), "Invalid parameter: orbit not embedded"); +// cgogn_message_assert(Inherit::is_embedded>(), "Invalid parameter: orbit not embedded"); // unsigned int nb_steps = Inherit::get_current_level() - Inherit::get_dart_level(c.dart); // unsigned int index = Inherit::get_embedding(c); @@ -247,29 +247,29 @@ class IHCMap2_T : public CMap2_T, public CPH2 * the inserted darts are automatically embedded on new attribute elements. * Actually a FACE attribute is created, if needed, for the new face. */ - Face2 add_face(unsigned int size) + Face add_face(unsigned int size) { - Face2 f = this->add_face_topo(size); + Face f = this->add_face_topo(size); - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) foreach_dart_of_orbit(f, [this] (Dart d) { - this->template new_embedding(d); + this->template new_orbit_embedding(d); }); - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) foreach_dart_of_orbit(f, [this] (Dart v) { - this->template new_embedding(v); + this->template new_orbit_embedding(v); }); - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) cgogn_assert_not_reached("Not implemented"); - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) cgogn_assert_not_reached("Not implemented"); - if (this->template is_orbit_embedded()) + if (this->template is_embedded()) cgogn_assert_not_reached("Not implemented"); return f; diff --git a/cgogn/multiresolution/cph/ihcmap2_adaptive.h b/cgogn/multiresolution/cph/ihcmap2_adaptive.h index 5231fd92..8c61aeeb 100644 --- a/cgogn/multiresolution/cph/ihcmap2_adaptive.h +++ b/cgogn/multiresolution/cph/ihcmap2_adaptive.h @@ -43,10 +43,10 @@ class IHCMap2Adaptive_T : public IHCMap2_T friend class MapBase; - using Vertex = typename Inherit::Vertex2; - using Edge = typename Inherit::Edge2; - using Face = typename Inherit::Face2; - using Volume = typename Inherit::Volume2; + using Vertex = typename Inherit::Vertex; + using Edge = typename Inherit::Edge; + using Face = typename Inherit::Face; + using Volume = typename Inherit::Volume; IHCMap2Adaptive_T() : Inherit() {} @@ -244,7 +244,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T Dart d2 = Inherit::phi2(d) ; unsigned int cur = Inherit::get_current_level(); Inherit::set_current_level(cur + 1); - if(this->degree(typename Inherit::Vertex2(Inherit::phi1(d))) == 2) + if(this->degree(typename Inherit::Vertex(Inherit::phi1(d))) == 2) { degree2 = true ; if(edge_is_subdivided(d) || edge_is_subdivided(d2)) @@ -380,7 +380,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T Inherit::set_edge_id(Inherit::phi1(d), eId); Inherit::set_edge_id(Inherit::phi1(dd), eId); - // if(Inherit::template is_orbit_embedded()) + // if(is_embedded()) // { // (*edgeVertexFunctor)(Inherit::phi1(d)); // } diff --git a/cgogn/multiresolution/cph/ihcmap2_regular.h b/cgogn/multiresolution/cph/ihcmap2_regular.h index 669296dc..68719fa3 100644 --- a/cgogn/multiresolution/cph/ihcmap2_regular.h +++ b/cgogn/multiresolution/cph/ihcmap2_regular.h @@ -39,10 +39,10 @@ class IHCMap2Regular_T : public IHCMap2_T friend class MapBase; - using Vertex = typename Inherit::Vertex2; - using Edge = typename Inherit::Edge2; - using Face = typename Inherit::Face2; - using Volume = typename Inherit::Volume2; + using Vertex = typename Inherit::Vertex; + using Edge = typename Inherit::Edge; + using Face = typename Inherit::Face; + using Volume = typename Inherit::Volume; IHCMap2Regular_T() : Inherit() {} From 280c20ec0967468eac727b8116043588f155190f Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Tue, 23 Feb 2016 17:41:16 +0100 Subject: [PATCH 150/402] Remove forgotten foreach_dart_of_DART() --- cgogn/core/cmap/cmap1.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 56a75b5b..4eebf665 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -382,7 +382,7 @@ class CMap1_T : public CMap0_T switch (ORBIT) { - case Orbit::DART: this->foreach_dart_of_DART(c, f); break; + case Orbit::DART: f(c.dart); break; case Orbit::PHI1: foreach_dart_of_PHI1_until(c, f); break; case Orbit::PHI2: case Orbit::PHI1_PHI2: From 98bdfc87a852a99cd70659f81fe7710546a7ef97 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Tue, 23 Feb 2016 18:32:15 +0100 Subject: [PATCH 151/402] Back to Dart in set_embedding --- cgogn/core/cmap/cmap1.h | 7 +++++-- cgogn/core/cmap/cmap2.h | 8 ++++---- cgogn/core/cmap/map_base.h | 4 ++-- cgogn/core/cmap/map_base_data.h | 6 +++--- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 9244e9d8..b994cbde 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -266,9 +266,9 @@ class CMap1_T : public CMap0_T Face f = add_face_topo(size); if (this->template is_embedded()) - foreach_dart_of_orbit(f, [this] (Vertex v) + foreach_dart_of_orbit(f, [this] (Dart d) { - this->new_orbit_embedding(v); + this->new_orbit_embedding(Vertex(d)); }); if (this->template is_embedded()) this->new_orbit_embedding(f); @@ -357,6 +357,9 @@ class CMap1_T : public CMap0_T template inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const { + static_assert(check_func_parameter_type(FUNC, Dart), + "Wrong function parameter type"); + static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1, "Orbit not supported in a CMap1"); diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 65b2f64a..475fc323 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -193,10 +193,10 @@ class CMap2_T : public CMap1_T /** * \brief Cut an embedded edge. - * \param d : A dart that represents the edge to cut + * \param e : A dart that represents the edge to cut * \return A dart of the inserted vertex - * The edge of d is cut by inserting a new vertex. - * The returned dart is the dart of the inserted vertex that belongs to the face of d. + * The edge e is cut by inserting a new vertex. + * The returned dart is the dart of the inserted vertex that belongs to the face of e. * If the map has Dart, Vertex, Edge, Face or Volume attributes, * the inserted darts are automatically embedded on new attribute elements. * - Actually a Vertex attribute is created, if needed, for the inserted vertex. @@ -218,7 +218,7 @@ class CMap2_T : public CMap1_T if (this->template is_embedded()) { - this->new_orbit_embedding(Vertex(v)); + this->new_orbit_embedding(v); } if (this->template is_embedded()) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index f889c6a0..e4f1fd23 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -354,8 +354,8 @@ class MapBase : public MapBaseData inline unsigned int new_orbit_embedding(Cell c) { const unsigned int emb = add_attribute_element(); - to_concrete()->foreach_dart_of_orbit(c, [this, emb] (Cell d) { - this->set_embedding(d, emb); + to_concrete()->foreach_dart_of_orbit(c, [this, emb] (Dart d) { + this->template set_embedding(d, emb); }); return emb; } diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index d4fb0e16..1e5c244d 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -266,20 +266,20 @@ class MapBaseData : public MapGen protected: template - inline void set_embedding(Cell c, unsigned int emb) + inline void set_embedding(Dart d, unsigned int emb) { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); cgogn_message_assert(is_embedded>(), "Invalid parameter: orbit not embedded"); cgogn_message_assert(emb != EMBNULL,"cannot set an embedding to EMBNULL."); - const unsigned int old = (*embeddings_[ORBIT])[c.dart.index]; + const unsigned int old = (*embeddings_[ORBIT])[d.dart.index]; // ref_line() is done before unref_line() to avoid deleting the indexed line if old == emb attributes_[ORBIT].ref_line(emb); // ref the new emb if (old != EMBNULL) attributes_[ORBIT].unref_line(old); // unref the old emb - (*embeddings_[ORBIT])[c.dart.index] = emb; // affect the embedding to the dart + (*embeddings_[ORBIT])[d.dart.index] = emb; // affect the embedding to the dart } /******************************************************************************* From fa7cfc044d45d397a3c2afeeb4bb41afa3184550 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Tue, 23 Feb 2016 20:09:54 +0100 Subject: [PATCH 152/402] foreach_dart_of_orbit accepting only functors working with Darts Signed-off-by: Etienne Schmitt --- cgogn/core/cmap/cmap1.h | 14 ++++--- cgogn/core/cmap/cmap2.h | 60 +++++++++++++------------- cgogn/core/cmap/cmap3.h | 86 +++++++++++++++++++------------------- cgogn/core/cmap/map_base.h | 4 +- 4 files changed, 87 insertions(+), 77 deletions(-) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 9244e9d8..09de78be 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -266,9 +266,9 @@ class CMap1_T : public CMap0_T Face f = add_face_topo(size); if (this->template is_embedded()) - foreach_dart_of_orbit(f, [this] (Vertex v) + foreach_dart_of_orbit(f, [this] (Dart d) { - this->new_orbit_embedding(v); + this->new_orbit_embedding(Vertex(d)); }); if (this->template is_embedded()) this->new_orbit_embedding(f); @@ -357,13 +357,15 @@ class CMap1_T : public CMap0_T template inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const { + static_assert(check_func_parameter_type(FUNC, Dart), + "Wrong function parameter type"); static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1, "Orbit not supported in a CMap1"); switch (ORBIT) { case Orbit::DART: f(c.dart); break; - case Orbit::PHI1: foreach_dart_of_PHI1(c, f); break; + case Orbit::PHI1: foreach_dart_of_PHI1(c.dart, f); break; case Orbit::PHI2: case Orbit::PHI1_PHI2: case Orbit::PHI1_PHI3: @@ -389,6 +391,8 @@ class CMap1_T : public CMap0_T template inline void foreach_dart_of_orbit_until(Cell c, const FUNC& f) const { + static_assert(check_func_parameter_type(FUNC, Dart), + "Wrong function parameter type"); static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); @@ -398,7 +402,7 @@ class CMap1_T : public CMap0_T switch (ORBIT) { case Orbit::DART: f(c.dart); break; - case Orbit::PHI1: foreach_dart_of_PHI1_until(c, f); break; + case Orbit::PHI1: foreach_dart_of_PHI1_until(c.dart, f); break; case Orbit::PHI2: case Orbit::PHI1_PHI2: case Orbit::PHI1_PHI3: @@ -420,7 +424,7 @@ class CMap1_T : public CMap0_T { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); - foreach_dart_of_orbit(f, func); + foreach_dart_of_orbit(f, [&func](Dart v) {func(Vertex(v));}); } }; diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 65b2f64a..0a730d63 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -368,22 +368,22 @@ class CMap2_T : public CMap1_T const Face f = add_face_topo(size); if (this->template is_embedded()) - foreach_dart_of_orbit(f, [this] (CDart d) + foreach_dart_of_orbit(f, [this] (Dart d) { - this->new_orbit_embedding(d); + this->new_orbit_embedding(CDart(d)); this->new_orbit_embedding(CDart(phi2(d))); }); if (this->template is_embedded()) - foreach_dart_of_orbit(f, [this] (Vertex v) + foreach_dart_of_orbit(f, [this] (Dart v) { - this->new_orbit_embedding(v); + this->new_orbit_embedding(Vertex(v)); }); if (this->template is_embedded()) - foreach_dart_of_orbit(f, [this] (Edge e) + foreach_dart_of_orbit(f, [this] (Dart e) { - this->new_orbit_embedding(e); + this->new_orbit_embedding(Edge(e)); }); if (this->template is_embedded()) @@ -440,21 +440,21 @@ class CMap2_T : public CMap1_T const Face new_face = phi2(d); if (this->template is_embedded()) - foreach_dart_of_orbit(new_face, [this] (CDart d) + foreach_dart_of_orbit(new_face, [this] (Dart d) { - this->new_orbit_embedding(d); + this->new_orbit_embedding(CDart(d)); }); if (this->template is_embedded()) - foreach_dart_of_orbit(new_face, [this] (Vertex v) + foreach_dart_of_orbit(new_face, [this] (Dart v) { - this->copy_embedding(v, Vertex(this->phi1(phi2(v)))); + this->copy_embedding(Vertex(v), Vertex(this->phi1(phi2(v)))); }); if (this->template is_embedded()) - foreach_dart_of_orbit(new_face, [this] (Edge e) + foreach_dart_of_orbit(new_face, [this] (Dart e) { - this->copy_embedding(e, Edge(phi2(e))); + this->copy_embedding(Edge(e), Edge(phi2(e))); }); if (this->template is_embedded()) @@ -465,9 +465,9 @@ class CMap2_T : public CMap1_T if (this->template is_embedded()) { const unsigned int idx = this->template get_embedding(Volume(d)); - foreach_dart_of_orbit(new_face, [this, idx] (Volume v) + foreach_dart_of_orbit(new_face, [this, idx] (Dart v) { - this->set_embedding(v, idx); + this->set_embedding(Volume(v), idx); }); } } @@ -542,6 +542,8 @@ class CMap2_T : public CMap1_T template inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const { + static_assert(check_func_parameter_type(FUNC, Dart), + "Wrong function parameter type"); static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || ORBIT == Orbit::PHI2 || ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21, "Orbit not supported in a CMap2"); @@ -617,6 +619,8 @@ class CMap2_T : public CMap1_T template inline void foreach_dart_of_orbit_until(Cell c, const FUNC& f) const { + static_assert(check_func_parameter_type(FUNC, Dart), + "Wrong function parameter type"); static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); @@ -648,42 +652,42 @@ class CMap2_T : public CMap1_T inline void foreach_incident_edge(Vertex v, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); - foreach_dart_of_orbit(v, func); + foreach_dart_of_orbit(v, [&func](Dart e) {func(Edge(e));}); } template inline void foreach_incident_face(Vertex v, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); - foreach_dart_of_orbit(v, func); + foreach_dart_of_orbit(v, [&func](Dart f) {func(Face(f));}); } template inline void foreach_incident_vertex(Edge e, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); - foreach_dart_of_orbit(e, func); + foreach_dart_of_orbit(e, [&func](Dart v) {func(Vertex(v));}); } template inline void foreach_incident_face(Edge e, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); - foreach_dart_of_orbit(e, func); + foreach_dart_of_orbit(e, [&func](Dart f) {func(Face(f));}); } template inline void foreach_incident_vertex(Face f, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); - foreach_dart_of_orbit(f, func); + foreach_dart_of_orbit(f, [&func](Dart v) {func(Vertex(v));}); } template inline void foreach_incident_edge(Face f, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); - foreach_dart_of_orbit(f, func); + foreach_dart_of_orbit(f, [&func](Dart e) {func(Edge(e));}); } template @@ -691,12 +695,12 @@ class CMap2_T : public CMap1_T { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); DartMarkerStore marker(*this); - foreach_dart_of_orbit(w, [&] (Vertex v) + foreach_dart_of_orbit(w, [&] (Dart v) { if (!marker.is_marked(v)) { - marker.template mark_orbit(v); - f(v); + marker.mark_orbit(Vertex(v)); + f(Vertex(v)); } }); } @@ -706,12 +710,12 @@ class CMap2_T : public CMap1_T { static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); DartMarkerStore marker(*this); - foreach_dart_of_orbit(w, [&] (Edge e) + foreach_dart_of_orbit(w, [&] (Dart e) { if (!marker.is_marked(e)) { - marker.template mark_orbit(e); - f(e); + marker.mark_orbit(Edge(e)); + f(Edge(e)); } }); } @@ -725,8 +729,8 @@ class CMap2_T : public CMap1_T { if (!marker.is_marked(d)) { - marker.template mark_orbit(d); - f(d); + marker.mark_orbit(Face(d)); + f(Face(d)); } }); } diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 1099e4a6..9476afbd 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -271,7 +271,7 @@ class CMap3_T : public CMap2_T visitedFaces.reserve(1024); visitedFaces.push_back(d); // Start with the face of d - dmarker.template mark_orbit(d); + dmarker.mark_orbit(Face2(d)); unsigned int count = 0u; @@ -282,7 +282,7 @@ class CMap3_T : public CMap2_T Dart f = it; const Dart b = this->Inherit::Inherit::add_face_topo(this->degree(Face(f))); - boundary_marker.template mark_orbit(b); + boundary_marker.mark_orbit(Face2(b)); ++count; Dart bit = b; @@ -298,7 +298,7 @@ class CMap3_T : public CMap2_T if(!dmarker.is_marked(e)) { visitedFaces.push_back(e); - dmarker.template mark_orbit(e); + dmarker.template mark_orbit(Face2(e)); } } else { if(boundary_marker.is_marked(e)) @@ -466,8 +466,8 @@ class CMap3_T : public CMap2_T template inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const { -// static_assert(check_func_parameter_type(FUNC, Dart), -// "Wrong function parameter type"); + static_assert(check_func_parameter_type(FUNC, Dart), + "Wrong function parameter type"); static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || ORBIT == Orbit::PHI2 || ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21 || @@ -477,13 +477,13 @@ class CMap3_T : public CMap2_T switch (ORBIT) { case Orbit::DART: f(c.dart); break; - case Orbit::PHI1: this->foreach_dart_of_PHI1(c, f); break; - case Orbit::PHI2: this->foreach_dart_of_PHI2(c, f); break; - case Orbit::PHI1_PHI2: this->foreach_dart_of_PHI1_PHI2(c, f); break; - case Orbit::PHI1_PHI3: foreach_dart_of_PHI1_PHI3(c, f); break; - case Orbit::PHI2_PHI3: foreach_dart_of_PHI2_PHI3(c, f); break; - case Orbit::PHI21: this->foreach_dart_of_PHI21(c, f); break; - case Orbit::PHI21_PHI31: foreach_dart_of_PHI21_PHI31(c, f); break; + case Orbit::PHI1: this->foreach_dart_of_PHI1(c.dart, f); break; + case Orbit::PHI2: this->foreach_dart_of_PHI2(c.dart, f); break; + case Orbit::PHI1_PHI2: this->foreach_dart_of_PHI1_PHI2(c.dart, f); break; + case Orbit::PHI1_PHI3: foreach_dart_of_PHI1_PHI3(c.dart, f); break; + case Orbit::PHI2_PHI3: foreach_dart_of_PHI2_PHI3(c.dart, f); break; + case Orbit::PHI21: this->foreach_dart_of_PHI21(c.dart, f); break; + case Orbit::PHI21_PHI31: foreach_dart_of_PHI21_PHI31(c.dart, f); break; default: cgogn_assert_not_reached("This orbit is not handled"); break; } } @@ -551,6 +551,8 @@ class CMap3_T : public CMap2_T template inline void foreach_dart_of_orbit_until(Cell c, const FUNC& f) const { + static_assert(check_func_parameter_type(FUNC, Dart), + "Wrong function parameter type"); static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); @@ -561,14 +563,14 @@ class CMap3_T : public CMap2_T switch (ORBIT) { - case Orbit::DART: this->foreach_dart_of_DART(c, f); break; - case Orbit::PHI1: this->foreach_dart_of_PHI1_until(c, f); break; - case Orbit::PHI2: this->foreach_dart_of_PHI2_until(c, f); break; - case Orbit::PHI1_PHI2: this->foreach_dart_of_PHI1_PHI2_until(c, f); break; - case Orbit::PHI1_PHI3: foreach_dart_of_PHI1_PHI3_until(c, f); break; - case Orbit::PHI2_PHI3: foreach_dart_of_PHI2_PHI3_until(c, f); break; - case Orbit::PHI21: this->foreach_dart_of_PHI21_until(c, f); break; - case Orbit::PHI21_PHI31: foreach_dart_of_PHI21_PHI31_until(c, f); break; + case Orbit::DART: f(c.dart); break; + case Orbit::PHI1: this->foreach_dart_of_PHI1_until(c.dart, f); break; + case Orbit::PHI2: this->foreach_dart_of_PHI2_until(c.dart, f); break; + case Orbit::PHI1_PHI2: this->foreach_dart_of_PHI1_PHI2_until(c.dart, f); break; + case Orbit::PHI1_PHI3: foreach_dart_of_PHI1_PHI3_until(c.dart, f); break; + case Orbit::PHI2_PHI3: foreach_dart_of_PHI2_PHI3_until(c.dart, f); break; + case Orbit::PHI21: this->foreach_dart_of_PHI21_until(c.dart, f); break; + case Orbit::PHI21_PHI31: foreach_dart_of_PHI21_PHI31_until(c.dart, f); break; default: cgogn_assert_not_reached("This orbit is not handled"); break; } } @@ -619,7 +621,7 @@ class CMap3_T : public CMap2_T { if (!marker.is_marked(d)) { - marker.mark_orbit(d); + marker.mark_orbit(Vertex2(d)); f(d); } }); @@ -651,14 +653,14 @@ class CMap3_T : public CMap2_T inline void foreach_incident_vertex(Face f, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); - foreach_dart_of_orbit(f.dart, func); + foreach_dart_of_orbit(Face2(f.dart), [&func](Dart v) {func(Vertex(v));}); } template inline void foreach_incident_edge(Face f, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); - foreach_dart_of_orbit(f.dart, func); + foreach_dart_of_orbit(Face2(f.dart), [&func](Dart e) {func(Edge(e));}); } template @@ -709,14 +711,14 @@ class CMap3_T : public CMap2_T { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); DartMarker marker_vertex(*this); - marker_vertex.mark_orbit(v); + marker_vertex.mark_orbit(v); foreach_incident_face(v, [&] (Face inc_face) { foreach_incident_vertex(inc_face, [&] (Vertex vertex_of_face) { if (!marker_vertex.is_marked(vertex_of_face)) { - marker_vertex.mark_orbit(vertex_of_face); + marker_vertex.mark_orbit(vertex_of_face); f(vertex_of_face); } }); @@ -728,14 +730,14 @@ class CMap3_T : public CMap2_T { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); DartMarker marker_vertex(*this); - marker_vertex.mark_orbit(v); + marker_vertex.mark_orbit(v); foreach_incident_volume(v, [&] (Volume inc_vol) { foreach_incident_vertex(inc_vol, [&] (Vertex inc_vert) { if (!marker_vertex.is_marked(inc_vert)) { - marker_vertex.mark_orbit(inc_vert); + marker_vertex.mark_orbit(inc_vert); f(inc_vert); } }); @@ -761,14 +763,14 @@ class CMap3_T : public CMap2_T { static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); DartMarker marker_edge(*this); - marker_edge.mark_orbit(e); + marker_edge.mark_orbit(e); foreach_incident_face(e, [&] (Face inc_face) { foreach_incident_edge(inc_face, [&] (Edge inc_edge) { if (!marker_edge.is_marked(inc_edge)) { - marker_edge.mark_orbit(inc_edge); + marker_edge.mark_orbit(inc_edge); f(inc_edge); } }); @@ -780,14 +782,14 @@ class CMap3_T : public CMap2_T { static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); DartMarker marker_edge(*this); - marker_edge.mark_orbit(e); + marker_edge.mark_orbit(e); foreach_incident_volume(e, [&] (Volume inc_vol) { foreach_incident_edge(inc_vol, [&] (Edge inc_edge) { if (!marker_edge.is_marked(inc_edge)) { - marker_edge.mark_orbit(inc_edge); + marker_edge.mark_orbit(inc_edge); f(inc_edge); } }); @@ -799,14 +801,14 @@ class CMap3_T : public CMap2_T { static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); DartMarker marker_face(*this); - marker_face.mark_orbit(f); + marker_face.mark_orbit(f); foreach_incident_vertex(f, [&] (Vertex v) { foreach_incident_face(f, [&](Face inc_fac) { if (!marker_face.is_marked(inc_fac)) { - marker_face.mark_orbit(inc_fac); + marker_face.mark_orbit(inc_fac); func(inc_fac); } }); @@ -832,12 +834,12 @@ class CMap3_T : public CMap2_T { static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); DartMarker marker_face(*this); - marker_face.mark_orbit(f); + marker_face.mark_orbit(f); foreach_incident_face(Volume(f.dart), [&] (Face inc_face) { if (!marker_face.is_marked(inc_face)) { - marker_face.mark_orbit((inc_face)); + marker_face.mark_orbit((inc_face)); func(inc_face); } }); @@ -846,7 +848,7 @@ class CMap3_T : public CMap2_T { if (!marker_face.is_marked(inc_face)) { - marker_face.mark_orbit((inc_face)); + marker_face.mark_orbit((inc_face)); func(inc_face); } }); @@ -857,14 +859,14 @@ class CMap3_T : public CMap2_T { static_assert(check_func_parameter_type(FUNC, Volume), "Wrong function cell parameter type"); DartMarker marker_volume(*this); - marker_volume.mark_orbit(v); + marker_volume.mark_orbit(v); foreach_incident_vertex(v, [&] (Vertex inc_vert) { foreach_incident_volume(inc_vert, [&](Volume inc_vol) { if (!marker_volume.is_marked(inc_vol)) { - marker_volume.mark_orbit(inc_vol); + marker_volume.mark_orbit(inc_vol); f(inc_vol); } }); @@ -876,14 +878,14 @@ class CMap3_T : public CMap2_T { static_assert(check_func_parameter_type(FUNC, Volume), "Wrong function cell parameter type"); DartMarker marker_volume(*this); - marker_volume.mark_orbit(v); + marker_volume.mark_orbit(v); foreach_incident_edge(v, [&] (Edge inc_edge) { foreach_incident_volume(inc_edge, [&] (Volume inc_vol) { if (!marker_volume.is_marked(inc_vol)) { - marker_volume.mark_orbit(inc_vol); + marker_volume.mark_orbit(inc_vol); f(inc_vol); } }); @@ -895,14 +897,14 @@ class CMap3_T : public CMap2_T { static_assert(check_func_parameter_type(FUNC, Volume), "Wrong function cell parameter type"); DartMarker marker_volume(*this); - marker_volume.mark_orbit(v); + marker_volume.mark_orbit(v); foreach_incident_face(v, [&] (Edge inc_face) { foreach_incident_volume(inc_face, [&] (Volume inc_vol) { if (!marker_volume.is_marked(inc_vol)) { - marker_volume.mark_orbit(inc_vol); + marker_volume.mark_orbit(inc_vol); f(inc_vol); } }); diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index f889c6a0..b8c8d621 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -354,8 +354,8 @@ class MapBase : public MapBaseData inline unsigned int new_orbit_embedding(Cell c) { const unsigned int emb = add_attribute_element(); - to_concrete()->foreach_dart_of_orbit(c, [this, emb] (Cell d) { - this->set_embedding(d, emb); + to_concrete()->foreach_dart_of_orbit(c, [this, emb] (Dart d) { + this->set_embedding(Cell(d), emb); }); return emb; } From 786fcbe387b4225cd9de7a9c4a280ebfc54f74ad Mon Sep 17 00:00:00 2001 From: David Cazier Date: Wed, 24 Feb 2016 10:44:27 +0100 Subject: [PATCH 153/402] Bug fixes on Windows (VS2013) --- cgogn/core/cmap/cmap0.h | 7 ++++--- cgogn/core/cmap/cmap1.cpp | 2 +- cgogn/core/cmap/cmap1.h | 7 ++++--- cgogn/core/cmap/cmap2.cpp | 2 +- cgogn/core/cmap/cmap2.h | 17 +++++++++-------- cgogn/core/cmap/cmap3.cpp | 18 +++++++++--------- cgogn/core/cmap/cmap3.h | 25 +++++++++++++------------ cgogn/core/cmap/cmap3_builder.h | 2 +- cgogn/core/cmap/map_base.h | 4 ++-- cgogn/core/cmap/map_base_data.h | 4 ++-- 10 files changed, 46 insertions(+), 42 deletions(-) diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index 1fc3cb5d..e8cb9a99 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -42,8 +42,9 @@ class CMap0_T : public MapBase using Self = CMap0_T; friend class MapBase; - template friend class DartMarker_T; - template friend class DartMarkerStore; + friend class DartMarker_T; + //template friend class DartMarker_T; + //template friend class DartMarkerStore; using Vertex = Cell; @@ -85,7 +86,7 @@ class CMap0_T : public MapBase /*! * \brief Init an newly added dart. */ - inline void init_dart(Dart d) + inline void init_dart(Dart /*d*/) { } diff --git a/cgogn/core/cmap/cmap1.cpp b/cgogn/core/cmap/cmap1.cpp index 6558862f..d7ea2051 100644 --- a/cgogn/core/cmap/cmap1.cpp +++ b/cgogn/core/cmap/cmap1.cpp @@ -29,7 +29,7 @@ namespace cgogn { - template class CGOGN_CORE_API CMap1_T>; +// template class CGOGN_CORE_API CMap1_T>; template class CGOGN_CORE_API DartMarker>; template class CGOGN_CORE_API DartMarkerStore>; template class CGOGN_CORE_API DartMarkerNoUnmark>; diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index b994cbde..db867acd 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -42,8 +42,9 @@ class CMap1_T : public CMap0_T using Self = CMap1_T; friend class MapBase; - template friend class DartMarker_T; - template friend class DartMarkerStore; + friend class DartMarker_T; + //template friend class DartMarker_T; + //template friend class DartMarkerStore; using Vertex = Cell; using Face = Cell; @@ -437,7 +438,7 @@ template using CMap1 = CMap1_T>; #if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_MAP_MAP1_CPP_)) -extern template class CGOGN_CORE_API CMap1_T>; +//extern template class CGOGN_CORE_API CMap1_T>; extern template class CGOGN_CORE_API DartMarker>; extern template class CGOGN_CORE_API DartMarkerStore>; extern template class CGOGN_CORE_API DartMarkerNoUnmark>; diff --git a/cgogn/core/cmap/cmap2.cpp b/cgogn/core/cmap/cmap2.cpp index c477312f..ecedf4c2 100644 --- a/cgogn/core/cmap/cmap2.cpp +++ b/cgogn/core/cmap/cmap2.cpp @@ -29,7 +29,7 @@ namespace cgogn { - template class CGOGN_CORE_API CMap2_T>; +// template class CGOGN_CORE_API CMap2_T>; template class CGOGN_CORE_API DartMarker>; template class CGOGN_CORE_API DartMarkerStore>; template class CGOGN_CORE_API DartMarkerNoUnmark>; diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 475fc323..11fd3e5f 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -48,8 +48,9 @@ class CMap2_T : public CMap1_T friend class MapBase; friend class CMap2Builder_T; - template friend class DartMarker_T; - template friend class DartMarkerStore; + //friend class DartMarker_T; + //template friend class DartMarker_T; + //template friend class DartMarkerStore; using CDart = Cell; using Vertex = Cell; @@ -464,10 +465,10 @@ class CMap2_T : public CMap1_T if (this->template is_embedded()) { - const unsigned int idx = this->template get_embedding(Volume(d)); - foreach_dart_of_orbit(new_face, [this, idx] (Volume v) + const unsigned int idx = this->get_embedding(Volume(d)); + foreach_dart_of_orbit(new_face, [this, idx] (Dart v) { - this->set_embedding(v, idx); + this->set_embedding(v, idx); }); } } @@ -695,7 +696,7 @@ class CMap2_T : public CMap1_T { if (!marker.is_marked(v)) { - marker.template mark_orbit(v); + marker.mark_orbit(v); f(v); } }); @@ -710,7 +711,7 @@ class CMap2_T : public CMap1_T { if (!marker.is_marked(e)) { - marker.template mark_orbit(e); + marker.mark_orbit(e); f(e); } }); @@ -822,7 +823,7 @@ template using CMap2 = CMap2_T>; #if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_MAP_MAP2_CPP_)) -extern template class CGOGN_CORE_API CMap2_T>; +//extern template class CGOGN_CORE_API CMap2_T>; extern template class CGOGN_CORE_API DartMarker>; extern template class CGOGN_CORE_API DartMarkerStore>; extern template class CGOGN_CORE_API DartMarkerNoUnmark>; diff --git a/cgogn/core/cmap/cmap3.cpp b/cgogn/core/cmap/cmap3.cpp index 7b3d5236..c2cbe7d0 100644 --- a/cgogn/core/cmap/cmap3.cpp +++ b/cgogn/core/cmap/cmap3.cpp @@ -29,17 +29,17 @@ namespace cgogn { - template class CGOGN_CORE_API CMap3_T>; +// template class CGOGN_CORE_API CMap3_T>; template class CGOGN_CORE_API DartMarker>; template class CGOGN_CORE_API DartMarkerStore>; template class CGOGN_CORE_API DartMarkerNoUnmark>; - template class CGOGN_CORE_API CellMarker, Orbit::PHI21_PHI31>; - template class CGOGN_CORE_API CellMarker, Orbit::PHI2_PHI3>; - template class CGOGN_CORE_API CellMarker, Orbit::PHI1_PHI3>; - template class CGOGN_CORE_API CellMarker, Orbit::PHI1_PHI2>; - template class CGOGN_CORE_API CellMarkerStore, Orbit::PHI21_PHI31>; - template class CGOGN_CORE_API CellMarkerStore, Orbit::PHI2_PHI3>; - template class CGOGN_CORE_API CellMarkerStore, Orbit::PHI1_PHI3>; - template class CGOGN_CORE_API CellMarkerStore, Orbit::PHI1_PHI2>; + template class CGOGN_CORE_API CellMarker, CMap3::Vertex::ORBIT>; + template class CGOGN_CORE_API CellMarker, CMap3::Edge::ORBIT>; + template class CGOGN_CORE_API CellMarker, CMap3::Face::ORBIT>; + template class CGOGN_CORE_API CellMarker, CMap3::Volume::ORBIT>; + template class CGOGN_CORE_API CellMarkerStore, CMap3::Vertex::ORBIT>; + template class CGOGN_CORE_API CellMarkerStore, CMap3::Edge::ORBIT>; + template class CGOGN_CORE_API CellMarkerStore, CMap3::Face::ORBIT>; + template class CGOGN_CORE_API CellMarkerStore, CMap3::Volume::ORBIT>; } // namespace cgogn diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 1099e4a6..2acca042 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -25,7 +25,6 @@ #define CORE_CMAP_CMAP3_H_ #include -#include namespace cgogn { @@ -48,8 +47,10 @@ class CMap3_T : public CMap2_T friend class MapBase; friend class CMap3Builder_T; - template friend class DartMarker_T; - template friend class DartMarkerStore; + friend class DartMarker_T; + friend class cgogn::DartMarkerStore; + //friend class DartMarkerStore; + //template friend class DartMarker_T; using CDart = Cell; using Vertex = Cell; @@ -920,18 +921,18 @@ template using CMap3 = CMap3_T>; #if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_MAP_MAP3_CPP_)) -extern template class CGOGN_CORE_API CMap3_T>; +//extern template class CGOGN_CORE_API CMap3_T>; extern template class CGOGN_CORE_API DartMarker>; extern template class CGOGN_CORE_API DartMarkerStore>; extern template class CGOGN_CORE_API DartMarkerNoUnmark>; -extern template class CGOGN_CORE_API CellMarker, Orbit::PHI21_PHI31>; -extern template class CGOGN_CORE_API CellMarker, Orbit::PHI2_PHI3>; -extern template class CGOGN_CORE_API CellMarker, Orbit::PHI1_PHI3>; -extern template class CGOGN_CORE_API CellMarker, Orbit::PHI1_PHI2>; -extern template class CGOGN_CORE_API CellMarkerStore, Orbit::PHI21_PHI31>; -extern template class CGOGN_CORE_API CellMarkerStore, Orbit::PHI2_PHI3>; -extern template class CGOGN_CORE_API CellMarkerStore, Orbit::PHI1_PHI3>; -extern template class CGOGN_CORE_API CellMarkerStore, Orbit::PHI1_PHI2>; +extern template class CGOGN_CORE_API CellMarker, CMap3::Vertex::ORBIT>; +extern template class CGOGN_CORE_API CellMarker, CMap3::Edge::ORBIT>; +extern template class CGOGN_CORE_API CellMarker, CMap3::Face::ORBIT>; +extern template class CGOGN_CORE_API CellMarker, CMap3::Volume::ORBIT>; +extern template class CGOGN_CORE_API CellMarkerStore, CMap3::Vertex::ORBIT>; +extern template class CGOGN_CORE_API CellMarkerStore, CMap3::Edge::ORBIT>; +extern template class CGOGN_CORE_API CellMarkerStore, CMap3::Face::ORBIT>; +extern template class CGOGN_CORE_API CellMarkerStore, CMap3::Volume::ORBIT>; #endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_MAP_MAP3_CPP_)) } // namespace cgogn diff --git a/cgogn/core/cmap/cmap3_builder.h b/cgogn/core/cmap/cmap3_builder.h index e2e4c846..12ec9cfe 100644 --- a/cgogn/core/cmap/cmap3_builder.h +++ b/cgogn/core/cmap/cmap3_builder.h @@ -67,7 +67,7 @@ class CMap3Builder_T { map_.foreach_dart_of_PHI21(d, [&] (Dart dit) { - map_.template set_embedding(Vertex(dit), emb); + map_.set_embedding(dit, emb); }); } diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index e4f1fd23..474ba216 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -286,7 +286,7 @@ class MapBase : public MapBaseData { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - unsigned int thread = this->get_current_thread_index(); + std::size_t thread = this->get_current_thread_index(); if (!this->mark_attributes_[ORBIT][thread].empty()) { ChunkArray* ca = this->mark_attributes_[ORBIT][thread].back(); @@ -363,7 +363,7 @@ class MapBase : public MapBaseData template inline void copy_embedding(Cell dest, Cell src) { - this->set_embedding(dest, this->get_embedding(src)); + this->set_embedding(dest, this->get_embedding(src)); } public: diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index 1e5c244d..612b51b7 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -272,14 +272,14 @@ class MapBaseData : public MapGen cgogn_message_assert(is_embedded>(), "Invalid parameter: orbit not embedded"); cgogn_message_assert(emb != EMBNULL,"cannot set an embedding to EMBNULL."); - const unsigned int old = (*embeddings_[ORBIT])[d.dart.index]; + const unsigned int old = (*embeddings_[ORBIT])[d.index]; // ref_line() is done before unref_line() to avoid deleting the indexed line if old == emb attributes_[ORBIT].ref_line(emb); // ref the new emb if (old != EMBNULL) attributes_[ORBIT].unref_line(old); // unref the old emb - (*embeddings_[ORBIT])[d.dart.index] = emb; // affect the embedding to the dart + (*embeddings_[ORBIT])[d.index] = emb; // affect the embedding to the dart } /******************************************************************************* From 901ee72fd1a175d371f6f182a8db47cc6acecf0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 24 Feb 2016 10:46:12 +0100 Subject: [PATCH 154/402] fixed some remaining copy_embedding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/cmap1.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index cf474442..901d8df0 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -214,7 +214,7 @@ class CMap1_T : public CMap0_T this->new_orbit_embedding(nv); if (this->template is_embedded()) - this->copy_embedding(Face(nv.dart), Face(v.dart)); + this->template copy_embedding(nv.dart,v.dart); return nv; } @@ -266,9 +266,9 @@ class CMap1_T : public CMap0_T Face f = add_face_topo(size); if (this->template is_embedded()) - foreach_dart_of_orbit(f, [this] (Dart d) + foreach_dart_of_orbit(f, [this] (Dart v) { - this->new_orbit_embedding(v); + this->new_orbit_embedding(Vertex(v)); }); if (this->template is_embedded()) this->new_orbit_embedding(f); From 1f6fc7168908e56beacc4cf52091861b18368e65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 24 Feb 2016 10:46:29 +0100 Subject: [PATCH 155/402] Removed unnecessary to_concrete() call. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/map_base.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 1425c84f..0a4091c9 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -380,11 +380,10 @@ class MapBase : public MapBaseData AttributeHandler counter = add_attribute("__tmp_counter"); for (unsigned int& i : counter) i = 0; - ConcreteMap* cmap = to_concrete(); - foreach_cell([cmap, &counter] (Cell c) + foreach_cell([this, &counter] (Cell c) { if (counter[c] > 0) - cmap->new_orbit_embedding(c); + this->new_orbit_embedding(c); counter[c]++; }); From a5f4f323bea2dd0ec88c1a42f12cd6d6228d8e00 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Wed, 24 Feb 2016 10:54:08 +0100 Subject: [PATCH 156/402] fixed compilation with MSVC 2013. Signed-off-by: Etienne Schmitt --- cgogn/core/CMakeLists.txt | 3 +++ cgogn/core/cmap/cmap0.h | 4 ++-- cgogn/core/cmap/cmap1.h | 4 ++-- cgogn/core/cmap/cmap2.h | 6 +++--- cgogn/core/cmap/cmap3.h | 6 +++--- cgogn/core/cmap/map_base_data.h | 8 +++++--- cgogn/geometry/algos/ear_triangulation.h | 2 +- cgogn/geometry/tests/algos/algos_test.cpp | 7 ++++--- cgogn/multiresolution/cph/cph2.cpp | 2 +- cgogn/multiresolution/cph/cph3.cpp | 2 +- cgogn/multiresolution/cph/cph3.h | 4 ++-- cgogn/multiresolution/cph/ihcmap2.cpp | 2 +- cgogn/multiresolution/cph/ihcmap2.h | 4 ++-- cgogn/multiresolution/cph/ihcmap2_adaptive.cpp | 2 +- cgogn/multiresolution/cph/ihcmap2_regular.cpp | 2 +- cgogn/multiresolution/cph/ihcmap3.cpp | 2 +- cgogn/multiresolution/cph/ihcmap3.h | 2 +- thirdparty/OffBinConverter/off_ascii2bin.cpp | 1 + 18 files changed, 35 insertions(+), 28 deletions(-) diff --git a/cgogn/core/CMakeLists.txt b/cgogn/core/CMakeLists.txt index a3de8ca8..43382fec 100644 --- a/cgogn/core/CMakeLists.txt +++ b/cgogn/core/CMakeLists.txt @@ -72,6 +72,9 @@ add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) if(NOT MSVC) target_compile_options(${PROJECT_NAME} PUBLIC "-std=c++11") endif() +if(MSVC) + target_compile_options(${PROJECT_NAME} PUBLIC "-D_USE_MATH_DEFINES") +endif() set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "_d") diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index 1fc3cb5d..431a3c49 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -42,8 +42,8 @@ class CMap0_T : public MapBase using Self = CMap0_T; friend class MapBase; - template friend class DartMarker_T; - template friend class DartMarkerStore; + template friend class cgogn::DartMarker_T; + template friend class cgogn::DartMarkerStore; using Vertex = Cell; diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 901d8df0..63ba59bb 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -42,8 +42,8 @@ class CMap1_T : public CMap0_T using Self = CMap1_T; friend class MapBase; - template friend class DartMarker_T; - template friend class DartMarkerStore; + template friend class cgogn::DartMarker_T; + template friend class cgogn::DartMarkerStore; using Vertex = Cell; using Face = Cell; diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 69f83174..d2991497 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -48,8 +48,8 @@ class CMap2_T : public CMap1_T friend class MapBase; friend class CMap2Builder_T; - template friend class DartMarker_T; - template friend class DartMarkerStore; + template friend class cgogn::DartMarker_T; + template friend class cgogn::DartMarkerStore; using CDart = Cell; using Vertex = Cell; @@ -464,7 +464,7 @@ class CMap2_T : public CMap1_T if (this->template is_embedded()) { - const unsigned int idx = this->template get_embedding(Volume(d)); + const unsigned int idx = this->get_embedding(Volume(d)); foreach_dart_of_orbit(new_face, [this, idx] (Dart v) { this->template set_embedding(v, idx); diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 7280a9fa..e138510f 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -48,8 +48,8 @@ class CMap3_T : public CMap2_T friend class MapBase; friend class CMap3Builder_T; - template friend class DartMarker_T; - template friend class DartMarkerStore; + template friend class cgogn::DartMarker_T; + template friend class cgogn::DartMarkerStore; using CDart = Cell; using Vertex = Cell; @@ -298,7 +298,7 @@ class CMap3_T : public CMap2_T if(!dmarker.is_marked(e)) { visitedFaces.push_back(e); - dmarker.template mark_orbit(Face2(e)); + dmarker.mark_orbit(Face2(e)); } } else { if(boundary_marker.is_marked(e)) diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index 612b51b7..efb90298 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -39,11 +39,13 @@ #include #include - -#define CGOGN_CHECK_CONCRETE_TYPE static_assert(std::is_same::value,"The concrete map type has to be equal to Self") #define CGOGN_CHECK_DYNAMIC_TYPE cgogn_message_assert(typeid(*this).hash_code() == typeid(Self).hash_code(),\ std::string("dynamic type of current object : ") + cgogn::internal::demangle(std::string(typeid(*this).name())) + std::string(",\nwhereas Self = ") + cgogn::name_of_type(Self())) - +#ifndef _MSC_VER +#define CGOGN_CHECK_CONCRETE_TYPE static_assert(std::is_same::value,"The concrete map type has to be equal to Self") +#else +#define CGOGN_CHECK_CONCRETE_TYPE CGOGN_CHECK_DYNAMIC_TYPE +#endif namespace cgogn { diff --git a/cgogn/geometry/algos/ear_triangulation.h b/cgogn/geometry/algos/ear_triangulation.h index 0a4b7dd0..15aafab2 100644 --- a/cgogn/geometry/algos/ear_triangulation.h +++ b/cgogn/geometry/algos/ear_triangulation.h @@ -303,7 +303,7 @@ class EarTriangulation if (nb_verts_ ==3) { - map_.template foreach_incident_vertex(face_, [&] (Vertex v) + map_.foreach_incident_vertex(face_, [&] (Vertex v) { table_indices.push_back(map_.get_embedding(v)); }); diff --git a/cgogn/geometry/tests/algos/algos_test.cpp b/cgogn/geometry/tests/algos/algos_test.cpp index c45abcd5..7e6c0041 100644 --- a/cgogn/geometry/tests/algos/algos_test.cpp +++ b/cgogn/geometry/tests/algos/algos_test.cpp @@ -43,9 +43,10 @@ using EigenVec3d = Eigen::Vector3d; using CMap2 = cgogn::CMap2; template using VertexAttributeHandler = CMap2::VertexAttributeHandler; -using Vertex = typename CMap2::Vertex; -using Edge = typename CMap2::Edge; -using Face = typename CMap2::Face; + +using Vertex = CMap2::Vertex; +using Edge = CMap2::Edge; +using Face = CMap2::Face; TEST(Algos_TEST, TriangleArea) { diff --git a/cgogn/multiresolution/cph/cph2.cpp b/cgogn/multiresolution/cph/cph2.cpp index 8b80c4e5..0d51adb5 100644 --- a/cgogn/multiresolution/cph/cph2.cpp +++ b/cgogn/multiresolution/cph/cph2.cpp @@ -21,7 +21,7 @@ * * *******************************************************************************/ -#define CGOGN_CORE_DLL_EXPORT +#define CGOGN_MULTIRESOLUTION_DLL_EXPORT #define MULTIRESOLUTION_CPH_CPH2_CPP_ #include diff --git a/cgogn/multiresolution/cph/cph3.cpp b/cgogn/multiresolution/cph/cph3.cpp index fc7f676d..ff6ce2c2 100644 --- a/cgogn/multiresolution/cph/cph3.cpp +++ b/cgogn/multiresolution/cph/cph3.cpp @@ -21,7 +21,7 @@ * * *******************************************************************************/ -#define CGOGN_CORE_DLL_EXPORT +#define CGOGN_MULTIRESOLUTION_DLL_EXPORT #define MULTIRESOLUTION_CPH_CPH3_CPP_ #include diff --git a/cgogn/multiresolution/cph/cph3.h b/cgogn/multiresolution/cph/cph3.h index 487711c7..a5e53056 100644 --- a/cgogn/multiresolution/cph/cph3.h +++ b/cgogn/multiresolution/cph/cph3.h @@ -75,12 +75,12 @@ class CPH3 : public CPH2 inline unsigned int get_tri_refinement_face_id(Dart d, Dart e) const { - + return 0u; } inline unsigned int get_quad_refinement_face_id(Dart d) const { - + return 0u; } }; diff --git a/cgogn/multiresolution/cph/ihcmap2.cpp b/cgogn/multiresolution/cph/ihcmap2.cpp index 4cc80055..09028488 100644 --- a/cgogn/multiresolution/cph/ihcmap2.cpp +++ b/cgogn/multiresolution/cph/ihcmap2.cpp @@ -21,7 +21,7 @@ * * *******************************************************************************/ -#define CGOGN_CORE_DLL_EXPORT +#define CGOGN_MULTIRESOLUTION_DLL_EXPORT #define MULTIRESOLUTION_CPH_IHCMAP2_CPP_ #include diff --git a/cgogn/multiresolution/cph/ihcmap2.h b/cgogn/multiresolution/cph/ihcmap2.h index 40a3d8cc..b441b8e9 100644 --- a/cgogn/multiresolution/cph/ihcmap2.h +++ b/cgogn/multiresolution/cph/ihcmap2.h @@ -66,8 +66,8 @@ class IHCMap2_T : public CMap2_T, public CPH2 using Self = IHCMap2_T; friend class MapBase; - template friend class DartMarker_T; - template friend class DartMarkerStore; + template friend class cgogn::DartMarker_T; + template friend class cgogn::DartMarkerStore; // static const Orbit DART = Inherit_CMAP::DART; // static const Orbit VERTEX = Inherit_CMAP::VERTEX; diff --git a/cgogn/multiresolution/cph/ihcmap2_adaptive.cpp b/cgogn/multiresolution/cph/ihcmap2_adaptive.cpp index 410a7f4d..b22ef849 100644 --- a/cgogn/multiresolution/cph/ihcmap2_adaptive.cpp +++ b/cgogn/multiresolution/cph/ihcmap2_adaptive.cpp @@ -21,7 +21,7 @@ * * *******************************************************************************/ -#define CGOGN_CORE_DLL_EXPORT +#define CGOGN_MULTIRESOLUTION_DLL_EXPORT #define MULTIRESOLUTION_CPH_IHCMAP2_ADAPTIVE_CPP_ #include diff --git a/cgogn/multiresolution/cph/ihcmap2_regular.cpp b/cgogn/multiresolution/cph/ihcmap2_regular.cpp index ecfd2336..d9283b98 100644 --- a/cgogn/multiresolution/cph/ihcmap2_regular.cpp +++ b/cgogn/multiresolution/cph/ihcmap2_regular.cpp @@ -21,7 +21,7 @@ * * *******************************************************************************/ -#define CGOGN_CORE_DLL_EXPORT +#define CGOGN_MULTIRESOLUTION_DLL_EXPORT #define MULTIRESOLUTION_CPH_IHCMAP2_REGULAR_CPP_ #include diff --git a/cgogn/multiresolution/cph/ihcmap3.cpp b/cgogn/multiresolution/cph/ihcmap3.cpp index a544aa88..0bacad5c 100644 --- a/cgogn/multiresolution/cph/ihcmap3.cpp +++ b/cgogn/multiresolution/cph/ihcmap3.cpp @@ -21,7 +21,7 @@ * * *******************************************************************************/ -#define CGOGN_CORE_DLL_EXPORT +#define CGOGN_MULTIRESOLUTION_DLL_EXPORT #define MULTIRESOLUTION_CPH_IHCMAP3_CPP_ #include diff --git a/cgogn/multiresolution/cph/ihcmap3.h b/cgogn/multiresolution/cph/ihcmap3.h index 43bdc992..d9a438e4 100644 --- a/cgogn/multiresolution/cph/ihcmap3.h +++ b/cgogn/multiresolution/cph/ihcmap3.h @@ -366,7 +366,7 @@ class IHCMap3_T :public CMap3_T, public CPH3 "Orbit not supported in a CMap2"); switch (ORBIT) { - case Orbit::DART: foreach_dart_of_DART(c, f); break; + case Orbit::DART: f(c.dart); break; case Orbit::PHI1: foreach_dart_of_PHI1(c, f); break; case Orbit::PHI2: foreach_dart_of_PHI2(c, f); break; case Orbit::PHI1_PHI2: foreach_dart_of_PHI1_PHI2(c, f); break; diff --git a/thirdparty/OffBinConverter/off_ascii2bin.cpp b/thirdparty/OffBinConverter/off_ascii2bin.cpp index 91d2b0e0..77319721 100644 --- a/thirdparty/OffBinConverter/off_ascii2bin.cpp +++ b/thirdparty/OffBinConverter/off_ascii2bin.cpp @@ -1,6 +1,7 @@ #include #include #include +#include inline unsigned int changeEndian(unsigned int x) { From aaa3ba5f34778c5258fb2b49b3cf156173a61954 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 24 Feb 2016 12:10:50 +0100 Subject: [PATCH 157/402] fixed compilation. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/cmap1.cpp | 2 +- cgogn/core/cmap/cmap2.cpp | 2 +- cgogn/core/cmap/cmap3.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cgogn/core/cmap/cmap1.cpp b/cgogn/core/cmap/cmap1.cpp index d7ea2051..6558862f 100644 --- a/cgogn/core/cmap/cmap1.cpp +++ b/cgogn/core/cmap/cmap1.cpp @@ -29,7 +29,7 @@ namespace cgogn { -// template class CGOGN_CORE_API CMap1_T>; + template class CGOGN_CORE_API CMap1_T>; template class CGOGN_CORE_API DartMarker>; template class CGOGN_CORE_API DartMarkerStore>; template class CGOGN_CORE_API DartMarkerNoUnmark>; diff --git a/cgogn/core/cmap/cmap2.cpp b/cgogn/core/cmap/cmap2.cpp index ecedf4c2..c477312f 100644 --- a/cgogn/core/cmap/cmap2.cpp +++ b/cgogn/core/cmap/cmap2.cpp @@ -29,7 +29,7 @@ namespace cgogn { -// template class CGOGN_CORE_API CMap2_T>; + template class CGOGN_CORE_API CMap2_T>; template class CGOGN_CORE_API DartMarker>; template class CGOGN_CORE_API DartMarkerStore>; template class CGOGN_CORE_API DartMarkerNoUnmark>; diff --git a/cgogn/core/cmap/cmap3.cpp b/cgogn/core/cmap/cmap3.cpp index c2cbe7d0..fe164fdd 100644 --- a/cgogn/core/cmap/cmap3.cpp +++ b/cgogn/core/cmap/cmap3.cpp @@ -29,7 +29,7 @@ namespace cgogn { -// template class CGOGN_CORE_API CMap3_T>; + template class CGOGN_CORE_API CMap3_T>; template class CGOGN_CORE_API DartMarker>; template class CGOGN_CORE_API DartMarkerStore>; template class CGOGN_CORE_API DartMarkerNoUnmark>; From 4575b6021237fb852217afa449c8b928398492fd Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Wed, 24 Feb 2016 11:16:59 +0100 Subject: [PATCH 158/402] fixed again the compilation with MSVC. Signed-off-by: Etienne Schmitt --- cgogn/core/cmap/cmap0.h | 4 ++-- cgogn/core/cmap/cmap1.h | 2 +- cgogn/core/cmap/cmap2.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index bc1c459d..3196d48b 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -42,8 +42,8 @@ class CMap0_T : public MapBase using Self = CMap0_T; friend class MapBase; - friend class DartMarker_T;; - friend class DartMarkerStore; + friend class DartMarker_T; + friend class cgogn::DartMarkerStore; using Vertex = Cell; diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 91b167f2..b386bcda 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -43,7 +43,7 @@ class CMap1_T : public CMap0_T friend class MapBase; friend class DartMarker_T; - friend class DartMarkerStore; + friend class cgogn::DartMarkerStore; using Vertex = Cell; using Face = Cell; diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 65898a0a..e4dd8cae 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -49,7 +49,7 @@ class CMap2_T : public CMap1_T friend class MapBase; friend class CMap2Builder_T; friend class DartMarker_T; - friend class DartMarkerStore; + friend class cgogn::DartMarkerStore; using CDart = Cell; using Vertex = Cell; From d9f9034d4d44d5cecee789faa89dd8eab662c39a Mon Sep 17 00:00:00 2001 From: David Cazier Date: Wed, 24 Feb 2016 13:18:28 +0100 Subject: [PATCH 159/402] off_ascii2bin.cpp => ajout de #include --- cgogn/core/cmap/cmap2_builder.h | 4 ++-- cgogn/core/cmap/map_base.h | 9 ++++----- cgogn/multiresolution/cph/ihcmap2.h | 4 ++-- thirdparty/OffBinConverter/off_ascii2bin.cpp | 1 + 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/cgogn/core/cmap/cmap2_builder.h b/cgogn/core/cmap/cmap2_builder.h index 04c0649d..99692038 100644 --- a/cgogn/core/cmap/cmap2_builder.h +++ b/cgogn/core/cmap/cmap2_builder.h @@ -63,9 +63,9 @@ class CMap2Builder_T } template - inline void set_embedding(Cell c, unsigned int emb) + inline void set_embedding(Dart d, unsigned int emb) { - map_.set_embedding(c, emb); + map_.set_embedding(d, emb); } inline void phi2_sew(Dart d, Dart e) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 474ba216..0b189358 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -361,9 +361,9 @@ class MapBase : public MapBaseData } template - inline void copy_embedding(Cell dest, Cell src) + inline void copy_embedding(Dart dest, Dart src) { - this->set_embedding(dest, this->get_embedding(src)); + this->set_embedding(dest, this->get_embedding(src)); } public: @@ -380,11 +380,10 @@ class MapBase : public MapBaseData AttributeHandler counter = add_attribute("__tmp_counter"); for (unsigned int& i : counter) i = 0; - ConcreteMap* cmap = to_concrete(); - foreach_cell([cmap, &counter] (Cell c) + foreach_cell([this, &counter] (Cell c) { if (counter[c] > 0) - cmap->new_orbit_embedding(c); + this->new_orbit_embedding(c); counter[c]++; }); diff --git a/cgogn/multiresolution/cph/ihcmap2.h b/cgogn/multiresolution/cph/ihcmap2.h index 40a3d8cc..f1d23de7 100644 --- a/cgogn/multiresolution/cph/ihcmap2.h +++ b/cgogn/multiresolution/cph/ihcmap2.h @@ -66,8 +66,8 @@ class IHCMap2_T : public CMap2_T, public CPH2 using Self = IHCMap2_T; friend class MapBase; - template friend class DartMarker_T; - template friend class DartMarkerStore; + friend class DartMarker_T; + friend class cgogn::DartMarkerStore; // static const Orbit DART = Inherit_CMAP::DART; // static const Orbit VERTEX = Inherit_CMAP::VERTEX; diff --git a/thirdparty/OffBinConverter/off_ascii2bin.cpp b/thirdparty/OffBinConverter/off_ascii2bin.cpp index 91d2b0e0..115070d8 100644 --- a/thirdparty/OffBinConverter/off_ascii2bin.cpp +++ b/thirdparty/OffBinConverter/off_ascii2bin.cpp @@ -1,5 +1,6 @@ #include #include +#include #include inline unsigned int changeEndian(unsigned int x) From 25c3fcc46b67d91bca904308b13f18f9ba3c6128 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Wed, 24 Feb 2016 15:27:29 +0100 Subject: [PATCH 160/402] Remove Cell from copy_embedding and set_embedding + Somes fix for MSVC 2013 --- cgogn/core/cmap/cmap1.h | 2 +- cgogn/core/cmap/cmap2.h | 79 +++++++++++------------ cgogn/core/cmap/cmap3.h | 6 +- cgogn/core/cmap/map_base.h | 2 +- cgogn/geometry/tests/algos/algos_test.cpp | 6 +- cgogn/geometry/types/vec.h | 2 +- 6 files changed, 47 insertions(+), 50 deletions(-) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index db867acd..4c8f64b9 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -215,7 +215,7 @@ class CMap1_T : public CMap0_T this->new_orbit_embedding(nv); if (this->template is_embedded()) - this->copy_embedding(Face(nv.dart), Face(v.dart)); + this->copy_embedding(nv.dart, v.dart); return nv; } diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 11fd3e5f..6c995fc6 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -25,14 +25,12 @@ #define CORE_CMAP_CMAP2_H_ #include -#include namespace cgogn { // forward declaration of CMap2Builder_T -template -class CMap2Builder_T; +template class CMap2Builder_T; template class CMap2_T : public CMap1_T @@ -208,39 +206,39 @@ class CMap2_T : public CMap1_T { CGOGN_CHECK_CONCRETE_TYPE; - const Vertex v = cut_edge_topo(e); - const Dart nf = phi2(e); - const Dart f = phi2(v); + const Dart ne = cut_edge_topo(e); + const Dart nf = phi2(e); + const Dart f = phi2(ne); if (this->template is_embedded()) { - this->new_orbit_embedding(CDart(v)); + this->new_orbit_embedding(CDart(ne)); this->new_orbit_embedding(CDart(nf)); } if (this->template is_embedded()) { - this->new_orbit_embedding(v); + this->new_orbit_embedding(Vertex(ne)); } if (this->template is_embedded()) { - this->copy_embedding(Edge(nf), e); - this->new_orbit_embedding(Edge(v)); + this->copy_embedding(nf, e); + this->new_orbit_embedding(Edge(ne)); } if (this->template is_embedded()) { - this->copy_embedding(Face(v), Face(e)); - this->copy_embedding(Face(nf), Face(f)); + this->copy_embedding(ne, e); + this->copy_embedding(nf, f); } if (this->template is_embedded()) { - this->copy_embedding(Volume(v),Volume(e)); - this->copy_embedding(Volume(nf), Volume(e)); + this->copy_embedding(ne, e); + this->copy_embedding(nf, e); } - return v; + return Vertex(ne); } protected: @@ -307,8 +305,8 @@ class CMap2_T : public CMap1_T if (this->template is_embedded()) { - this->copy_embedding(Vertex(nd), e); - this->copy_embedding(Vertex(ne), d); + this->copy_embedding(nd, e); + this->copy_embedding(ne, d); } if (this->template is_embedded()) @@ -318,14 +316,14 @@ class CMap2_T : public CMap1_T if (this->template is_embedded()) { - this->copy_embedding(Face(nd), Face(d.dart)); + this->copy_embedding(nd, d.dart); this->new_orbit_embedding(Face(ne)); } if (this->template is_embedded()) { - this->copy_embedding(Volume(nd), Volume(d.dart)); - this->copy_embedding(Volume(ne), Volume(d.dart)); + this->copy_embedding(nd, d.dart); + this->copy_embedding(ne, d.dart); } } @@ -369,26 +367,28 @@ class CMap2_T : public CMap1_T const Face f = add_face_topo(size); if (this->template is_embedded()) - foreach_dart_of_orbit(f, [this] (CDart d) + foreach_dart_of_orbit(f, [this] (Dart d) { - this->new_orbit_embedding(d); + this->new_orbit_embedding(CDart(d)); this->new_orbit_embedding(CDart(phi2(d))); }); if (this->template is_embedded()) - foreach_dart_of_orbit(f, [this] (Vertex v) + foreach_dart_of_orbit(f, [this] (Dart d) { - this->new_orbit_embedding(v); + this->new_orbit_embedding(Vertex(d)); }); if (this->template is_embedded()) - foreach_dart_of_orbit(f, [this] (Edge e) + foreach_dart_of_orbit(f, [this] (Dart d) { - this->new_orbit_embedding(e); + this->new_orbit_embedding(Edge(d)); }); - if (this->template is_embedded()) + if (this->template is_embedded()) { this->new_orbit_embedding(f); + this->new_orbit_embedding(Face(phi2(f.dart))); + } if (this->template is_embedded()) this->new_orbit_embedding(Volume(f.dart)); @@ -417,15 +417,12 @@ class CMap2_T : public CMap1_T if (d_phi1 != d) { - Dart next = this->add_dart(); // Add a new edge there and link it to the face - this->phi1_sew(first, next); // the edge is linked to the face - phi2_sew(d_next, next); // the face is linked to the hole + Dart next = this->split_vertex_topo(first); // Add a new vertex into the built face + phi2_sew(d_next, next); // and link the face to the hole } } while (d_phi1 != d); } -protected: - /** * @brief close_map closes the map so that there are no phi2 fix points */ @@ -441,21 +438,21 @@ class CMap2_T : public CMap1_T const Face new_face = phi2(d); if (this->template is_embedded()) - foreach_dart_of_orbit(new_face, [this] (CDart d) + foreach_dart_of_orbit(new_face, [this] (Dart e) { - this->new_orbit_embedding(d); + this->new_orbit_embedding(CDart(e)); }); if (this->template is_embedded()) - foreach_dart_of_orbit(new_face, [this] (Vertex v) + foreach_dart_of_orbit(new_face, [this] (Dart e) { - this->copy_embedding(v, Vertex(this->phi1(phi2(v)))); + this->copy_embedding(e, this->phi1(phi2(e))); }); if (this->template is_embedded()) - foreach_dart_of_orbit(new_face, [this] (Edge e) + foreach_dart_of_orbit(new_face, [this] (Dart e) { - this->copy_embedding(e, Edge(phi2(e))); + this->copy_embedding(e, phi2(e)); }); if (this->template is_embedded()) @@ -465,10 +462,10 @@ class CMap2_T : public CMap1_T if (this->template is_embedded()) { - const unsigned int idx = this->get_embedding(Volume(d)); - foreach_dart_of_orbit(new_face, [this, idx] (Dart v) + const unsigned int idx = this->get_embedding(d); + foreach_dart_of_orbit(new_face, [this, idx] (Dart e) { - this->set_embedding(v, idx); + this->set_embedding(e, idx); }); } } diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 2acca042..5d061ddf 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -367,7 +367,7 @@ class CMap3_T : public CMap2_T { foreach_dart_of_orbit(new_volume, [this] (Dart wd) { - this->copy_embedding(Vertex(wd), Vertex(this->phi1(phi3(wd)))); + this->copy_embedding(wd, this->phi1(phi3(wd))); }); } @@ -375,7 +375,7 @@ class CMap3_T : public CMap2_T { foreach_dart_of_orbit(new_volume, [this] (Dart wd) { - this->copy_embedding(Edge(wd), Edge(phi3(wd))); + this->copy_embedding(wd, phi3(wd)); }); } @@ -383,7 +383,7 @@ class CMap3_T : public CMap2_T { foreach_dart_of_orbit(new_volume, [this] (Dart wd) { - this->copy_embedding(Face(wd), Face(phi3(wd))); + this->copy_embedding(wd, phi3(wd)); }); } diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 0b189358..dde93488 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -394,7 +394,7 @@ class MapBase : public MapBaseData bool is_well_embedded(Cell c) const { const ConcreteMap* cmap = to_concrete(); - unsigned int index = this->get_embedding(c); + //unsigned int index = this->get_embedding(c); bool result = true; std::map emb_set; diff --git a/cgogn/geometry/tests/algos/algos_test.cpp b/cgogn/geometry/tests/algos/algos_test.cpp index c45abcd5..892af6af 100644 --- a/cgogn/geometry/tests/algos/algos_test.cpp +++ b/cgogn/geometry/tests/algos/algos_test.cpp @@ -43,9 +43,9 @@ using EigenVec3d = Eigen::Vector3d; using CMap2 = cgogn::CMap2; template using VertexAttributeHandler = CMap2::VertexAttributeHandler; -using Vertex = typename CMap2::Vertex; -using Edge = typename CMap2::Edge; -using Face = typename CMap2::Face; +using Vertex = CMap2::Vertex; +using Edge = CMap2::Edge; +using Face = CMap2::Face; TEST(Algos_TEST, TriangleArea) { diff --git a/cgogn/geometry/types/vec.h b/cgogn/geometry/types/vec.h index 4a290bdc..7847bc2f 100644 --- a/cgogn/geometry/types/vec.h +++ b/cgogn/geometry/types/vec.h @@ -58,7 +58,7 @@ class Vec_T using Self = Vec_T; using Scalar = typename std::remove_cv< typename std::remove_reference::type >::type; - inline Vec_T() : data_() {} +// inline Vec_T() : data_() {} template inline Vec_T(Args... a) : data_({ std::forward(a)... }) From 72187d05b67efad1c13cb63e613a81b7b7d80eb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 24 Feb 2016 15:45:28 +0100 Subject: [PATCH 161/402] using cmake to detect endiannesss and wrote some utilitary functions. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- CMakeLists.txt | 12 +++ cgogn/core/CMakeLists.txt | 1 + cgogn/core/utils/definitions.h | 26 ----- cgogn/core/utils/endian.h | 102 +++++++++++++++++++ thirdparty/OffBinConverter/CMakeLists.txt | 4 + thirdparty/OffBinConverter/off_ascii2bin.cpp | 15 ++- 6 files changed, 125 insertions(+), 35 deletions(-) create mode 100644 cgogn/core/utils/endian.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d693ac85..95f43b2d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -108,6 +108,18 @@ if(CGOGN_BUILD_TESTS) endif() endif(CGOGN_BUILD_TESTS) +#### Endianness detection +include (TestBigEndian) +test_big_endian(CGOGN_TEST_BIG_ENDIAN) +add_definitions("-DCGOGN_LITTLE_ENDIAN=1234") +add_definitions("-DCGOGN_BIG_ENDIAN=4321") +if(${CGOGN_TEST_BIG_ENDIAN}) + add_definitions("-DCGOGN_ENDIANNESS=CGOGN_BIG_ENDIAN") +else() + add_definitions("-DCGOGN_ENDIANNESS=CGOGN_LITTLE_ENDIAN") +endif() + + add_subdirectory(${CGOGN_THIRDPARTY_DIR}) add_subdirectory(${CGOGN_SOURCE_DIR}) diff --git a/cgogn/core/CMakeLists.txt b/cgogn/core/CMakeLists.txt index 43382fec..41bfb287 100644 --- a/cgogn/core/CMakeLists.txt +++ b/cgogn/core/CMakeLists.txt @@ -31,6 +31,7 @@ set(HEADER_FILES utils/buffers.h utils/definitions.h utils/dll.h + utils/endian.h utils/make_unique.h utils/name_types.h utils/serialization.h diff --git a/cgogn/core/utils/definitions.h b/cgogn/core/utils/definitions.h index 52840b57..3b38cec3 100644 --- a/cgogn/core/utils/definitions.h +++ b/cgogn/core/utils/definitions.h @@ -134,33 +134,7 @@ #define CGOGN_PRAGMA_EIGEN_REMOVE_WARNINGS_OFF #endif - #define CGOGN_QUOTE(name) #name #define CGOGN_STR(macro) CGOGN_QUOTE(macro) -#define CGOGN_LITTLE_ENDIAN 1234 -#define CGOGN_BIG_ENDIAN 4321 - -#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \ - defined(__BYTE_ORDER__) && __BYTE_ORDER__ ==__ORDER_BIG_ENDIAN__ || \ - defined(__BIG_ENDIAN__) || \ - defined(__ARMEB__) || \ - defined(__THUMBEB__) || \ - defined(__AARCH64EB__) || \ - defined(_MIBSEB) || defined(__MIBSEB) || defined(__MIBSEB__) -#define CGOGN_ENDIANNESS CGOGN_BIG_ENDIAN -#else -#if defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || \ - defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || \ - defined(__LITTLE_ENDIAN__) || \ - defined(__ARMEL__) || \ - defined(__THUMBEL__) || \ - defined(__AARCH64EL__) || \ - defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) -#define CGOGN_ENDIANNESS CGOGN_LITTLE_ENDIAN -#else -#define CGOGN_ENDIANNESS 0 -#endif -#endif - #endif // CORE_UTILS_DEFINITIONS_H_ diff --git a/cgogn/core/utils/endian.h b/cgogn/core/utils/endian.h new file mode 100644 index 00000000..b4380bb8 --- /dev/null +++ b/cgogn/core/utils/endian.h @@ -0,0 +1,102 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef CORE_UTILS_ENDIAN_H_ +#define CORE_UTILS_ENDIAN_H_ + +#include +#include +#include + +namespace cgogn +{ + +namespace internal +{ + +#if CGOGN_ENDIANNESS == CGOGN_BIG_ENDIAN +const bool cgogn_is_big_endian = true; +const bool cgogn_is_little_endian = false; +#else +const bool cgogn_is_big_endian = false; +const bool cgogn_is_little_endian = true; +#endif + +inline std::uint16_t swap_endianness16(std::uint16_t x) +{ + return ((x >> 8) & 0x00FF) | ((x << 8) & 0xFF00); +} + +inline std::uint32_t swap_endianness32(std::uint32_t x) +{ + return ((x >> 24) & 0x000000FF) | ((x >> 8) & 0x0000FF00) | + ((x << 8) & 0x00FF0000) | ((x << 24) & 0xFF000000); +} + +inline std::uint64_t swap_endianness64(std::uint64_t x) +{ + return ((x >> 56) & 0x00000000000000FF) | ((x >> 40) & 0x000000000000FF00) | + ((x >> 24) & 0x0000000000FF0000) | ((x >> 8) & 0x00000000FF000000) | + ((x << 8) & 0x000000FF00000000) | ((x << 24) & 0x0000FF0000000000) | + ((x << 40) & 0x00FF000000000000) | ((x << 56) & 0xFF00000000000000); +} + +template +inline UINT swap_endianness_if(UINT x) +{ + static_assert(std::is_same::value || + std::is_same::value || + std::is_same::value, "This function is specialized for 16, 32 or 64 bits uints."); + + if (COND) + { + if (std::is_same::value) + return swap_endianness16(x); + if (std::is_same::value) + return swap_endianness32(x); + if (std::is_same::value) + return swap_endianness64(x); + } + return x; +} + +} // namespace internal + + +template +inline UINT swap_endianness_system_big(UINT x) +{ + return internal::swap_endianness_if(x); +} + +template +inline UINT swap_endianness_system_little(UINT x) +{ + return internal::swap_endianness_if(x); +} + + + +} // namespace cgogn + +#endif // CORE_UTILS_ENDIAN_H_ diff --git a/thirdparty/OffBinConverter/CMakeLists.txt b/thirdparty/OffBinConverter/CMakeLists.txt index 25ff33f8..c17ae6dd 100644 --- a/thirdparty/OffBinConverter/CMakeLists.txt +++ b/thirdparty/OffBinConverter/CMakeLists.txt @@ -1 +1,5 @@ +include_directories(${CGOGN_SOURCE_DIR}) add_executable(off_ascii2bin off_ascii2bin.cpp) +if(NOT MSVC) + target_compile_options(off_ascii2bin PUBLIC "-std=c++11") +endif() diff --git a/thirdparty/OffBinConverter/off_ascii2bin.cpp b/thirdparty/OffBinConverter/off_ascii2bin.cpp index c93098cd..b2cb3a69 100644 --- a/thirdparty/OffBinConverter/off_ascii2bin.cpp +++ b/thirdparty/OffBinConverter/off_ascii2bin.cpp @@ -4,10 +4,7 @@ #include #include -inline unsigned int changeEndian(unsigned int x) -{ - return (x>>24) | ((x<<8) & 0x00FF0000) | ((x>>8) & 0x0000FF00) | (x<<24); -} +#include int main(int argc, char **argv) { @@ -37,9 +34,9 @@ int main(int argc, char **argv) ifs >> np; ifs >> ne; - unsigned int nv_be = changeEndian(nv); - unsigned int np_be = changeEndian(np); - unsigned int ne_be = changeEndian(ne); + unsigned int nv_be = cgogn::swap_endianness_system_big(nv); + unsigned int np_be = cgogn::swap_endianness_system_big(np); + unsigned int ne_be = cgogn::swap_endianness_system_big(ne); ofs << "OFF BINARY"<< std::endl; @@ -57,7 +54,7 @@ int main(int argc, char **argv) unsigned int* ptr = reinterpret_cast(vertices); for (unsigned int i=0; i<3*nv;++i) { - *ptr = changeEndian(*ptr); + *ptr = cgogn::swap_endianness_system_big(*ptr); ptr++; } @@ -85,7 +82,7 @@ int main(int argc, char **argv) ptr = reinterpret_cast(&(prim[0])); for (unsigned int i=0; i Date: Wed, 24 Feb 2016 15:48:36 +0100 Subject: [PATCH 162/402] is_embedded with Orbit or Cell parameter --- cgogn/core/cmap/map_base.h | 155 +++++++++++++++----------------- cgogn/core/cmap/map_base_data.h | 22 +++-- cgogn/core/cmap/sanity_check.h | 4 +- 3 files changed, 90 insertions(+), 91 deletions(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 6b81b3d4..dc27796f 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -222,7 +222,7 @@ class MapBase : public MapBaseData { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - if (!this->template is_embedded>()) + if (!this->template is_embedded()) create_embedding(); ChunkArray* ca = this->attributes_[ORBIT].template add_attribute(attribute_name); return AttributeHandler(this, ca); @@ -296,7 +296,7 @@ class MapBase : public MapBaseData else { std::lock_guard lock(this->mark_attributes_mutex_[ORBIT]); - if (!this->template is_embedded>()) + if (!this->template is_embedded()) create_embedding(); ChunkArray* ca = this->attributes_[ORBIT].add_marker_attribute(); return ca; @@ -311,7 +311,7 @@ class MapBase : public MapBaseData inline void release_mark_attribute(ChunkArray* ca) { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - cgogn_message_assert(this->template is_embedded>(), + cgogn_message_assert(this->template is_embedded(), "Invalid parameter: orbit not embedded"); this->mark_attributes_[ORBIT][this->get_current_thread_index()].push_back(ca); @@ -328,7 +328,7 @@ class MapBase : public MapBaseData inline void create_embedding() { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - cgogn_message_assert(!this->template is_embedded>(), "Invalid parameter: orbit is already embedded"); + cgogn_message_assert(!this->template is_embedded(), "Invalid parameter: orbit is already embedded"); std::ostringstream oss; oss << "EMB_" << orbit_name(ORBIT); @@ -360,12 +360,6 @@ class MapBase : public MapBaseData return emb; } - template - inline void copy_embedding(Dart dest, Dart src) - { - this->template set_embedding(dest, this->get_embedding(Cell(src))); - } - public: /** @@ -375,7 +369,7 @@ class MapBase : public MapBaseData void enforce_unique_orbit_embedding() { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - cgogn_message_assert(this->template is_embedded>(), "Invalid parameter: orbit not embedded"); + cgogn_message_assert(this->template is_embedded(), "Invalid parameter: orbit not embedded"); AttributeHandler counter = add_attribute("__tmp_counter"); for (unsigned int& i : counter) i = 0; @@ -422,14 +416,14 @@ class MapBase : public MapBaseData *******************************************************************************/ template - bool is_topo_cache_enabled() const + inline bool is_topo_cache_enabled() const { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); return this->global_topo_cache_[ORBIT] != nullptr; } template - void enable_topo_cache() + inline void enable_topo_cache() { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); cgogn_message_assert(!is_topo_cache_enabled(), "Trying to enable an enabled global topo cache"); @@ -439,7 +433,7 @@ class MapBase : public MapBaseData } template - void update_topo_cache() + inline void update_topo_cache() { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); cgogn_message_assert(is_topo_cache_enabled(), "Trying to update a disabled global topo cache"); @@ -451,7 +445,7 @@ class MapBase : public MapBaseData } template - void disable_topo_cache() + inline void disable_topo_cache() { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); cgogn_message_assert(is_topo_cache_enabled(), "Trying to disable a disabled global topo cache"); @@ -470,11 +464,11 @@ class MapBase : public MapBaseData * @param c1 first cell to compare * @param c2 second cell to compare */ - template - bool same_cell(CellType c1, CellType c2) const + template + bool same_cell(Cell c1, Cell c2) const { - if (this->template is_embedded()) - return this->get_embedding(c1) == this->get_embedding(c2); + if (this->template is_embedded()) + return get_embedding(c1) == get_embedding(c2); const ConcreteMap* cmap = to_concrete(); bool result = false; @@ -505,7 +499,7 @@ class MapBase : public MapBaseData template unsigned int nb_cells() const { - if (this->template is_embedded>()) + if (this->template is_embedded()) return this->attributes_[ORBIT].size(); else { @@ -607,7 +601,7 @@ class MapBase : public MapBaseData static_assert(check_func_ith_parameter_type(FUNC, 0, Dart), "Wrong function first parameter type"); static_assert(check_func_ith_parameter_type(FUNC, 1, unsigned int), "Wrong function second parameter type"); - using Future = std::future< typename std::result_of::type >; + using Future = std::future::type>; using VecDarts = std::vector; ThreadPool* thread_pool = cgogn::get_thread_pool(); @@ -620,7 +614,6 @@ class MapBase : public MapBaseData futures[0].reserve(nb_threads_pool); futures[1].reserve(nb_threads_pool); - Buffers* dbuffs = cgogn::get_dart_buffers(); Dart it = Dart(this->topology_.begin()); @@ -628,7 +621,7 @@ class MapBase : public MapBaseData while (it != end) { - for (unsigned i = 0u; i < 2u; ++i) + for (unsigned int i = 0u; i < 2u; ++i) { for (unsigned int j = 0u; j < nb_threads_pool && it != end ; ++j) { @@ -641,13 +634,14 @@ class MapBase : public MapBaseData darts.push_back(it); this->topology_.next(it.index); } - futures[i].push_back(thread_pool->enqueue( [&darts ,&f](unsigned int th_id){ + futures[i].push_back(thread_pool->enqueue([&darts, &f] (unsigned int th_id) + { for (auto d : darts) f(d,th_id); })); } const unsigned int id = (i+1u)%2u; - for (auto& fu: futures[id]) + for (auto& fu : futures[id]) fu.wait(); for (auto &b : dart_buffers[id]) dbuffs->release_cell_buffer(b); @@ -658,13 +652,12 @@ class MapBase : public MapBaseData // if we reach the end of the map while filling buffers from the second set we need to clean them too. if (it == end && i == 1u) { - for (auto& fu: futures[1u]) + for (auto& fu : futures[1u]) fu.wait(); for (auto &b : dart_buffers[1u]) dbuffs->release_buffer(b); } } - } } @@ -696,8 +689,8 @@ class MapBase : public MapBaseData template inline void foreach_cell(const FUNC& f) const { - using cell_type = typename function_traits::template arg<0>::type; - static const Orbit ORBIT = cell_type::ORBIT; + using CellType = typename function_traits::template arg<0>::type; + static const Orbit ORBIT = CellType::ORBIT; switch (STRATEGY) { @@ -713,7 +706,7 @@ class MapBase : public MapBaseData case AUTO : if (is_topo_cache_enabled()) foreach_cell_topo_cache(f); - else if (this->template is_embedded()) + else if (this->template is_embedded()) foreach_cell_cell_marking(f); else foreach_cell_dart_marking(f); @@ -789,8 +782,7 @@ class MapBase : public MapBaseData template inline void foreach_cell_dart_marking(const FUNC& f) const { - using cell_type = typename function_traits::template arg<0>::type; - static const Orbit ORBIT = cell_type::ORBIT; + using CellType = typename function_traits::template arg<0>::type; DartMarker dm(*to_concrete()); for (Dart d = Dart(this->topology_.begin()), end = Dart(this->topology_.end()); @@ -799,7 +791,7 @@ class MapBase : public MapBaseData { if (!dm.is_marked(d)) { - dm.template mark_orbit(d); + dm.mark_orbit(CellType(d)); f(d); } } @@ -808,10 +800,10 @@ class MapBase : public MapBaseData template inline void parallel_foreach_cell_dart_marking(const FUNC& f) const { - using cell_type = typename function_traits::template arg<0>::type; - static const Orbit ORBIT = cell_type::ORBIT; - using VecCell = std::vector>; - using Future = std::future< typename std::result_of, unsigned int)>::type >; + using CellType = typename function_traits::template arg<0>::type; + static const Orbit ORBIT = CellType::ORBIT; + using VecCell = std::vector>; + using Future = std::future, unsigned int)>::type>; ThreadPool* thread_pool = cgogn::get_thread_pool(); const std::size_t nb_threads_pool = thread_pool->get_nb_threads(); @@ -829,8 +821,8 @@ class MapBase : public MapBaseData Dart it = Dart(this->topology_.begin()); const Dart end = Dart(this->topology_.end()); - unsigned i = 0u; // buffer id (0/1) - unsigned int j = 0u;// thread id (0..nb_threads_pool) + unsigned int i = 0u; // buffer id (0/1) + unsigned int j = 0u; // thread id (0..nb_threads_pool) while (it != end) { // fill buffer @@ -848,16 +840,17 @@ class MapBase : public MapBaseData this->topology_.next(it.index); } //launch thread - futures[i].push_back(thread_pool->enqueue( [&cells,&f](unsigned int th_id){ + futures[i].push_back(thread_pool->enqueue([&cells, &f] (unsigned int th_id) + { for (auto c : cells) f(c,th_id); - })); + })); // next thread if (++j == nb_threads_pool) { // again from 0 & change buffer j = 0; const unsigned int id = (i+1u)%2u; - for (auto& fu: futures[id]) + for (auto& fu : futures[id]) fu.wait(); for (auto &b : cells_buffers[id]) dbuffs->release_cell_buffer(b); @@ -867,11 +860,11 @@ class MapBase : public MapBaseData } // clean all at end - for (auto& fu: futures[0u]) + for (auto& fu : futures[0u]) fu.wait(); for (auto &b : cells_buffers[0u]) dbuffs->release_cell_buffer(b); - for (auto& fu: futures[1u]) + for (auto& fu : futures[1u]) fu.wait(); for (auto &b : cells_buffers[1u]) dbuffs->release_cell_buffer(b); @@ -880,8 +873,8 @@ class MapBase : public MapBaseData template inline void foreach_cell_cell_marking(const FUNC& f) const { - using cell_type = typename function_traits::template arg<0>::type; - static const Orbit ORBIT = cell_type::ORBIT; + using CellType = typename function_traits::template arg<0>::type; + static const Orbit ORBIT = CellType::ORBIT; CellMarker cm(*to_concrete()); for (Dart d = Dart(this->topology_.begin()), end = Dart(this->topology_.end()); @@ -899,10 +892,10 @@ class MapBase : public MapBaseData template inline void parallel_foreach_cell_cell_marking(const FUNC& f) const { - using cell_type = typename function_traits::template arg<0>::type; - static const Orbit ORBIT = cell_type::ORBIT; - using VecCell = std::vector>; - using Future = std::future< typename std::result_of, unsigned int)>::type >; + using CellType = typename function_traits::template arg<0>::type; + static const Orbit ORBIT = CellType::ORBIT; + using VecCell = std::vector>; + using Future = std::future, unsigned int)>::type>; ThreadPool* thread_pool = cgogn::get_thread_pool(); const std::size_t nb_threads_pool = thread_pool->get_nb_threads(); @@ -920,8 +913,8 @@ class MapBase : public MapBaseData Dart it = Dart(this->topology_.begin()); const Dart end = Dart(this->topology_.end()); - unsigned i = 0u; // buffer id (0/1) - unsigned int j = 0u;// thread id (0..nb_threads_pool) + unsigned int i = 0u; // buffer id (0/1) + unsigned int j = 0u; // thread id (0..nb_threads_pool) while (it != end) { // fill buffer @@ -938,17 +931,18 @@ class MapBase : public MapBaseData } this->topology_.next(it.index); } - //launch thread - futures[i].push_back(thread_pool->enqueue( [&cells,&f](unsigned int th_id){ + // launch thread + futures[i].push_back(thread_pool->enqueue([&cells, &f] (unsigned int th_id) + { for (auto c : cells) - f(c,th_id); - })); + f(c, th_id); + })); // next thread if (++j == nb_threads_pool) { // again from 0 & change buffer j = 0; const unsigned int id = (i+1u)%2u; - for (auto& fu: futures[id]) + for (auto& fu : futures[id]) fu.wait(); for (auto &b : cells_buffers[id]) dbuffs->release_cell_buffer(b); @@ -958,11 +952,11 @@ class MapBase : public MapBaseData } // clean all at end - for (auto& fu: futures[0u]) + for (auto& fu : futures[0u]) fu.wait(); for (auto &b : cells_buffers[0u]) dbuffs->release_cell_buffer(b); - for (auto& fu: futures[1u]) + for (auto& fu : futures[1u]) fu.wait(); for (auto &b : cells_buffers[1u]) dbuffs->release_cell_buffer(b); @@ -972,8 +966,8 @@ class MapBase : public MapBaseData template inline void foreach_cell_topo_cache(const FUNC& f) const { - using cell_type = typename function_traits::template arg<0>::type; - static const Orbit ORBIT = cell_type::ORBIT; + using CellType = typename function_traits::template arg<0>::type; + static const Orbit ORBIT = CellType::ORBIT; for (unsigned int i = this->attributes_[ORBIT].begin(), end = this->attributes_[ORBIT].end(); i != end; @@ -986,10 +980,10 @@ class MapBase : public MapBaseData template inline void parallel_foreach_cell_topo_cache(const FUNC& f) const { - using cell_type = typename function_traits::template arg<0>::type; - static const Orbit ORBIT = cell_type::ORBIT; - using VecCell = std::vector>; - using Future = std::future< typename std::result_of, unsigned int)>::type >; + using CellType = typename function_traits::template arg<0>::type; + static const Orbit ORBIT = CellType::ORBIT; + using VecCell = std::vector>; + using Future = std::future, unsigned int)>::type>; ThreadPool* thread_pool = cgogn::get_thread_pool(); const std::size_t nb_threads_pool = thread_pool->get_nb_threads(); @@ -998,7 +992,6 @@ class MapBase : public MapBaseData futures[0].reserve(nb_threads_pool); futures[1].reserve(nb_threads_pool); - const auto& attr = this->attributes_[ORBIT]; unsigned int it = attr.begin(); unsigned int end = attr.end(); @@ -1006,18 +999,19 @@ class MapBase : public MapBaseData unsigned int nbc = PARALLEL_BUFFER_SIZE; // do block of PARALLEL_BUFFER_SIZE only if nb cells is huge else just divide - if ( (end - it) < 16*nb_threads_pool*PARALLEL_BUFFER_SIZE ) + if ((end - it) < 16 * nb_threads_pool * PARALLEL_BUFFER_SIZE) nbc = (end - it) / nb_threads_pool; unsigned int local_end = it+nbc; const auto& cache = *(this->global_topo_cache_[ORBIT]); - unsigned int i=0; // used buffered futures 0/1 - unsigned int j=0;// thread num + unsigned int i = 0; // used buffered futures 0/1 + unsigned int j = 0; // thread num while (it != end) { - futures[i].push_back(thread_pool->enqueue( [&cache,&attr,it,local_end,&f](unsigned int th_id){ + futures[i].push_back(thread_pool->enqueue([&cache, &attr, it, local_end, &f] (unsigned int th_id) + { unsigned int loc_it = it; while (loc_it < local_end) { @@ -1026,12 +1020,12 @@ class MapBase : public MapBaseData } })); it = local_end; - local_end = std::min(local_end+nbc,end); + local_end = std::min(local_end + nbc, end); if (++j == nb_threads_pool) // change thread { // again from 0 & change buffer j = 0; - const unsigned int id = (i+1u)%2u; + const unsigned int id = (i+1u) % 2u; for (auto& fu: futures[id]) fu.wait(); futures[id].clear(); @@ -1040,17 +1034,16 @@ class MapBase : public MapBaseData } // wait for remaining running threads - for (auto& fu: futures[0u]) + for (auto& fu : futures[0u]) fu.wait(); - for (auto& fu: futures[1u]) + for (auto& fu : futures[1u]) fu.wait(); } template inline void foreach_cell_until_dart_marking(const FUNC& f) const { - using cell_type = typename function_traits::template arg<0>::type; - static const Orbit ORBIT = cell_type::ORBIT; + using CellType = typename function_traits::template arg<0>::type; DartMarker dm(*to_concrete()); for (Dart d = Dart(this->topology_.begin()), end = Dart(this->topology_.end()); @@ -1059,7 +1052,7 @@ class MapBase : public MapBaseData { if (!dm.is_marked(d)) { - dm.template mark_orbit(d); + dm.mark_orbit(CellType(d)); if(!f(d)) break; } @@ -1069,8 +1062,8 @@ class MapBase : public MapBaseData template inline void foreach_cell_until_cell_marking(const FUNC& f) const { - using cell_type = typename function_traits::template arg<0>::type; - static const Orbit ORBIT = cell_type::ORBIT; + using CellType = typename function_traits::template arg<0>::type; + static const Orbit ORBIT = CellType::ORBIT; CellMarker cm(*to_concrete()); for (Dart d = Dart(this->topology_.begin()), end = Dart(this->topology_.end()); @@ -1089,8 +1082,8 @@ class MapBase : public MapBaseData template inline void foreach_cell_until_topo_cache(const FUNC& f) const { - using cell_type = typename function_traits::template arg<0>::type; - static const Orbit ORBIT = cell_type::ORBIT; + using CellType = typename function_traits::template arg<0>::type; + static const Orbit ORBIT = CellType::ORBIT; for (unsigned int i = this->attributes_[ORBIT].begin(), end = this->attributes_[ORBIT].end(); i != end; diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index efb90298..b91936a8 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -241,12 +241,12 @@ class MapBaseData : public MapGen public: -// template -// inline bool is_orbit_embedded() const -// { -// static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); -// return embeddings_[ORBIT] != nullptr; -// } + template + inline bool is_embedded() const + { + static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); + return embeddings_[ORBIT] != nullptr; + } template inline bool is_embedded() const @@ -259,7 +259,7 @@ class MapBaseData : public MapGen inline unsigned int get_embedding(Cell c) const { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - cgogn_message_assert(is_embedded>(), "Invalid parameter: orbit not embedded"); + cgogn_message_assert(is_embedded(), "Invalid parameter: orbit not embedded"); cgogn_message_assert((*embeddings_[ORBIT])[c.dart.index] != EMBNULL, "get_embedding result is EMBNULL"); return (*embeddings_[ORBIT])[c.dart.index]; @@ -271,7 +271,7 @@ class MapBaseData : public MapGen inline void set_embedding(Dart d, unsigned int emb) { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - cgogn_message_assert(is_embedded>(), "Invalid parameter: orbit not embedded"); + cgogn_message_assert(is_embedded(), "Invalid parameter: orbit not embedded"); cgogn_message_assert(emb != EMBNULL,"cannot set an embedding to EMBNULL."); const unsigned int old = (*embeddings_[ORBIT])[d.index]; @@ -284,6 +284,12 @@ class MapBaseData : public MapGen (*embeddings_[ORBIT])[d.index] = emb; // affect the embedding to the dart } + template + inline void copy_embedding(Dart dest, Dart src) + { + this->template set_embedding(dest, get_embedding(Cell(src))); + } + /******************************************************************************* * Thread management *******************************************************************************/ diff --git a/cgogn/core/cmap/sanity_check.h b/cgogn/core/cmap/sanity_check.h index fe1fe85b..d6e5fa25 100644 --- a/cgogn/core/cmap/sanity_check.h +++ b/cgogn/core/cmap/sanity_check.h @@ -57,7 +57,7 @@ template bool is_orbit_embedding_unique(MAP& map) { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - cgogn_message_assert(map.template is_embedded>(), "Invalid parameter: orbit not embedded"); + cgogn_message_assert(map.template is_embedded(), "Invalid parameter: orbit not embedded"); typename MAP::template AttributeHandler counter = map.template add_attribute("__tmp_counter"); for (unsigned int& i : counter) i = 0; @@ -89,7 +89,7 @@ template bool is_container_well_referenced(MAP& map) { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - cgogn_message_assert(map.template is_embedded>(), "Invalid parameter: orbit not embedded"); + cgogn_message_assert(map.template is_embedded(), "Invalid parameter: orbit not embedded"); typename MAP::template AttributeHandler counter = map.template add_attribute("__tmp_counter"); From 504c5638e4dd76a5830bf59da69b7f08091f3ff2 Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Wed, 24 Feb 2016 16:30:26 +0100 Subject: [PATCH 163/402] remove a few "this" and useless temprary variables --- cgogn/core/cmap/map_base.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index dc27796f..40884e89 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -138,8 +138,8 @@ class MapBase : public MapBaseData inline Dart add_dart() { - Dart d(this->add_topology_element()); - this->to_concrete()->init_dart(d); + Dart d(add_topology_element()); + to_concrete()->init_dart(d); return d; } @@ -470,9 +470,8 @@ class MapBase : public MapBaseData if (this->template is_embedded()) return get_embedding(c1) == get_embedding(c2); - const ConcreteMap* cmap = to_concrete(); bool result = false; - cmap->foreach_dart_of_orbit_until(c1, [&] (Dart d) -> bool + to_concrete()->foreach_dart_of_orbit_until(c1, [&] (Dart d) -> bool { if (d == c2.dart) { @@ -515,9 +514,8 @@ class MapBase : public MapBaseData template unsigned int nb_darts_of_orbit(Cell c) const { - const ConcreteMap* cmap = to_concrete(); unsigned int result = 0u; - cmap->foreach_dart_of_orbit(c, [&result] (Dart) { ++result; }); + to_concrete()->foreach_dart_of_orbit(c, [&result] (Dart) { ++result; }); return result; } From 1e5b946168ea8ab375d624b733f547cda3306d92 Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Wed, 24 Feb 2016 17:03:45 +0100 Subject: [PATCH 164/402] also define set_embedding and copy_embedding with Cell or Orbit template parameter --- cgogn/core/cmap/cmap1.h | 43 +++++------ cgogn/core/cmap/cmap2.h | 128 ++++++++++++++++++-------------- cgogn/core/cmap/map_base_data.h | 18 ++++- 3 files changed, 104 insertions(+), 85 deletions(-) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index b386bcda..eb9cb814 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -201,7 +201,7 @@ class CMap1_T : public CMap0_T * \param d : a vertex * \return The inserted vertex * A new vertex is inserted after v in the PHI1 orbit. - * If the map has DART or FACE attributes, the inserted darts + * If the map has Vertex or Face attributes, the inserted cells * are automatically embedded on new attribute elements. */ inline Vertex split_vertex(Vertex v) @@ -214,7 +214,7 @@ class CMap1_T : public CMap0_T this->new_orbit_embedding(nv); if (this->template is_embedded()) - this->template copy_embedding(nv.dart,v.dart); + this->template copy_embedding(nv.dart, v.dart); return nv; } @@ -254,10 +254,10 @@ class CMap1_T : public CMap0_T public: /*! - * \brief Add an embedded face in the map. - * \param size : the number of darts in the built face - * \return A dart of the built face. If the map has DART or FACE attributes, - * the inserted darts are automatically embedded on new attribute elements. + * \brief Add a face in the map. + * \param size : the number of edges in the built face + * \return The built face. If the map has Vertex or Face attributes, + * the new inserted cells are automatically embedded on new attribute elements. */ Face add_face(unsigned int size) { @@ -266,12 +266,15 @@ class CMap1_T : public CMap0_T Face f = add_face_topo(size); if (this->template is_embedded()) - foreach_dart_of_orbit(f, [this] (Dart v) + { + foreach_dart_of_orbit(f, [this] (Dart d) { - this->new_orbit_embedding(Vertex(v)); + this->new_orbit_embedding(Vertex(d)); }); + } - if (this->template is_embedded()) this->new_orbit_embedding(f); + if (this->template is_embedded()) + this->new_orbit_embedding(f); return f; } @@ -357,11 +360,8 @@ class CMap1_T : public CMap0_T template inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const { - static_assert(check_func_parameter_type(FUNC, Dart), - "Wrong function parameter type"); - - static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1, - "Orbit not supported in a CMap1"); + static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); + static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1, "Orbit not supported in a CMap1"); switch (ORBIT) { @@ -392,13 +392,9 @@ class CMap1_T : public CMap0_T template inline void foreach_dart_of_orbit_until(Cell c, const FUNC& f) const { - static_assert(check_func_parameter_type(FUNC, Dart), - "Wrong function parameter type"); - static_assert(check_func_return_type(FUNC, bool), - "Wrong function return type"); - - static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1, - "Orbit not supported in a CMap1"); + static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); + static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); + static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1, "Orbit not supported in a CMap1"); switch (ORBIT) { @@ -423,8 +419,7 @@ class CMap1_T : public CMap0_T template inline void foreach_incident_vertex(Face f, const FUNC& func) const { - static_assert(check_func_parameter_type(FUNC, Vertex), - "Wrong function cell parameter type"); + static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); foreach_dart_of_orbit(f, [&func](Dart v) {func(Vertex(v));}); } }; @@ -449,8 +444,6 @@ extern template class CGOGN_CORE_API CellMarkerStore, CM extern template class CGOGN_CORE_API CellMarkerStore, CMap1::Face::ORBIT>; #endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_MAP_MAP1_CPP_)) - - } // namespace cgogn #endif // CORE_CMAP_CMAP1_H_ diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index e4dd8cae..e5aaee35 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -192,16 +192,17 @@ class CMap2_T : public CMap1_T public: /** - * \brief Cut an embedded edge. - * \param e : A dart that represents the edge to cut - * \return A dart of the inserted vertex + * \brief Cut an edge. + * \param e : the edge to cut + * \return The inserted vertex * The edge e is cut by inserting a new vertex. - * The returned dart is the dart of the inserted vertex that belongs to the face of e. + * The returned vertex is represented by the dart of the inserted vertex that belongs to the face of e. * If the map has Dart, Vertex, Edge, Face or Volume attributes, - * the inserted darts are automatically embedded on new attribute elements. - * - Actually a Vertex attribute is created, if needed, for the inserted vertex. - * - If needed, an Edge attribute is created for the edge inserted after e. - * The Edge attribute of e is kept unchanged. + * the inserted cells are automatically embedded on new attribute elements. + * More precisely : + * - a Vertex attribute is created, if needed, for the inserted vertex. + * - an Edge attribute is created, if needed, for the edge inserted after e. + * - the Edge attribute of e is kept unchanged. */ inline Vertex cut_edge(Edge e) { @@ -211,46 +212,48 @@ class CMap2_T : public CMap1_T const Dart nf = phi2(e); const Dart f = phi2(v); - if (this->template is_embedded()) { + if (this->template is_embedded()) + { this->new_orbit_embedding(CDart(v)); this->new_orbit_embedding(CDart(nf)); } if (this->template is_embedded()) - { this->new_orbit_embedding(v); - } if (this->template is_embedded()) { - this->template copy_embedding(nf, e); + this->template copy_embedding(nf, e); this->new_orbit_embedding(Edge(v)); } if (this->template is_embedded()) { - this->template copy_embedding(v, e); - this->template copy_embedding(nf, f); + this->template copy_embedding(v, e); + this->template copy_embedding(nf, f); } if (this->template is_embedded()) { - this->template copy_embedding(v,e); - this->template copy_embedding(nf, e); + this->template copy_embedding(v, e); + this->template copy_embedding(nf, e); } return v; } protected: - void merge_adjacent_edges_topo(Dart d) { + + void merge_adjacent_edges_topo(Dart d) + { Dart e = this->phi_1(this->phi2(d)); cgogn_message_assert(d == this->phi_1(this->phi2(e)), "merge_adjacent_edge: the degree of the vertex of d should be 2"); // TODO } - void merge_adjacent_faces_topo(Dart d) { + void merge_adjacent_faces_topo(Dart d) + { Dart e = this->phi2(d); // TODO } @@ -258,7 +261,7 @@ class CMap2_T : public CMap1_T protected: /** - * \brief Cut the face of d and e by inserting an edge between the vertex of d and e + * \brief Cut the face of d and e by inserting an edge between the vertices of d and e * \param d : first vertex * \param e : second vertex * Darts d and e should belong to the same face and be distinct from each other. @@ -280,16 +283,17 @@ class CMap2_T : public CMap1_T public: /** - * \brief Cut an enbedded face by inserting an edge between the vertices d and e + * \brief Cut a face by inserting an edge between the vertices d and e * \param d : first vertex * \param e : second vertex * The vertices d and e should belong to the same face and be distinct from each other. - * An edge made of two new darts is inserted between the two given vertices. + * An edge is inserted between the two given vertices. * If the map has Dart, Vertex, Edge, Face or Volume attributes, - * the inserted darts are automatically embedded on new attribute elements. - * Actually an Edge attribute is created, if needed, for the inserted edge - * and a new Face attribute is created for the subdived face that e belongs to. - * The Face attribute of the subdived face that d belongs to is kept unchanged. + * the inserted cells are automatically embedded on new attribute elements. + * More precisely : + * - an Edge attribute is created, if needed, for the inserted edge. + * - a Face attribute is created, if needed, for the subdivided face that e belongs to. + * - the Face attribute of the subdivided face that d belongs to is kept unchanged. */ inline void cut_face(Vertex d, Vertex e) { @@ -299,39 +303,38 @@ class CMap2_T : public CMap1_T Dart nd = this->phi_1(d); Dart ne = this->phi_1(e); - if (this->template is_embedded()) { + if (this->template is_embedded()) + { this->new_orbit_embedding(CDart(nd)); this->new_orbit_embedding(CDart(ne)); } if (this->template is_embedded()) { - this->template copy_embedding(nd, e.dart); - this->template copy_embedding(ne, d.dart); + this->template copy_embedding(nd, e.dart); + this->template copy_embedding(ne, d.dart); } if (this->template is_embedded()) - { this->new_orbit_embedding(Edge(nd)); - } if (this->template is_embedded()) { - this->template copy_embedding(nd, d.dart); + this->template copy_embedding(nd, d.dart); this->new_orbit_embedding(Face(ne)); } if (this->template is_embedded()) { - this->template copy_embedding(nd, d.dart); - this->template copy_embedding(ne, d.dart); + this->template copy_embedding(nd, d.dart); + this->template copy_embedding(ne, d.dart); } } protected: /*! - * \brief Add an embedded face in the map. + * \brief Add a face in the map. * \param size : the number of darts in the built face * \return A dart of the built face. */ @@ -356,10 +359,11 @@ class CMap2_T : public CMap1_T /*! * \brief Add a face in the map. * \param size : the number of edges in the built face - * \return A dart of the built face + * \return The built face * If the map has Dart, Vertex, Edge, Face or Volume attributes, - * the inserted darts are automatically embedded on new attribute elements. - * Actually a Face attribute is created, if needed, for the new face. + * the inserted cells are automatically embedded on new attribute elements. + * More precisely : + * - a Face attribute is created, if needed, for the new face. */ Face add_face(unsigned int size) { @@ -368,26 +372,35 @@ class CMap2_T : public CMap1_T const Face f = add_face_topo(size); if (this->template is_embedded()) + { foreach_dart_of_orbit(f, [this] (Dart d) { this->new_orbit_embedding(CDart(d)); this->new_orbit_embedding(CDart(phi2(d))); }); + } if (this->template is_embedded()) - foreach_dart_of_orbit(f, [this] (Dart v) + { + foreach_dart_of_orbit(f, [this] (Dart d) { - this->new_orbit_embedding(Vertex(v)); + this->new_orbit_embedding(Vertex(d)); }); + } if (this->template is_embedded()) - foreach_dart_of_orbit(f, [this] (Dart e) + { + foreach_dart_of_orbit(f, [this] (Dart d) { - this->new_orbit_embedding(Edge(e)); + this->new_orbit_embedding(Edge(d)); }); + } if (this->template is_embedded()) + { this->new_orbit_embedding(f); + this->new_orbit_embedding(Face(phi2(f.dart))); + } if (this->template is_embedded()) this->new_orbit_embedding(Volume(f.dart)); @@ -440,34 +453,38 @@ class CMap2_T : public CMap1_T const Face new_face = phi2(d); if (this->template is_embedded()) - foreach_dart_of_orbit(new_face, [this] (Dart d) + { + foreach_dart_of_orbit(new_face, [this] (Dart it) { - this->new_orbit_embedding(CDart(d)); + this->new_orbit_embedding(CDart(it)); }); + } if (this->template is_embedded()) - foreach_dart_of_orbit(new_face, [this] (Dart v) + { + foreach_dart_of_orbit(new_face, [this] (Dart it) { - this->template copy_embedding(v, this->phi1(phi2(v))); + this->template copy_embedding(it, this->phi1(phi2(it))); }); + } if (this->template is_embedded()) - foreach_dart_of_orbit(new_face, [this] (Dart e) + { + foreach_dart_of_orbit(new_face, [this] (Dart it) { - this->template copy_embedding(e, phi2(e)); + this->template copy_embedding(it, phi2(it)); }); + } if (this->template is_embedded()) - { this->new_orbit_embedding(new_face); - } if (this->template is_embedded()) { const unsigned int idx = this->get_embedding(Volume(d)); - foreach_dart_of_orbit(new_face, [this, idx] (Dart v) + foreach_dart_of_orbit(new_face, [this, idx] (Dart it) { - this->template set_embedding(v, idx); + this->template set_embedding(it, idx); }); } } @@ -542,8 +559,7 @@ class CMap2_T : public CMap1_T template inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const { - static_assert(check_func_parameter_type(FUNC, Dart), - "Wrong function parameter type"); + static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || ORBIT == Orbit::PHI2 || ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21, "Orbit not supported in a CMap2"); @@ -619,10 +635,8 @@ class CMap2_T : public CMap1_T template inline void foreach_dart_of_orbit_until(Cell c, const FUNC& f) const { - static_assert(check_func_parameter_type(FUNC, Dart), - "Wrong function parameter type"); - static_assert(check_func_return_type(FUNC, bool), - "Wrong function return type"); + static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); + static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || ORBIT == Orbit::PHI2 || ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21, diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index b91936a8..97c253b6 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -248,11 +248,10 @@ class MapBaseData : public MapGen return embeddings_[ORBIT] != nullptr; } - template + template inline bool is_embedded() const { - static_assert(Cell::ORBIT < NB_ORBITS, "Unknown orbit parameter"); - return embeddings_[Cell::ORBIT] != nullptr; + return is_embedded(); } template @@ -284,12 +283,25 @@ class MapBaseData : public MapGen (*embeddings_[ORBIT])[d.index] = emb; // affect the embedding to the dart } + template + inline void set_embedding(Dart d, unsigned int emb) + { + set_embedding(d, emb); + } + template inline void copy_embedding(Dart dest, Dart src) { + static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); this->template set_embedding(dest, get_embedding(Cell(src))); } + template + inline void copy_embedding(Dart dest, Dart src) + { + copy_embedding(dest, src); + } + /******************************************************************************* * Thread management *******************************************************************************/ From b13d3d78e530ba3e52d957e9077050fc2cbc53c9 Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Wed, 24 Feb 2016 17:13:17 +0100 Subject: [PATCH 165/402] add Self in Cell class & remove old comments --- cgogn/core/basic/cell.h | 11 +++++++---- cgogn/core/basic/cell_marker.h | 20 ++------------------ 2 files changed, 9 insertions(+), 22 deletions(-) diff --git a/cgogn/core/basic/cell.h b/cgogn/core/basic/cell.h index 79969063..8c2883df 100644 --- a/cgogn/core/basic/cell.h +++ b/cgogn/core/basic/cell.h @@ -82,7 +82,10 @@ template class Cell { public: + static const Orbit ORBIT = ORBIT_VAL; + using Self = Cell; + /** * \brief the dart representing this cell */ @@ -106,7 +109,7 @@ class Cell * Creates a new Cell from an another one. * \param[in] c a cell */ - inline Cell(const Cell& c) : dart(c.dart) + inline Cell(const Self& c) : dart(c.dart) {} //TODO @@ -131,21 +134,21 @@ class Cell * \param[in] rhs the cell to assign * \return The cell with the assigned value */ - Cell operator=(Cell rhs) { dart = rhs.dart; return *this; } + Self operator=(Self rhs) { dart = rhs.dart; return *this; } /** * \brief Prints a cell to a stream. * \param[out] out the stream to print on * \param[in] rhs the cell to print */ - friend std::ostream& operator<<(std::ostream &out, const Cell& rhs) { return out << rhs.dart; } + friend std::ostream& operator<<(std::ostream &out, const Self& rhs) { return out << rhs.dart; } /** * \brief Reads a cell from a stream. * \param[in] in the stream to read from * \param[out] rhs the cell read */ - friend std::istream& operator>>(std::istream &in, Cell& rhs) { in >> rhs.dart; return in; } + friend std::istream& operator>>(std::istream &in, Self& rhs) { in >> rhs.dart; return in; } /** * \brief Name of this CGoGN type diff --git a/cgogn/core/basic/cell_marker.h b/cgogn/core/basic/cell_marker.h index 095afe9c..df77d972 100644 --- a/cgogn/core/basic/cell_marker.h +++ b/cgogn/core/basic/cell_marker.h @@ -31,27 +31,13 @@ namespace cgogn { -//class CGOGN_CORE_API CellMarkerGen -//{ -//public: -// using Self = CellMarkerGen; -// CellMarkerGen() -// {} - -// virtual ~CellMarkerGen(); - -// CellMarkerGen(const Self& dm) = delete; -// CellMarkerGen(Self&& dm) = delete; -// CellMarkerGen& operator=(Self&& dm) = delete; -// CellMarkerGen& operator=(const Self& dm) = delete; -//}; - template -class CellMarker_T // : public CellMarkerGen +class CellMarker_T { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); public: + static const unsigned int CHUNKSIZE = MAP::CHUNKSIZE; using Self = CellMarker_T; using Map = MAP; @@ -65,14 +51,12 @@ class CellMarker_T // : public CellMarkerGen public: CellMarker_T(Map& map) : -// Inherit(), map_(map) { mark_attribute_ = map_.template get_mark_attribute(); } CellMarker_T(const MAP& map) : -// Inherit(), map_(const_cast(map)) { mark_attribute_ = map_.template get_mark_attribute(); From 1dc4f28b1233275d6218e131a96e419126b21d6a Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Wed, 24 Feb 2016 17:29:01 +0100 Subject: [PATCH 166/402] update CMap3 code --- cgogn/core/cmap/cmap2.h | 30 +++++++------- cgogn/core/cmap/cmap3.h | 91 ++++++++++++++++++++--------------------- 2 files changed, 60 insertions(+), 61 deletions(-) diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index e5aaee35..4f2fb482 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -54,7 +54,7 @@ class CMap2_T : public CMap1_T using CDart = Cell; using Vertex = Cell; using Edge = Cell; - using Face = Cell; + using Face = typename Inherit::Face; using Volume = Cell; template @@ -666,42 +666,42 @@ class CMap2_T : public CMap1_T inline void foreach_incident_edge(Vertex v, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); - foreach_dart_of_orbit(v, [&func](Dart e) {func(Edge(e));}); + foreach_dart_of_orbit(v, [&func] (Dart d) { func(Edge(d)); }); } template inline void foreach_incident_face(Vertex v, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); - foreach_dart_of_orbit(v, [&func](Dart f) {func(Face(f));}); + foreach_dart_of_orbit(v, [&func] (Dart d) { func(Face(d)); }); } template inline void foreach_incident_vertex(Edge e, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); - foreach_dart_of_orbit(e, [&func](Dart v) {func(Vertex(v));}); + foreach_dart_of_orbit(e, [&func] (Dart d) { func(Vertex(d)); }); } template inline void foreach_incident_face(Edge e, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); - foreach_dart_of_orbit(e, [&func](Dart f) {func(Face(f));}); + foreach_dart_of_orbit(e, [&func] (Dart d) { func(Face(d)); }); } template inline void foreach_incident_vertex(Face f, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); - foreach_dart_of_orbit(f, [&func](Dart v) {func(Vertex(v));}); + foreach_dart_of_orbit(f, [&func] (Dart d) { func(Vertex(d)); }); } template inline void foreach_incident_edge(Face f, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); - foreach_dart_of_orbit(f, [&func](Dart e) {func(Edge(e));}); + foreach_dart_of_orbit(f, [&func] (Dart d) { func(Edge(d)); }); } template @@ -709,12 +709,12 @@ class CMap2_T : public CMap1_T { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); DartMarkerStore marker(*this); - foreach_dart_of_orbit(w, [&] (Dart v) + foreach_dart_of_orbit(w, [&] (Dart d) { - if (!marker.is_marked(v)) + if (!marker.is_marked(d)) { - marker.mark_orbit(Vertex(v)); - f(Vertex(v)); + marker.mark_orbit(Vertex(d)); + f(Vertex(d)); } }); } @@ -724,12 +724,12 @@ class CMap2_T : public CMap1_T { static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); DartMarkerStore marker(*this); - foreach_dart_of_orbit(w, [&] (Dart e) + foreach_dart_of_orbit(w, [&] (Dart d) { - if (!marker.is_marked(e)) + if (!marker.is_marked(d)) { - marker.mark_orbit(Edge(e)); - f(Edge(e)); + marker.mark_orbit(Edge(d)); + f(Edge(d)); } }); } diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index a1756541..59a894e8 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -51,19 +51,19 @@ class CMap3_T : public CMap2_T friend class DartMarker_T; friend class cgogn::DartMarkerStore; - using CDart = Cell; - using Vertex = Cell; - using Edge = Cell; - using Face = Cell; - using Volume = Cell; - using Vertex2 = typename Inherit::Vertex; - using Edge2 = typename Inherit::Edge; - using Face2 = typename Inherit::Face; + using CDart = typename Inherit::CDart; + using Vertex = Cell; + using Edge = Cell; + using Face = Cell; + using Volume = typename Inherit::Volume; + using Vertex2 = typename Inherit::Vertex; + using Edge2 = typename Inherit::Edge; + using Face2 = typename Inherit::Face; template - using ChunkArray = typename Inherit::template ChunkArray; + using ChunkArray = typename Inherit::template ChunkArray; template - using ChunkArrayContainer = typename Inherit::template ChunkArrayContainer; + using ChunkArrayContainer = typename Inherit::template ChunkArrayContainer; template using AttributeHandler = typename Inherit::template AttributeHandler; @@ -183,11 +183,9 @@ class CMap3_T : public CMap2_T std::vector m_tableVertDarts; m_tableVertDarts.reserve(n); - // creation of triangles around circunference and storing vertices + // creation of triangles around circumference and storing vertices for (unsigned int i = 0u; i < n; ++i) - { m_tableVertDarts.push_back(this->Inherit::Inherit::add_face_topo(3u)); - } // sewing the triangles for (unsigned int i = 0u; i < n-1u; ++i) @@ -197,10 +195,10 @@ class CMap3_T : public CMap2_T this->phi2_sew(d,e); } - //sewing the last with the first - this->phi2_sew(this->phi1(m_tableVertDarts[0ul]), this->phi_1(m_tableVertDarts[n-1u])); + // sewing the last with the first + this->phi2_sew(this->phi1(m_tableVertDarts[0u]), this->phi_1(m_tableVertDarts[n-1u])); - //sewing the bottom face + // sewing the bottom face Dart base = this->Inherit::Inherit::add_face_topo(n); const Dart dres = base; for(unsigned int i = 0u; i < n; ++i) @@ -208,7 +206,8 @@ class CMap3_T : public CMap2_T this->phi2_sew(m_tableVertDarts[i], base); base = this->phi1(base); } - //return a dart from the base + + // return a dart from the base return dres; } @@ -225,15 +224,11 @@ class CMap3_T : public CMap2_T // creation of quads around circunference and storing vertices for (unsigned int i = 0u; i < n; ++i) - { - m_tableVertDarts.emplace_back(this->Inherit::Inherit::add_face_topo(4)); - } + m_tableVertDarts.emplace_back(this->Inherit::Inherit::add_face_topo(4u)); // storing a dart from the vertex pointed by phi1(phi1(d)) for (unsigned int i = 0u; i < n; ++i) - { m_tableVertDarts.emplace_back(this->phi1(this->phi1(m_tableVertDarts[i]))); - } // sewing the quads for (unsigned int i = 0u; i < n-1u; ++i) @@ -242,10 +237,10 @@ class CMap3_T : public CMap2_T const Dart e = this->phi1(m_tableVertDarts[i+1u]); this->phi2_sew(d,e); } - //sewing the last with the first - this->phi2_sew(this->phi1(m_tableVertDarts[0]), this->phi_1(m_tableVertDarts[n-1u])); + // sewing the last with the first + this->phi2_sew(this->phi1(m_tableVertDarts[0u]), this->phi_1(m_tableVertDarts[n-1u])); - //sewing the top & bottom faces + // sewing the top & bottom faces Dart top = this->Inherit::Inherit::add_face_topo(n); Dart bottom = this->Inherit::Inherit::add_face_topo(n); const Dart dres = top; @@ -257,13 +252,14 @@ class CMap3_T : public CMap2_T bottom = this->phi_1(bottom); } - //return a dart from the base + // return a dart from the base return dres; } inline void close_hole_topo(Dart d) { cgogn_message_assert(phi3(d) == d, "CMap3: close hole called on a dart that is not a phi3 fix point"); + DartMarkerStore dmarker(*this); DartMarkerStore boundary_marker(*this); @@ -295,19 +291,21 @@ class CMap3_T : public CMap2_T if (phi3(e) == e) { found = true; - if(!dmarker.is_marked(e)) + if (!dmarker.is_marked(e)) { visitedFaces.push_back(e); dmarker.mark_orbit(Face2(e)); } - } else { - if(boundary_marker.is_marked(e)) + } + else + { + if (boundary_marker.is_marked(e)) { found = true; this->phi2_sew(e, bit); - } else { - e = this->phi3(this->phi2(e)); } + else + e = this->phi3(this->phi2(e)); } } while(!found); @@ -337,22 +335,28 @@ class CMap3_T : public CMap2_T const Volume new_volume = phi3(d); if (this->template is_embedded()) + { foreach_dart_of_orbit(new_volume, [this] (Dart d) { this->new_orbit_embedding(CDart(d)); }); + } if (this->template is_embedded()) + { Inherit::foreach_incident_vertex(new_volume, [this] (Vertex2 v) { this->new_orbit_embedding(v); }); + } if (this->template is_embedded()) + { Inherit::foreach_incident_edge(new_volume, [this] (Edge2 e) { this->new_orbit_embedding(e); }); + } if (this->template is_embedded()) { @@ -366,7 +370,7 @@ class CMap3_T : public CMap2_T { foreach_dart_of_orbit(new_volume, [this] (Dart wd) { - this->template copy_embedding(wd, this->phi1(phi3(wd))); + this->template copy_embedding(wd, this->phi1(phi3(wd))); }); } @@ -374,7 +378,7 @@ class CMap3_T : public CMap2_T { foreach_dart_of_orbit(new_volume, [this] (Dart wd) { - this->template copy_embedding(wd, phi3(wd)); + this->template copy_embedding(wd, phi3(wd)); }); } @@ -382,10 +386,10 @@ class CMap3_T : public CMap2_T { foreach_dart_of_orbit(new_volume, [this] (Dart wd) { - this->template copy_embedding(wd, phi3(wd)); + this->template copy_embedding(wd, phi3(wd)); }); - } + if (this->template is_embedded()) { this->new_orbit_embedding(new_volume); @@ -399,7 +403,7 @@ class CMap3_T : public CMap2_T inline unsigned int degree(Face f) const { - return Inherit::degree(typename Inherit::Face(f.dart)); + return Inherit::degree(Face2(f.dart)); } protected: @@ -466,9 +470,7 @@ class CMap3_T : public CMap2_T template inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const { - static_assert(check_func_parameter_type(FUNC, Dart), - "Wrong function parameter type"); - + static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || ORBIT == Orbit::PHI2 || ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21 || ORBIT == Orbit::PHI1_PHI3 || ORBIT == Orbit::PHI2_PHI3 || ORBIT == Orbit::PHI21_PHI31, @@ -551,11 +553,8 @@ class CMap3_T : public CMap2_T template inline void foreach_dart_of_orbit_until(Cell c, const FUNC& f) const { - static_assert(check_func_parameter_type(FUNC, Dart), - "Wrong function parameter type"); - static_assert(check_func_return_type(FUNC, bool), - "Wrong function return type"); - + static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); + static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || ORBIT == Orbit::PHI2 || ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21 || ORBIT == Orbit::PHI1_PHI3 || ORBIT == Orbit::PHI2_PHI3 || ORBIT == Orbit::PHI21_PHI31, @@ -653,14 +652,14 @@ class CMap3_T : public CMap2_T inline void foreach_incident_vertex(Face f, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); - foreach_dart_of_orbit(Face2(f.dart), [&func](Dart v) {func(Vertex(v));}); + foreach_dart_of_orbit(Face2(f.dart), [&func] (Dart v) { func(Vertex(v)); }); } template inline void foreach_incident_edge(Face f, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); - foreach_dart_of_orbit(Face2(f.dart), [&func](Dart e) {func(Edge(e));}); + foreach_dart_of_orbit(Face2(f.dart), [&func] (Dart e) { func(Edge(e)); }); } template From a45910d4e4fc1be9c3362eaede488a1c7cc94a3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 24 Feb 2016 18:13:57 +0100 Subject: [PATCH 167/402] using endian.h for import and export. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/map_export.h | 42 +++++++++------------------------------ cgogn/io/surface_import.h | 20 +++++++------------ 2 files changed, 16 insertions(+), 46 deletions(-) diff --git a/cgogn/io/map_export.h b/cgogn/io/map_export.h index 064afd44..cdfc33ec 100644 --- a/cgogn/io/map_export.h +++ b/cgogn/io/map_export.h @@ -30,12 +30,10 @@ #include #include +#include #include #include - - - namespace cgogn { @@ -123,14 +121,6 @@ bool export_off(MAP& map, const typename MAP::template VertexAttributeHandler bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandler& position, const std::string& filename) { - - // local function for little/big endian conversion - auto changeEndianness = [](unsigned int x) -> unsigned int - { - return (x>>24) | ((x<<8) & 0x00FF0000) | ((x>>8) & 0x0000FF00) | (x<<24); - }; - - std::ofstream fp(filename.c_str(), std::ios::out|std::ofstream::binary); if (!fp.good()) { @@ -141,8 +131,8 @@ bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandle fp << "OFF BINARY"<< std::endl; unsigned int nb_cells[3]; - nb_cells[0] = changeEndianness(map.template nb_cells()); - nb_cells[1] = changeEndianness(map.template nb_cells()); + nb_cells[0] = swap_endianness_system_big(map.template nb_cells()); + nb_cells[1] = swap_endianness_system_big(map.template nb_cells()); nb_cells[2] = 0; fp.write(reinterpret_cast(nb_cells),3*sizeof(unsigned int)); @@ -172,9 +162,9 @@ bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandle // VEC3 can be double ! float Pf[3]={float(P[0]),float(P[1]),float(P[2])}; unsigned int* ui_vec = reinterpret_cast(Pf); - ui_vec[0] = changeEndianness(ui_vec[0]); - ui_vec[1] = changeEndianness(ui_vec[1]); - ui_vec[2] = changeEndianness(ui_vec[2]); + ui_vec[0] = swap_endianness_system_big(ui_vec[0]); + ui_vec[1] = swap_endianness_system_big(ui_vec[1]); + ui_vec[2] = swap_endianness_system_big(ui_vec[2]); buffer_pos.push_back(Pf[0]); buffer_pos.push_back(Pf[1]); @@ -212,9 +202,9 @@ bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandle ++valence; }); - buffer_prims.push_back(changeEndianness(valence)); + buffer_prims.push_back(swap_endianness_system_big(valence)); for(unsigned int i: prim) - buffer_prims.push_back(changeEndianness(i)); + buffer_prims.push_back(swap_endianness_system_big(i)); if (buffer_prims.size() >= BUFFER_SZ) { @@ -614,14 +604,6 @@ bool export_ply(MAP& map, const typename MAP::template VertexAttributeHandler bool export_ply_bin(MAP& map, const typename MAP::template VertexAttributeHandler& position, const std::string& filename) { - - // local function for little/big endian conversion - auto changeEndianness = [](unsigned int x) -> unsigned int - { - return (x>>24) | ((x<<8) & 0x00FF0000) | ((x>>8) & 0x0000FF00) | (x<<24); - }; - - std::ofstream fp(filename.c_str(), std::ios::out|std::ofstream::binary); if (!fp.good()) { @@ -630,12 +612,7 @@ bool export_ply_bin(MAP& map, const typename MAP::template VertexAttributeHandle } fp << "ply" << std::endl ; - union - { - uint32_t i ; - char c[4] ; - } bint = {0x01020304} ; - if (bint.c[0] == 1) // big endian + if (internal::cgogn_is_big_endian) fp << "format binary_big_endian 1.0" << std::endl ; else fp << "format binary_little_endian 1.0" << std::endl ; @@ -723,7 +700,6 @@ bool export_ply_bin(MAP& map, const typename MAP::template VertexAttributeHandle } map.remove_attribute(ids); - fp.close(); return true; } diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index 10a56867..aeaeb4e8 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -26,6 +26,7 @@ #include +#include #include #include #include @@ -361,19 +362,12 @@ class SurfaceImport template bool import_OFF_BIN(std::ifstream& fp) { - - // local function for little/big endian conversion - auto changeEndianness = [](unsigned int x) -> unsigned int - { - return (x>>24) | ((x<<8) & 0x00FF0000) | ((x>>8) & 0x0000FF00) | (x<<24); - }; - char buffer1[12]; fp.read(buffer1,12); - nb_vertices_= changeEndianness(*(reinterpret_cast(buffer1))); - nb_faces_= changeEndianness(*(reinterpret_cast(buffer1+4))); - nb_edges_= changeEndianness(*(reinterpret_cast(buffer1+8))); + nb_vertices_= swap_endianness_system_big(*(reinterpret_cast(buffer1))); + nb_faces_= swap_endianness_system_big(*(reinterpret_cast(buffer1+4))); + nb_edges_= swap_endianness_system_big(*(reinterpret_cast(buffer1+8))); ChunkArray* position = vertex_attributes_.template add_attribute("position"); @@ -400,7 +394,7 @@ class SurfaceImport unsigned int* ptr = reinterpret_cast(buff_pos); for (unsigned int i=0; i< 3*BUFFER_SZ;++i) { - *ptr = changeEndianness(*ptr); + *ptr = swap_endianness_system_big(*ptr); ++ptr; } } @@ -431,7 +425,7 @@ class SurfaceImport ptr = buff_ind; for (unsigned int i=0; i< BUFFER_SZ;++i) { - *ptr = changeEndianness(*ptr); + *ptr = swap_endianness_system_big(*ptr); ++ptr; } ptr = buff_ind; @@ -450,7 +444,7 @@ class SurfaceImport ptr = buff_ind; for (unsigned int i=0; i< BUFFER_SZ;++i) { - *ptr = changeEndianness(*ptr); + *ptr = swap_endianness_system_big(*ptr); ++ptr; } ptr = buff_ind; From 945aec542dd87491f46f8aa748709812794c6975 Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Wed, 24 Feb 2016 22:22:59 +0100 Subject: [PATCH 168/402] missing "this->" --- cgogn/core/CMakeLists.txt | 6 +++--- cgogn/core/cmap/map_base.h | 2 +- cgogn/geometry/CMakeLists.txt | 12 ++++++------ cgogn/io/CMakeLists.txt | 14 +++++++------- cgogn/rendering/CMakeLists.txt | 2 -- 5 files changed, 17 insertions(+), 19 deletions(-) diff --git a/cgogn/core/CMakeLists.txt b/cgogn/core/CMakeLists.txt index 43382fec..5159aec7 100644 --- a/cgogn/core/CMakeLists.txt +++ b/cgogn/core/CMakeLists.txt @@ -45,9 +45,9 @@ set(SOURCE_FILES basic/dart_marker.cpp cmap/map_base_data.cpp - cmap/cmap0.cpp - cmap/cmap1.cpp - cmap/cmap2.cpp + cmap/cmap0.cpp + cmap/cmap1.cpp + cmap/cmap2.cpp cmap/cmap3.cpp cmap/cmap2_builder.cpp cmap/cmap3_builder.cpp diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 40884e89..6173bbba 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -468,7 +468,7 @@ class MapBase : public MapBaseData bool same_cell(Cell c1, Cell c2) const { if (this->template is_embedded()) - return get_embedding(c1) == get_embedding(c2); + return this->get_embedding(c1) == this->get_embedding(c2); bool result = false; to_concrete()->foreach_dart_of_orbit_until(c1, [&] (Dart d) -> bool diff --git a/cgogn/geometry/CMakeLists.txt b/cgogn/geometry/CMakeLists.txt index 3631febf..e07faf45 100644 --- a/cgogn/geometry/CMakeLists.txt +++ b/cgogn/geometry/CMakeLists.txt @@ -1,6 +1,6 @@ project(cgogn_geometry LANGUAGES CXX - ) +) set(HEADER_FILES dll.h @@ -18,13 +18,13 @@ set(HEADER_FILES types/geometry_traits.h types/plane_3d.h types/vec.h - ) +) set(SOURCE_FILES types/plane_3d.cpp types/vec.cpp types/bounding_box.cpp - ) +) add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) @@ -34,21 +34,21 @@ target_include_directories(${PROJECT_NAME} PUBLIC $ $ $ - ) +) target_link_libraries(${PROJECT_NAME} cgogn_core) install(DIRECTORY . DESTINATION include/cgogn/geometry FILES_MATCHING PATTERN "*.h" - ) +) install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}Targets RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib - ) +) if(CGOGN_BUILD_TESTS) add_subdirectory(tests) diff --git a/cgogn/io/CMakeLists.txt b/cgogn/io/CMakeLists.txt index 0a066d3e..1a84def6 100644 --- a/cgogn/io/CMakeLists.txt +++ b/cgogn/io/CMakeLists.txt @@ -1,6 +1,6 @@ project(cgogn_io LANGUAGES CXX C - ) +) set(HEADER_FILES surface_import.h @@ -10,14 +10,14 @@ set(HEADER_FILES ply.h import_ply_data.h dll.h - ) +) set(SOURCE_FILES surface_import.cpp volume_import.cpp ply.c import_ply_data.cpp - ) +) add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) @@ -28,20 +28,20 @@ target_include_directories(${PROJECT_NAME} PUBLIC $ $ $ - ) +) target_link_libraries(${PROJECT_NAME} tinyxml2 cgogn_core cgogn_geometry) install(DIRECTORY . - DESTINATION include/cgogn/cgogn_core + DESTINATION include/cgogn/io FILES_MATCHING PATTERN "*.h" - ) +) install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}Targets RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib - ) +) add_subdirectory(examples) diff --git a/cgogn/rendering/CMakeLists.txt b/cgogn/rendering/CMakeLists.txt index f186f3cb..9d60f94c 100644 --- a/cgogn/rendering/CMakeLists.txt +++ b/cgogn/rendering/CMakeLists.txt @@ -5,7 +5,6 @@ project(cgogn_rendering find_package(Qt5Widgets) #find_package(Qt5OpenGL) - set(HEADER_FILES dll.h map_render.h @@ -23,7 +22,6 @@ set(SOURCE_FILES shaders/shader_color_per_vertex.cpp shaders/shader_flat.cpp shaders/shader_vector_per_vertex.cpp - ) add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) From 087e4bd5c31af52bd40d47e5b498ef736d470b9b Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Wed, 24 Feb 2016 23:24:22 +0100 Subject: [PATCH 169/402] Moved ply from io/ to thirdparty/ Signed-off-by: Etienne Schmitt --- cgogn/io/CMakeLists.txt | 7 +++---- cgogn/io/import_ply_data.h | 2 +- thirdparty/CMakeLists.txt | 1 + thirdparty/ply/CMakeLists.txt | 16 ++++++++++++++++ {cgogn/io => thirdparty/ply}/ply.c | 0 {cgogn/io => thirdparty/ply}/ply.h | 0 6 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 thirdparty/ply/CMakeLists.txt rename {cgogn/io => thirdparty/ply}/ply.c (100%) rename {cgogn/io => thirdparty/ply}/ply.h (100%) diff --git a/cgogn/io/CMakeLists.txt b/cgogn/io/CMakeLists.txt index 0a066d3e..f4652459 100644 --- a/cgogn/io/CMakeLists.txt +++ b/cgogn/io/CMakeLists.txt @@ -1,5 +1,5 @@ project(cgogn_io - LANGUAGES CXX C + LANGUAGES CXX ) set(HEADER_FILES @@ -7,7 +7,6 @@ set(HEADER_FILES volume_import.h map_import.h map_export.h - ply.h import_ply_data.h dll.h ) @@ -15,7 +14,6 @@ set(HEADER_FILES set(SOURCE_FILES surface_import.cpp volume_import.cpp - ply.c import_ply_data.cpp ) @@ -27,10 +25,11 @@ target_include_directories(${PROJECT_NAME} PUBLIC $ $ $ + $ $ ) -target_link_libraries(${PROJECT_NAME} tinyxml2 cgogn_core cgogn_geometry) +target_link_libraries(${PROJECT_NAME} tinyxml2 cgogn_core cgogn_geometry ply) install(DIRECTORY . DESTINATION include/cgogn/cgogn_core diff --git a/cgogn/io/import_ply_data.h b/cgogn/io/import_ply_data.h index df52ddb4..70d99e8b 100644 --- a/cgogn/io/import_ply_data.h +++ b/cgogn/io/import_ply_data.h @@ -29,7 +29,7 @@ #include #include -#include +#include #include namespace cgogn diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index ad249fa1..55c6adac 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -18,4 +18,5 @@ if (CGOGN_BUILD_BENCHS) add_subdirectory(google-benchmark) endif(CGOGN_BUILD_BENCHS) +add_subdirectory(ply) add_subdirectory(OffBinConverter) diff --git a/thirdparty/ply/CMakeLists.txt b/thirdparty/ply/CMakeLists.txt new file mode 100644 index 00000000..fdf73bb3 --- /dev/null +++ b/thirdparty/ply/CMakeLists.txt @@ -0,0 +1,16 @@ +set(PLY_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE PATH "Ply include directory") + +project(ply + LANGUAGES C + ) + +set(HEADER_FILES + ply.h + ) + +set(SOURCE_FILES + ply.c + ) + +add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) +set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "_d") \ No newline at end of file diff --git a/cgogn/io/ply.c b/thirdparty/ply/ply.c similarity index 100% rename from cgogn/io/ply.c rename to thirdparty/ply/ply.c diff --git a/cgogn/io/ply.h b/thirdparty/ply/ply.h similarity index 100% rename from cgogn/io/ply.h rename to thirdparty/ply/ply.h From b5ece6725a99b3af620eb7b27d94f92349ae5492 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Thu, 25 Feb 2016 00:50:46 +0100 Subject: [PATCH 170/402] Unity tests on CMap1 --- cgogn/core/cmap/cmap3.h | 4 +- cgogn/core/container/chunk_array.h | 2 +- .../chunk_array/bench_chunk_array.cpp | 2 +- cgogn/core/tests/cmap/cmap1_topo_test.cpp | 95 ++++++++++++++++++- cgogn/geometry/tests/algos/algos_test.cpp | 3 +- cgogn/io/examples/cmap2_import.cpp | 4 +- cgogn/io/examples/cmap3_import.cpp | 4 +- cgogn/multiresolution/cph/cph3.h | 4 +- cgogn/rendering/examples/simple_viewer.cpp | 4 +- 9 files changed, 104 insertions(+), 18 deletions(-) diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 7671ba81..c1ff4cf6 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -25,14 +25,12 @@ #define CORE_CMAP_CMAP3_H_ #include -#include namespace cgogn { // forward declaration of CMap3Builder_T -template -class CMap3Builder_T; +template class CMap3Builder_T; template class CMap3_T : public CMap2_T diff --git a/cgogn/core/container/chunk_array.h b/cgogn/core/container/chunk_array.h index 43bb23c5..2e755708 100644 --- a/cgogn/core/container/chunk_array.h +++ b/cgogn/core/container/chunk_array.h @@ -103,7 +103,7 @@ class ChunkArray : public ChunkArrayGen */ void add_chunk() override { - table_data_.emplace_back(new T[CHUNKSIZE]()); + table_data_.push_back(new T[CHUNKSIZE]()); } /** diff --git a/cgogn/core/examples/chunk_array/bench_chunk_array.cpp b/cgogn/core/examples/chunk_array/bench_chunk_array.cpp index dd67f833..f6dba580 100644 --- a/cgogn/core/examples/chunk_array/bench_chunk_array.cpp +++ b/cgogn/core/examples/chunk_array/bench_chunk_array.cpp @@ -182,7 +182,7 @@ int test5() for(unsigned int i = container.begin(); i < container.end(); i += 9) container.remove_lines<1>(i); - unsigned int total = 0; + int total = 0; for (unsigned int j = 0; j < 50; ++j) { for(unsigned int i = container.begin(); i != container.end(); container.next(i)) diff --git a/cgogn/core/tests/cmap/cmap1_topo_test.cpp b/cgogn/core/tests/cmap/cmap1_topo_test.cpp index 1f2904bc..8953bf1a 100644 --- a/cgogn/core/tests/cmap/cmap1_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_topo_test.cpp @@ -21,6 +21,9 @@ * * *******************************************************************************/ +#include +#include + #include #include @@ -32,24 +35,108 @@ namespace cgogn class CMap1TopoTest: public CMap1, public ::testing::Test { + public: - using Face = CMap1TopoTest::Face; + + static const int NB_MAX = 1000; + + using Vertex = CMap1TopoTest::Vertex; + using Face = CMap1TopoTest::Face; protected: - CMap1TopoTest() - {} + /*! + * \brief Generate a random set of faces. + */ + CMap1TopoTest() : nb_darts_(0) + { + std::srand(static_cast(std::time(0))); + } + + bool dartIntegrity(Dart d) { + return (phi1(phi_1(d)) == d && phi_1(phi1(d)) == d); + } + + bool mapIntegrity() { + bool result = true; + foreach_dart( [&] (Dart d) { + if (!dartIntegrity(d)) { + result = false; + return ; + } + }); + return result; + } + + int randomDarts() { + int n = std::rand() % NB_MAX; + for (int i = 0; i < n; ++i) + tdarts_[i] = add_dart(); + + return n; + } + + int randomFaces() { + int count = 0; + for (int i = 0; i < NB_MAX; ++i) { + int n = std::rand() % 100; + Dart d = add_face_topo(n); + count += n; + + for (int k = std::rand() % n; k > 0; ++k) + d = phi1(d); + + tdarts_[i] = d; + } + return count; + } + + std::array tdarts_; + int nb_darts_; }; TEST_F(CMap1TopoTest, testAddDart) { - + int n = randomDarts(); + EXPECT_EQ(nb_darts(), n); + EXPECT_TRUE(mapIntegrity()); } TEST_F(CMap1TopoTest, testDeleteDart) { + int n = randomDarts(); + int count = n; + for (int i = 0; i < n; ++i) { + if (std::rand() % 3 == 1) { + remove_dart(tdarts_[i]); + --count; + } + } + EXPECT_EQ(nb_darts(), count); + EXPECT_TRUE(mapIntegrity()); +} +TEST_F(CMap1TopoTest, testPhi1SewUnSew) +{ + int n = randomDarts(); + for (int i = 0; i < 1000; ++i) { + Dart d = tdarts_[std::rand() % n]; + Dart e = tdarts_[std::rand() % n]; + Dart f = tdarts_[std::rand() % n]; + Dart nd = phi1(d); + Dart ne = phi1(e); + phi1_sew(d, e); + EXPECT_TRUE(phi1(d) == ne); + EXPECT_TRUE(phi1(e) == nd); + Dart nf1 = phi1(f); + Dart nf2 = phi1(nf1); + phi1_unsew(f); + EXPECT_TRUE(phi1(nf1) == nf1); + EXPECT_TRUE(phi1(f) == nf2); + } + EXPECT_EQ(nb_darts(), n); + EXPECT_TRUE(mapIntegrity()); } TEST_F(CMap1TopoTest, testFaceDegree) diff --git a/cgogn/geometry/tests/algos/algos_test.cpp b/cgogn/geometry/tests/algos/algos_test.cpp index 892af6af..00c124e6 100644 --- a/cgogn/geometry/tests/algos/algos_test.cpp +++ b/cgogn/geometry/tests/algos/algos_test.cpp @@ -37,7 +37,8 @@ #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) -using StdArray = cgogn::geometry::Vec_T>; +//using StdArray = cgogn::geometry::Vec_T>; +using StdArray = Eigen::Vector3d; using EigenVec3d = Eigen::Vector3d; using CMap2 = cgogn::CMap2; diff --git a/cgogn/io/examples/cmap2_import.cpp b/cgogn/io/examples/cmap2_import.cpp index 0dcbcff5..70b8eb27 100644 --- a/cgogn/io/examples/cmap2_import.cpp +++ b/cgogn/io/examples/cmap2_import.cpp @@ -18,8 +18,8 @@ struct MyMapTraits : public cgogn::DefaultMapTraits using Map2 = cgogn::CMap2; -//using Vec3 = Eigen::Vector3d; -using Vec3 = cgogn::geometry::Vec_T>; +using Vec3 = Eigen::Vector3d; +//using Vec3 = cgogn::geometry::Vec_T>; template using VertexAttributeHandler = Map2::VertexAttributeHandler; diff --git a/cgogn/io/examples/cmap3_import.cpp b/cgogn/io/examples/cmap3_import.cpp index 94e839f3..8c353d3d 100644 --- a/cgogn/io/examples/cmap3_import.cpp +++ b/cgogn/io/examples/cmap3_import.cpp @@ -11,8 +11,8 @@ using Map3 = cgogn::CMap3; -//using Vec3 = Eigen::Vector3d; -using Vec3 = cgogn::geometry::Vec_T>; +using Vec3 = Eigen::Vector3d; +//using Vec3 = cgogn::geometry::Vec_T>; template using VertexAttributeHandler = Map3::VertexAttributeHandler; diff --git a/cgogn/multiresolution/cph/cph3.h b/cgogn/multiresolution/cph/cph3.h index a5e53056..d4f5a425 100644 --- a/cgogn/multiresolution/cph/cph3.h +++ b/cgogn/multiresolution/cph/cph3.h @@ -73,12 +73,12 @@ class CPH3 : public CPH2 (*face_id_)[d.index] = i ; } - inline unsigned int get_tri_refinement_face_id(Dart d, Dart e) const + inline unsigned int get_tri_refinement_face_id(Dart /*d*/, Dart /*e*/) const { return 0u; } - inline unsigned int get_quad_refinement_face_id(Dart d) const + inline unsigned int get_quad_refinement_face_id(Dart /*d*/) const { return 0u; } diff --git a/cgogn/rendering/examples/simple_viewer.cpp b/cgogn/rendering/examples/simple_viewer.cpp index 54d0e1d1..e5c797d9 100644 --- a/cgogn/rendering/examples/simple_viewer.cpp +++ b/cgogn/rendering/examples/simple_viewer.cpp @@ -44,8 +44,8 @@ #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) using Map2 = cgogn::CMap2; -//using Vec3 = Eigen::Vector3d; -using Vec3 = cgogn::geometry::Vec_T>; +using Vec3 = Eigen::Vector3d; +//using Vec3 = cgogn::geometry::Vec_T>; template using VertexAttributeHandler = Map2::VertexAttributeHandler; From 8c58b046b4230b5e40ba9f802df419fa63dd31eb Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Thu, 25 Feb 2016 01:06:02 +0100 Subject: [PATCH 171/402] remove comment in CMakeLists --- cgogn/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cgogn/CMakeLists.txt b/cgogn/CMakeLists.txt index 190b1a7b..0e58899a 100644 --- a/cgogn/CMakeLists.txt +++ b/cgogn/CMakeLists.txt @@ -6,4 +6,4 @@ if(CGOGN_USE_QT) add_subdirectory(rendering) endif(CGOGN_USE_QT) -#add_subdirectory(multiresolution) +add_subdirectory(multiresolution) From 70a7e3b7de32736cec16d95d871c6e2bc181b313 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Thu, 25 Feb 2016 09:15:11 +0100 Subject: [PATCH 172/402] drawer & phong --- cgogn/geometry/types/vec.h | 5 + cgogn/rendering/CMakeLists.txt | 5 +- cgogn/rendering/drawer.cpp | 183 ++++++++++++ cgogn/rendering/drawer.h | 150 ++++++++++ cgogn/rendering/examples/simple_viewer.cpp | 158 +++++++++-- .../shaders/shader_color_per_vertex.cpp | 34 +-- cgogn/rendering/shaders/shader_phong.cpp | 267 ++++++++++++++++++ cgogn/rendering/shaders/shader_phong.h | 119 ++++++++ cgogn/rendering/shaders/vbo.h | 109 ++++++- 9 files changed, 981 insertions(+), 49 deletions(-) create mode 100644 cgogn/rendering/drawer.cpp create mode 100644 cgogn/rendering/drawer.h create mode 100644 cgogn/rendering/shaders/shader_phong.cpp create mode 100644 cgogn/rendering/shaders/shader_phong.h diff --git a/cgogn/geometry/types/vec.h b/cgogn/geometry/types/vec.h index 4a290bdc..9aadfacc 100644 --- a/cgogn/geometry/types/vec.h +++ b/cgogn/geometry/types/vec.h @@ -67,6 +67,11 @@ class Vec_T Vec_T(const Self&v) = default; Self& operator=(const Self& v) = default; + inline const Scalar* data() const + { + return data_.data(); + } + inline Scalar& operator[](std::size_t i) { return data_[i]; diff --git a/cgogn/rendering/CMakeLists.txt b/cgogn/rendering/CMakeLists.txt index f186f3cb..86697c9f 100644 --- a/cgogn/rendering/CMakeLists.txt +++ b/cgogn/rendering/CMakeLists.txt @@ -15,6 +15,8 @@ set(HEADER_FILES shaders/shader_color_per_vertex.h shaders/shader_flat.h shaders/shader_vector_per_vertex.h + shaders/shader_phong.h + drawer.h ) set(SOURCE_FILES @@ -23,7 +25,8 @@ set(SOURCE_FILES shaders/shader_color_per_vertex.cpp shaders/shader_flat.cpp shaders/shader_vector_per_vertex.cpp - + shaders/shader_phong.cpp + drawer.cpp ) add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) diff --git a/cgogn/rendering/drawer.cpp b/cgogn/rendering/drawer.cpp new file mode 100644 index 00000000..3a30ad6d --- /dev/null +++ b/cgogn/rendering/drawer.cpp @@ -0,0 +1,183 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#define CGOGN_RENDERING_DLL_EXPORT + +#include + +#include +#include + +namespace cgogn +{ + +namespace rendering +{ + +ShaderColorPerVertex* Drawer::shader_cpv_= NULL; + +Drawer::Drawer() : + current_size_(1.0f) +{ + vbo_pos_ = new VBO(3); + vbo_col_ = new VBO(3); + + if (shader_cpv_ == NULL) + shader_cpv_ = new ShaderColorPerVertex(); + + + vao_ = shader_cpv_->add_vao(); + shader_cpv_->set_vao(vao_,vbo_pos_,vbo_col_); + +} + +Drawer::~Drawer() +{ + +} + +void Drawer::new_list() +{ + data_pos_.clear(); + data_col_.clear(); + begins_.clear(); +} + +void Drawer::begin(GLenum mode) +{ + if (mode == GL_POINTS) + begins_.push_back(PrimParam(data_pos_.size(), mode, current_size_)); + else + begins_.push_back(PrimParam(data_pos_.size(), mode, 1.0)); +} + +void Drawer::end() +{ + begins_.back().nb = data_pos_.size() - begins_.back().begin; +} + + +void Drawer::vertex3f(float x, float y, float z) +{ + if (data_pos_.size() == data_col_.size()) + { + if (data_col_.empty()) + data_col_.push_back(Vec3f{1.0f, 1.0f, 1.0f}); + else + data_col_.push_back( data_col_.back()); + } + data_pos_.push_back(Vec3f{x,y,z}); +} + + +void Drawer::color3f(float r, float g, float b) +{ + if (data_pos_.size() == data_col_.size()) + data_col_.push_back(Vec3f{r,g,b}); + else + data_col_.back() = Vec3f{r,g,b}; +} + + +void Drawer::end_list() +{ + unsigned int nb_elts(data_pos_.size()); + + if (nb_elts == 0) + return; + + vbo_pos_->allocate(nb_elts,3); + float* ptr = vbo_pos_->lock_pointer(); + std::memcpy(ptr,data_pos_[0].data(),nb_elts*12); + vbo_pos_->release_pointer(); + + + vbo_col_->allocate(nb_elts,3); + ptr = vbo_col_->lock_pointer(); + std::memcpy(ptr,data_col_[0].data(),nb_elts*12); + vbo_col_->release_pointer(); + + + // free memory + data_pos_.clear(); + data_pos_.shrink_to_fit(); + data_col_.clear(); + data_col_.shrink_to_fit(); + + for (const auto& beg : begins_) + { + switch (beg.mode) + { + case GL_POINTS: + begins_point_.push_back(beg); + break; + case GL_LINES: + case GL_LINE_STRIP: + case GL_LINE_LOOP: + begins_line_.push_back(beg); + break; + default: + begins_face_.push_back(beg); + break; + } + } +} + +void Drawer::callList(const QMatrix4x4& projection, const QMatrix4x4& modelview) +{ + QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); + + if (begins_.empty()) + return; + + shader_cpv_->bind(); + shader_cpv_->set_matrices(projection,modelview); + shader_cpv_->bind_vao(vao_); + for (auto& pp : begins_point_) + { + glPointSize(pp.width); + ogl->glDrawArrays(pp.mode, pp.begin, pp.nb); + } + + for (auto& pp : begins_line_) + { + glLineWidth(3.0); + ogl->glDrawArrays(pp.mode, pp.begin, pp.nb); + } + + for (auto& pp : begins_face_) + { + ogl->glDrawArrays(pp.mode, pp.begin, pp.nb); + } + + shader_cpv_->release_vao(vao_); + shader_cpv_->release(); + +} + + + + +} // namespace rendering + +} // namespace cgogn diff --git a/cgogn/rendering/drawer.h b/cgogn/rendering/drawer.h new file mode 100644 index 00000000..afde7bd4 --- /dev/null +++ b/cgogn/rendering/drawer.h @@ -0,0 +1,150 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef RENDERING_DRAWER_H_ +#define RENDERING_DRAWER_H_ + +#include +#include +#include +#include + +//#include +namespace cgogn +{ + +namespace rendering +{ + + +class CGOGN_RENDERING_API Drawer +{ + struct PrimParam + { + unsigned int begin; + GLenum mode; + float width; + unsigned int nb; + PrimParam(unsigned int b, GLenum m, float w): begin(b),mode(m),width(w),nb(0) {} + }; + + using Vec3f = std::array; + +protected: + VBO* vbo_pos_; + VBO* vbo_col_; + unsigned int vao_; + + std::vector data_pos_; + std::vector data_col_; + std::vector begins_; + std::vector begins_point_; + std::vector begins_line_; + std::vector begins_face_; + + float current_size_; + static ShaderColorPerVertex* shader_cpv_; + +public: + + /** + * constructor, init all buffers (data and OpenGL) and shader + * @param lineMode 0:simple thin Line / 1:line with possible width /2:3D Lines + * @Warning need OpenGL context + */ + Drawer(); + + /** + * release buffers and shader + */ + ~Drawer(); + + + /** + * init the data structure + */ + void new_list(); + + /** + * as glBegin, but need a newList call before + * @param mode: GL_POINTS, GL_LINES, GL_LINE_LOOP, GL_TRIANGLES, + */ + void begin(GLenum mode); + + /** + * as glEnd + */ + void end(); + + /** + * finalize the data initialization + * drawn is done if newList called with GL_COMPILE_AND_EXECUTE + */ + void end_list(); + + /** + * use as glVertex3f + */ + void vertex3f(float x, float y, float z); + + /** + * use as glColor3f + */ + void color3f(float r, float g, float b); + + template + inline void vertex3fv(SCAL* xyz) + { + vertex3f(float(xyz[0]),float(xyz[1]),float(xyz[2])); + } + + template + inline void color3fv(SCAL* rgb) + { + color3f(float(rgb[0]),float(rgb[1]),float(rgb[2])); + } + + /** + * use as a glCallList + * @param projection projection matrix + * @param modelview modelview matrix + */ + void callList(const QMatrix4x4& projection, const QMatrix4x4& modelview); + + /** + * usr as glPointSize + */ + inline void pointSize(float ps) + { + current_size_ = ps; + } + +}; + + + +} // namespace rendering + +} // namespace cgogn + +#endif // RENDERING_DRAWER_H_ diff --git a/cgogn/rendering/examples/simple_viewer.cpp b/cgogn/rendering/examples/simple_viewer.cpp index 54d0e1d1..f1cf4adc 100644 --- a/cgogn/rendering/examples/simple_viewer.cpp +++ b/cgogn/rendering/examples/simple_viewer.cpp @@ -36,16 +36,19 @@ #include #include #include +#include #include #include #include +#include + #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) using Map2 = cgogn::CMap2; -//using Vec3 = Eigen::Vector3d; -using Vec3 = cgogn::geometry::Vec_T>; +using Vec3 = Eigen::Vector3d; +//using Vec3 = cgogn::geometry::Vec_T>; template using VertexAttributeHandler = Map2::VertexAttributeHandler; @@ -74,10 +77,16 @@ class Viewer : public QOGLViewer cgogn::rendering::VBO* vbo_pos_; cgogn::rendering::VBO* vbo_norm_; + cgogn::rendering::VBO* vbo_color_; + cgogn::rendering::ShaderSimpleColor* shader1_; cgogn::rendering::ShaderFlat* shader2_; cgogn::rendering::ShaderVectorPerVertex* shader3_; + cgogn::rendering::ShaderPhong* shader_phong_; + + cgogn::rendering::Drawer* drawer_; + cgogn::rendering::Drawer* drawer2_; }; @@ -108,9 +117,11 @@ Viewer::~Viewer() delete render_; delete vbo_pos_; delete vbo_norm_; + delete vbo_color_; delete shader1_; delete shader2_; delete shader3_; + delete shader_phong_; } Viewer::Viewer() : @@ -133,48 +144,71 @@ void Viewer::draw() camera()->getProjectionMatrix(proj); camera()->getModelViewMatrix(view); - shader1_->bind(); - shader1_->set_matrices(proj,view); - shader1_->bind_vao(0); +// shader1_->bind(); +// shader1_->set_matrices(proj,view); +// shader1_->bind_vao(0); - glPointSize(5.0f); - shader1_->set_color(QColor(255,0,0)); - render_->draw(cgogn::rendering::POINTS); +// glPointSize(5.0f); +// shader1_->set_color(QColor(255,0,0)); +// render_->draw(cgogn::rendering::POINTS); - shader1_->set_color(QColor(255,255,0)); - render_->draw(cgogn::rendering::LINES); +// shader1_->set_color(QColor(255,255,0)); +// render_->draw(cgogn::rendering::LINES); - shader1_->release_vao(0); - shader1_->release(); +// shader1_->release_vao(0); +// shader1_->release(); - glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(1.0f, 1.0f); +// glEnable(GL_POLYGON_OFFSET_FILL); +// glPolygonOffset(1.0f, 1.0f); - shader2_->bind(); - shader2_->set_matrices(proj,view); - shader2_->bind_vao(0); +// shader2_->bind(); +// shader2_->set_matrices(proj,view); +// shader2_->bind_vao(0); +// render_->draw(cgogn::rendering::TRIANGLES); +// shader2_->release_vao(0); +// shader2_->release(); + +// shader3_->bind(); +// shader3_->set_matrices(proj,view); +// shader3_->bind_vao(0); +// render_->draw(cgogn::rendering::POINTS); +// shader3_->release_vao(0); +// shader3_->release(); + + shader_phong_->bind(); + shader_phong_->set_matrices(proj,view); + shader_phong_->bind_vao(0); render_->draw(cgogn::rendering::TRIANGLES); - shader2_->release_vao(0); - shader2_->release(); + shader_phong_->release_vao(0); + shader_phong_->release(); - shader3_->bind(); - shader3_->set_matrices(proj,view); - shader3_->bind_vao(0); - render_->draw(cgogn::rendering::POINTS); - shader3_->release_vao(0); - shader3_->release(); + + drawer_->callList(proj,view); + drawer2_->callList(proj,view); } void Viewer::init() { glClearColor(0.1,0.1,0.3,0.0); - vbo_pos_ = new cgogn::rendering::VBO; + vbo_pos_ = new cgogn::rendering::VBO(3); cgogn::rendering::update_vbo(vertex_position_, *vbo_pos_); - vbo_norm_ = new cgogn::rendering::VBO; + vbo_norm_ = new cgogn::rendering::VBO(3); cgogn::rendering::update_vbo(vertex_normal_, *vbo_norm_); + vbo_color_ = new cgogn::rendering::VBO(3); +// cgogn::rendering::update_vbo(vertex_normal_, *vbo_color_,[] (const Vec3& n) -> std::array +// { +// return {float(std::abs(n[0])), float(std::abs(n[1])), float(std::abs(n[2]))}; +// }); + + cgogn::rendering::update_vbo(vertex_normal_, vertex_normal_, *vbo_color_, [] (const Vec3& n, const Vec3& n2) -> std::array + { + return {float(std::abs(n[0])), float(std::abs(n[1])), float(std::abs(n2[2]))}; + }); + + render_ = new cgogn::rendering::MapRender(); render_->init_primitives(map_, cgogn::rendering::POINTS, vertex_position_); @@ -202,8 +236,76 @@ void Viewer::init() shader3_->bind(); shader3_->set_color(QColor(200,0,0)); shader3_->set_length(bb_.diag_size()/50); + shader3_->release(); - shader2_->release(); + + shader_phong_ = new cgogn::rendering::ShaderPhong(true); + shader_phong_->add_vao(); + shader_phong_->set_vao(0, vbo_pos_, vbo_norm_, vbo_color_); + + shader_phong_->bind(); + shader_phong_->set_front_color(QColor(0,200,0)); + shader_phong_->set_back_color(QColor(0,0,200)); + shader_phong_->set_ambiant_color(QColor(5,5,5)); + shader_phong_->set_double_side(true); + shader_phong_->set_specular_color(QColor(255,255,255)); + shader_phong_->set_specular_coef(10.0); + shader_phong_->release(); + + + // drawer for simple old-school g1 rendering + drawer_ = new cgogn::rendering::Drawer; + drawer_->new_list(); + drawer_->begin(GL_LINES); + drawer_->color3f(0.5,0.5,0.5); + drawer_->vertex3fv(bb_.min().data()); // fv work with float & double + drawer_->vertex3fv(bb_.max().data()); + drawer_->end(); + drawer_->begin(GL_LINE_LOOP); + drawer_->color3f(1.0,1.0,1.0); + drawer_->vertex3f(bb_.min()[0],bb_.min()[1],bb_.min()[2]); + drawer_->vertex3f(bb_.max()[0],bb_.min()[1],bb_.min()[2]); + drawer_->vertex3f(bb_.max()[0],bb_.max()[1],bb_.min()[2]); + drawer_->vertex3f(bb_.min()[0],bb_.max()[1],bb_.min()[2]); + drawer_->vertex3f(bb_.min()[0],bb_.max()[1],bb_.max()[2]); + drawer_->vertex3f(bb_.max()[0],bb_.max()[1],bb_.max()[2]); + drawer_->vertex3f(bb_.max()[0],bb_.min()[1],bb_.max()[2]); + drawer_->vertex3f(bb_.min()[0],bb_.min()[1],bb_.max()[2]); + drawer_->end(); + drawer_->begin(GL_LINES); + drawer_->vertex3f(bb_.min()[0],bb_.min()[1],bb_.min()[2]); + drawer_->vertex3f(bb_.min()[0],bb_.max()[1],bb_.min()[2]); + drawer_->vertex3f(bb_.min()[0],bb_.min()[1],bb_.max()[2]); + drawer_->vertex3f(bb_.min()[0],bb_.max()[1],bb_.max()[2]); + drawer_->vertex3f(bb_.max()[0],bb_.min()[1],bb_.min()[2]); + drawer_->vertex3f(bb_.max()[0],bb_.min()[1],bb_.max()[2]); + drawer_->vertex3f(bb_.max()[0],bb_.max()[1],bb_.min()[2]); + drawer_->vertex3f(bb_.max()[0],bb_.max()[1],bb_.max()[2]); + drawer_->end(); + drawer_->end_list(); + + drawer2_ = new cgogn::rendering::Drawer; + drawer2_->new_list(); + drawer2_->begin(GL_TRIANGLES); + drawer2_->color3f(0.0,1.0,1.0); + drawer2_->vertex3f(bb_.min()[0],bb_.min()[1],bb_.min()[2]); + drawer2_->color3f(1.0,1.0,0.0); + drawer2_->vertex3f(bb_.min()[0],bb_.max()[1],bb_.min()[2]); + drawer2_->color3f(1.0,0.0,1.0); + drawer2_->vertex3f(bb_.max()[0],bb_.max()[1],bb_.min()[2]); + drawer2_->end(); + + drawer2_->pointSize(5.0); + drawer2_->begin(GL_POINTS); + drawer2_->color3f(0.0,1.0,1.0); + drawer2_->vertex3f(bb_.min()[0],bb_.min()[1],bb_.max()[2]); + drawer2_->color3f(1.0,1.0,0.0); + drawer2_->vertex3f(bb_.min()[0],bb_.max()[1],bb_.max()[2]); + drawer2_->color3f(1.0,0.0,1.0); + drawer2_->vertex3f(bb_.max()[0],bb_.max()[1],bb_.max()[2]); + drawer2_->end(); + + drawer2_->end_list(); } int main(int argc, char** argv) diff --git a/cgogn/rendering/shaders/shader_color_per_vertex.cpp b/cgogn/rendering/shaders/shader_color_per_vertex.cpp index f170d89d..5eb2ce10 100644 --- a/cgogn/rendering/shaders/shader_color_per_vertex.cpp +++ b/cgogn/rendering/shaders/shader_color_per_vertex.cpp @@ -35,24 +35,24 @@ namespace rendering { const char* ShaderColorPerVertex::vertex_shader_source_ = - "#version 150\n" - "in vec3 vertex_pos;\n" - "in vec3 color;\n" - "uniform mat4 projection_matrix;\n" - "uniform mat4 model_view_matrix;\n" - "out vec3 color_v;\n" - "void main() {\n" - " color_v = color;" - " gl_Position = projection_matrix * model_view_matrix * vec4(vertex_pos,1.0);\n" - "}\n"; +"#version 150\n" +"in vec3 vertex_pos;\n" +"in vec3 vertex_color;\n" +"uniform mat4 projection_matrix;\n" +"uniform mat4 model_view_matrix;\n" +"out vec3 color_v;\n" +"void main() {\n" +" color_v = vertex_color;" +" gl_Position = projection_matrix * model_view_matrix * vec4(vertex_pos,1.0);\n" +"}\n"; const char* ShaderColorPerVertex::fragment_shader_source_ = - "#version 150\n" - "in vec3 color_v;\n" - "out vec3 fragColor;\n" - "void main() {\n" - " fragColor = color_v;\n" - "}\n"; +"#version 150\n" +"in vec3 color_v;\n" +"out vec3 fragColor;\n" +"void main() {\n" +" fragColor = color_v;\n" +"}\n"; ShaderColorPerVertex::ShaderColorPerVertex() @@ -60,7 +60,7 @@ ShaderColorPerVertex::ShaderColorPerVertex() prg_.addShaderFromSourceCode(QOpenGLShader::Vertex, vertex_shader_source_); prg_.addShaderFromSourceCode(QOpenGLShader::Fragment, fragment_shader_source_); prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); - prg_.bindAttributeLocation("color", ATTRIB_COLOR); + prg_.bindAttributeLocation("vertex_color", ATTRIB_COLOR); prg_.link(); get_matrices_uniforms(); diff --git a/cgogn/rendering/shaders/shader_phong.cpp b/cgogn/rendering/shaders/shader_phong.cpp new file mode 100644 index 00000000..41a30e23 --- /dev/null +++ b/cgogn/rendering/shaders/shader_phong.cpp @@ -0,0 +1,267 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#define CGOGN_RENDERING_DLL_EXPORT + +#include + +#include +#include +#include + +namespace cgogn +{ + +namespace rendering +{ + +const char* ShaderPhong::vertex_shader_source_ = + "#version 150\n" + "in vec3 vertex_pos;\n" + "in vec3 vertex_normal;\n" + "uniform mat4 projection_matrix;\n" + "uniform mat4 model_view_matrix;\n" + "uniform mat3 normal_matrix;\n" + "uniform vec3 lightPosition;\n" + "out vec3 EyeVector;\n" + "out vec3 Normal;\n" + "out vec3 LightDir;\n" + "void main ()\n" + "{\n" + " Normal = normal_matrix * vertex_normal;\n" + " vec3 Position = vec3 (model_view_matrix * vec4 (vertex_pos, 1.0));\n" + " LightDir = lightPosition - Position;\n" + " EyeVector = -Position;" + " gl_Position = projection_matrix * model_view_matrix * vec4 (vertex_pos, 1.0);\n" + "}\n"; + +const char* ShaderPhong::fragment_shader_source_ = + "#version 150\n" + "in vec3 EyeVector;\n" + "in vec3 Normal;\n" + "in vec3 LightDir;\n" + "uniform vec4 front_color;\n" + "uniform vec4 spec_color;\n" + "uniform vec4 ambiant_color;\n" + "uniform vec4 back_color;\n" + "uniform float spec_coef;\n" + "uniform bool double_side;\n" + "out vec4 frag_color;\n" + "void main()\n" + "{\n" + " vec3 N = normalize (Normal);\n" + " vec3 L = normalize (LightDir);\n" + " vec4 finalColor = ambiant_color;\n" + " vec4 currentColor = front_color;\n" + " if (!gl_FrontFacing)\n" + " {\n" + " if (!double_side)\n" + " discard;\n" + " N *= -1.0;\n" + " currentColor = back_color;\n" + " }\n" + " float lambertTerm = clamp(dot(N,L),0.0,1.0);\n" + " finalColor += currentColor*lambertTerm ;\n" + " vec3 E = normalize(EyeVector);\n" + " vec3 R = reflect(-L, N);\n" + " float specular = pow( max(dot(R, E), 0.0), spec_coef );\n" + " finalColor += spec_color * specular;\n" + " frag_color=finalColor;\n" + "}\n"; + + +const char* ShaderPhong::vertex_shader_source_2_ = + "#version 150\n" + "in vec3 vertex_pos;\n" + "in vec3 vertex_normal;\n" + "in vec3 vertex_color;\n" + "uniform mat4 projection_matrix;\n" + "uniform mat4 model_view_matrix;\n" + "uniform mat3 normal_matrix;\n" + "uniform vec3 lightPosition;\n" + "out vec3 EyeVector;\n" + "out vec3 Normal;\n" + "out vec3 LightDir;\n" + "out vec3 front_color;\n" + "void main ()\n" + "{\n" + " Normal = normal_matrix * vertex_normal;\n" + " vec3 Position = vec3 (model_view_matrix * vec4 (vertex_pos, 1.0));\n" + " LightDir = lightPosition - Position;\n" + " EyeVector = -Position;" + " front_color = vertex_color;" + " gl_Position = projection_matrix * model_view_matrix * vec4 (vertex_pos, 1.0);\n" + "}\n"; + +const char* ShaderPhong::fragment_shader_source_2_ = + "#version 150\n" + "in vec3 EyeVector;\n" + "in vec3 Normal;\n" + "in vec3 LightDir;\n" + "in vec3 front_color;\n" + "uniform vec4 spec_color;\n" + "uniform vec4 ambiant_color;\n" + "uniform float spec_coef;\n" + "uniform bool double_side;\n" + "out vec4 frag_color;\n" + "void main()\n" + "{\n" + " vec3 N = normalize (Normal);\n" + " vec3 L = normalize (LightDir);\n" + " vec4 finalColor = ambiant_color;\n" + " if (!gl_FrontFacing)\n" + " {\n" + " if (!double_side)\n" + " discard;\n" + " N *= -1.0;\n" + " }\n" + " float lambertTerm = clamp(dot(N,L),0.0,1.0);\n" + " finalColor += vec4(front_color*lambertTerm,0.0);\n" + " vec3 E = normalize(EyeVector);\n" + " vec3 R = reflect(-L, N);\n" + " float specular = pow( max(dot(R, E), 0.0), spec_coef );\n" + " finalColor += spec_color * specular;\n" + " frag_color=finalColor;\n" + "}\n"; + + + +ShaderPhong::ShaderPhong(bool color_per_vertex) +{ + if (color_per_vertex) + { + prg_.addShaderFromSourceCode(QOpenGLShader::Vertex, vertex_shader_source_2_); + prg_.addShaderFromSourceCode(QOpenGLShader::Fragment, fragment_shader_source_2_); + prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); + prg_.bindAttributeLocation("vertex_normal", ATTRIB_NORM); + prg_.bindAttributeLocation("vertex_color", ATTRIB_COLOR); + prg_.link(); + + get_matrices_uniforms(); + + unif_ambiant_color_ = prg_.uniformLocation("ambiant_color"); + unif_spec_color_ = prg_.uniformLocation("spec_color"); + unif_spec_coef_ = prg_.uniformLocation("spec_coef"); + unif_double_side_ = prg_.uniformLocation("double_side"); + } + else + { + prg_.addShaderFromSourceCode(QOpenGLShader::Vertex, vertex_shader_source_); + prg_.addShaderFromSourceCode(QOpenGLShader::Fragment, fragment_shader_source_); + prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); + prg_.bindAttributeLocation("vertex_normal", ATTRIB_NORM); + prg_.link(); + + get_matrices_uniforms(); + + unif_front_color_ = prg_.uniformLocation("front_color"); + unif_back_color_ = prg_.uniformLocation("back_color"); + unif_ambiant_color_ = prg_.uniformLocation("ambiant_color"); + unif_spec_color_ = prg_.uniformLocation("spec_color"); + unif_spec_coef_ = prg_.uniformLocation("spec_coef"); + unif_double_side_ = prg_.uniformLocation("double_side"); + } +} + + +void ShaderPhong::set_front_color(const QColor& rgb) +{ + if (unif_front_color_>=0) + prg_.setUniformValue(unif_front_color_,rgb); +} + +void ShaderPhong::set_back_color(const QColor& rgb) +{ + if (unif_back_color_>=0) + prg_.setUniformValue(unif_back_color_,rgb); +} + +void ShaderPhong::set_ambiant_color(const QColor& rgb) +{ + prg_.setUniformValue(unif_ambiant_color_,rgb); +} + +void ShaderPhong::set_specular_color(const QColor& rgb) +{ + prg_.setUniformValue(unif_spec_color_,rgb); +} + +void ShaderPhong::set_specular_coef(float coef) +{ + prg_.setUniformValue(unif_spec_coef_,coef); +} + +void ShaderPhong::set_double_side(bool ts) +{ + prg_.setUniformValue(unif_double_side_,ts); +} + +bool ShaderPhong::set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_norm, VBO* vbo_color) +{ + if (i >= vaos_.size()) + { + std::cerr << "VAO number " << i << " does not exist" << std::endl; + return false; + } + + QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); + + prg_.bind(); + vaos_[i]->bind(); + + // position vbo + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ATTRIB_POS); + ogl->glVertexAttribPointer(ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + + // position vbo + vbo_norm->bind(); + ogl->glEnableVertexAttribArray(ATTRIB_NORM); + ogl->glVertexAttribPointer(ATTRIB_NORM, vbo_norm->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_norm->release(); + + if (vbo_color) + { + // color vbo + vbo_color->bind(); + ogl->glEnableVertexAttribArray(ATTRIB_COLOR); + ogl->glVertexAttribPointer(ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_color->release(); + } + else + { + if (unif_front_color_<0) + std::cerr << "ShaderPhong: no color attribute, no color uniform"<< std::endl; + } + + vaos_[i]->release(); + prg_.release(); + + return true; +} + +} // namespace rendering + +} // namespace cgogn + diff --git a/cgogn/rendering/shaders/shader_phong.h b/cgogn/rendering/shaders/shader_phong.h new file mode 100644 index 00000000..3fc5aa94 --- /dev/null +++ b/cgogn/rendering/shaders/shader_phong.h @@ -0,0 +1,119 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef RENDERING_SHADERS_PHONG_H_ +#define RENDERING_SHADERS_PHONG_H_ + +#include +#include +#include + +class QColor; + +namespace cgogn +{ + +namespace rendering +{ + +class CGOGN_RENDERING_API ShaderPhong : public ShaderProgram +{ + static const char* vertex_shader_source_; + static const char* fragment_shader_source_; + + static const char* vertex_shader_source_2_; + static const char* fragment_shader_source_2_; + + + enum + { + ATTRIB_POS = 0, + ATTRIB_NORM, + ATTRIB_COLOR + }; + + // uniform ids + int unif_front_color_; + int unif_back_color_; + int unif_ambiant_color_; + int unif_spec_color_; + int unif_spec_coef_; + int unif_double_side_; + +public: + + ShaderPhong(bool color_per_vertex = false); + + /** + * @brief set current front color + * @param rgb + */ + void set_front_color(const QColor& rgb); + + /** + * @brief set current front color + * @param rgb + */ + void set_back_color(const QColor& rgb); + + /** + * @brief set current ambiant color + * @param rgb + */ + void set_ambiant_color(const QColor& rgb); + + /** + * @brief set current specular color + * @param rgb + */ + void set_specular_color(const QColor& rgb); + + /** + * @brief set current specular coefficient + * @param rgb + */ + void set_specular_coef(float coef); + + /** + * @brief set double side option + * @param ts + */ + void set_double_side(bool ts); + + + /** + * @brief set a vao configuration + * @param i id of vao (0,1,....) + * @param vbo_pos pointer on position vbo (XYZ) + * @param vbo_norm pointer on normal vbo (XYZ) + * @param vbo_color pointer on normal vbo (RGB) only used when color per vertex rendering + * @return true if ok + */ + bool set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_norm, VBO* vbo_color=NULL); +}; + +} // namespace rendering + +} // namespace cgogn + +#endif // RENDERING_SHADERS_PHONG_H_ diff --git a/cgogn/rendering/shaders/vbo.h b/cgogn/rendering/shaders/vbo.h index dc8b03fa..7c159e02 100644 --- a/cgogn/rendering/shaders/vbo.h +++ b/cgogn/rendering/shaders/vbo.h @@ -46,9 +46,9 @@ class VBO public: - inline VBO() : - nb_vectors_(0), - vector_dimension_(0) + inline VBO(unsigned int vec_dim) : + nb_vectors_(), + vector_dimension_(vec_dim) { buffer_.create(); buffer_.bind(); @@ -172,6 +172,109 @@ void update_vbo(const ATTR& attr, VBO& vbo) } } + + +template +void update_vbo(const ATTR& attr, VBO& vbo, const FUNC& convert) +{ + static_assert(function_traits::arity == 1, "convert lambda function must have only one arg"); + + const typename ATTR::TChunkArray* ca = attr.get_data(); + + std::vector chunk_addr; + unsigned int byte_chunk_size; + unsigned int nb_chunks = ca->get_chunks_pointers(chunk_addr, byte_chunk_size); + + typedef std::array Vec2f; + typedef std::array Vec3f; + typedef std::array Vec4f; + + typedef typename function_traits::result_type OutputConvert; + typedef inside_type(ATTR) InputConvert; + + unsigned int vec_dim = 0; + if (check_func_return_type(FUNC,float) ) + vec_dim = 1; + else if (check_func_return_type(FUNC,Vec2f) ) + vec_dim = 2; + else if (check_func_return_type(FUNC,Vec3f) ) + vec_dim = 3; + else if (check_func_return_type(FUNC,Vec4f) ) + vec_dim = 4; + else + { + cgogn_message_assert(false, "update_vbo: convert output must be float or std::array" ); + } + + vbo.allocate(nb_chunks * ATTR::CHUNKSIZE, vec_dim); + + // copy (after conversion) + OutputConvert* dst = reinterpret_cast(vbo.lock_pointer()); + for (unsigned int i = 0; i < nb_chunks; ++i) + { + InputConvert* typed_chunk = static_cast(chunk_addr[i]); + for (unsigned int j = 0; j < ATTR::CHUNKSIZE; ++j) + *dst++ = convert(typed_chunk[j]); + } + vbo.release_pointer(); +} + +template +void update_vbo(const ATTR& attr, const ATTR2& attr2, VBO& vbo, const FUNC& convert) +{ + static_assert(function_traits::arity == 2, "convert lambda function must have two arg"); + + const typename ATTR::TChunkArray* ca = attr.get_data(); + std::vector chunk_addr; + unsigned int byte_chunk_size; + unsigned int nb_chunks = ca->get_chunks_pointers(chunk_addr, byte_chunk_size); + + const typename ATTR::TChunkArray* ca2 = attr2.get_data(); + std::vector chunk_addr2; + unsigned int nb_chunks2 = ca2->get_chunks_pointers(chunk_addr2, byte_chunk_size); + + + typedef std::array Vec2f; + typedef std::array Vec3f; + typedef std::array Vec4f; + + typedef typename function_traits::result_type OutputConvert; + typedef inside_type(ATTR) InputConvert; + typedef inside_type(ATTR) InputConvert2; + + unsigned int vec_dim = 0; + if (check_func_return_type(FUNC,float) ) + vec_dim = 1; + else if (check_func_return_type(FUNC,Vec2f) ) + vec_dim = 2; + else if (check_func_return_type(FUNC,Vec3f) ) + vec_dim = 3; + else if (check_func_return_type(FUNC,Vec4f) ) + vec_dim = 4; + else + { + cgogn_message_assert(false, "update_vbo: convert output must be float or std::array" ); + } + + vbo.allocate(nb_chunks * ATTR::CHUNKSIZE, vec_dim); + + // copy (after conversion) + OutputConvert* dst = reinterpret_cast(vbo.lock_pointer()); + for (unsigned int i = 0; i < nb_chunks; ++i) + { + InputConvert* typed_chunk = static_cast(chunk_addr[i]); + InputConvert2* typed_chunk2 = static_cast(chunk_addr2[i]); + for (unsigned int j = 0; j < ATTR::CHUNKSIZE; ++j) + *dst++ = convert(typed_chunk[j],typed_chunk2[j]); + } + vbo.release_pointer(); +} + + + + + + } // namespace rendering } // namespace cgogn From ec13fe11922442229616a53806b137a3e83f7d64 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Thu, 25 Feb 2016 10:23:41 +0100 Subject: [PATCH 173/402] fixed compilation with MSVC + changed the name of some CMAKE variables. Signed-off-by: Etienne Schmitt --- cgogn/core/CMakeLists.txt | 1 - cgogn/geometry/CMakeLists.txt | 2 +- cgogn/io/CMakeLists.txt | 6 +++--- cgogn/multiresolution/CMakeLists.txt | 1 - cgogn/rendering/CMakeLists.txt | 6 +++--- thirdparty/TinyXml2/CMakeLists.txt | 2 +- thirdparty/eigen-3.2.7/CMakeLists.txt | 4 ++-- thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt | 3 +-- thirdparty/ply/CMakeLists.txt | 6 +++--- 9 files changed, 14 insertions(+), 17 deletions(-) diff --git a/cgogn/core/CMakeLists.txt b/cgogn/core/CMakeLists.txt index 41bfb287..989e8d1a 100644 --- a/cgogn/core/CMakeLists.txt +++ b/cgogn/core/CMakeLists.txt @@ -80,7 +80,6 @@ endif() set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "_d") target_include_directories(${PROJECT_NAME} PUBLIC - $ $ $ ) diff --git a/cgogn/geometry/CMakeLists.txt b/cgogn/geometry/CMakeLists.txt index 3631febf..7860a9fb 100644 --- a/cgogn/geometry/CMakeLists.txt +++ b/cgogn/geometry/CMakeLists.txt @@ -31,7 +31,7 @@ add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "_d") target_include_directories(${PROJECT_NAME} PUBLIC - $ + $ $ $ ) diff --git a/cgogn/io/CMakeLists.txt b/cgogn/io/CMakeLists.txt index f4652459..4f9d6144 100644 --- a/cgogn/io/CMakeLists.txt +++ b/cgogn/io/CMakeLists.txt @@ -22,10 +22,10 @@ add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "_d") target_include_directories(${PROJECT_NAME} PUBLIC - $ + $ $ - $ - $ + $ + $ $ ) diff --git a/cgogn/multiresolution/CMakeLists.txt b/cgogn/multiresolution/CMakeLists.txt index da5f0ef3..2eae3335 100644 --- a/cgogn/multiresolution/CMakeLists.txt +++ b/cgogn/multiresolution/CMakeLists.txt @@ -37,7 +37,6 @@ add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "_d") target_include_directories(${PROJECT_NAME} PUBLIC - $ $ $ ) diff --git a/cgogn/rendering/CMakeLists.txt b/cgogn/rendering/CMakeLists.txt index f186f3cb..82e0e255 100644 --- a/cgogn/rendering/CMakeLists.txt +++ b/cgogn/rendering/CMakeLists.txt @@ -31,10 +31,10 @@ add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "_d") target_include_directories(${PROJECT_NAME} PUBLIC - $ - $ + $ + $ $ - $ + $ $ ) diff --git a/thirdparty/TinyXml2/CMakeLists.txt b/thirdparty/TinyXml2/CMakeLists.txt index 38f21a06..dbdd35c0 100644 --- a/thirdparty/TinyXml2/CMakeLists.txt +++ b/thirdparty/TinyXml2/CMakeLists.txt @@ -1,4 +1,4 @@ -set(TinyXml2_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE PATH "TinyXml2 include directory") +set(CGOGN_THIRDPARTY_TINYXML2_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE PATH "TinyXml2 include directory") cmake_minimum_required(VERSION 3.0 FATAL_ERROR) project(tinyxml2) diff --git a/thirdparty/eigen-3.2.7/CMakeLists.txt b/thirdparty/eigen-3.2.7/CMakeLists.txt index 5b8d58e9..a41af45b 100644 --- a/thirdparty/eigen-3.2.7/CMakeLists.txt +++ b/thirdparty/eigen-3.2.7/CMakeLists.txt @@ -1,5 +1,5 @@ -set(EIGEN_ROOT "${CMAKE_CURRENT_SOURCE_DIR}" CACHE PATH "Directory for find_package(Eigen3)") -set(EIGEN3_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE PATH "Include directory for find_package(Eigen3)") +set(CGOGN_THIRDPARTY_EIGEN_ROOT "${CMAKE_CURRENT_SOURCE_DIR}" CACHE PATH "Directory for find_package(Eigen3)") +set(CGOGN_THIRDPARTY_EIGEN3_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE PATH "Include directory for find_package(Eigen3)") install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/Eigen COMPONENT Eigen_headers diff --git a/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt b/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt index 03bacd31..64f3c40e 100644 --- a/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt +++ b/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt @@ -1,4 +1,4 @@ -set(QOGLViewer_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE PATH "QOGLViewer include directory") +set(CGOGN_THIRDPARTY_QOGLVIEWER_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE PATH "QOGLViewer include directory") PROJECT(QOGLViewer) @@ -51,4 +51,3 @@ target_link_libraries(QOGLViewer ${OPENGL_LIBRARY} Qt5::Widgets) - diff --git a/thirdparty/ply/CMakeLists.txt b/thirdparty/ply/CMakeLists.txt index fdf73bb3..b276a2ac 100644 --- a/thirdparty/ply/CMakeLists.txt +++ b/thirdparty/ply/CMakeLists.txt @@ -1,4 +1,4 @@ -set(PLY_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE PATH "Ply include directory") +set(CGOGN_THIRDPARTY_PLY_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE PATH "Ply include directory") project(ply LANGUAGES C @@ -12,5 +12,5 @@ set(SOURCE_FILES ply.c ) -add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) -set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "_d") \ No newline at end of file +add_library(${PROJECT_NAME} STATIC ${HEADER_FILES} ${SOURCE_FILES}) +set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "_d") From 68361f08f92537f29303baea0f507ac5eefda1da Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Thu, 25 Feb 2016 14:17:24 +0100 Subject: [PATCH 174/402] remove is_boundary(Cell) --- cgogn/core/cmap/map_base.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 4db4d444..8c9ca2be 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -533,15 +533,6 @@ class MapBase : public MapBaseData this->boundary_marker_->set_value(d.index, b); } - template - inline bool is_boundary(Cell c) - { - static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - static_assert(ORBIT == ConcreteMap::BOUNDARY, "Cell is not of current map boundary dimension"); - - return is_boundary(c.dart); - } - /******************************************************************************* * Traversals *******************************************************************************/ From f4eb6c8146e4f6aec2a63d0b3542c7f1863f4c31 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Thu, 25 Feb 2016 17:06:04 +0100 Subject: [PATCH 175/402] Tests in CMap1 + bug in CMap2::add_face() --- cgogn/core/cmap/cmap1.h | 31 ++++-- cgogn/core/cmap/cmap2.h | 28 ++--- cgogn/core/cmap/cmap3.h | 6 +- cgogn/core/tests/cmap/cmap1_topo_test.cpp | 129 ++++++++++++---------- 4 files changed, 111 insertions(+), 83 deletions(-) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 670b7317..8eae2493 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -214,7 +214,7 @@ class CMap1_T : public CMap0_T this->new_orbit_embedding(nv); if (this->template is_embedded()) - this->copy_embedding(nv.dart, v.dart); + this->template copy_embedding(nv.dart, v.dart); return nv; } @@ -324,15 +324,26 @@ class CMap1_T : public CMap0_T inline bool has_degree(Face f, unsigned int degree) { - Dart it = f.dart ; - for (unsigned int i=1;i if (this->template is_embedded()) { - this->copy_embedding(nf, e); + this->template copy_embedding(nf, e); this->new_orbit_embedding(Edge(ne)); } if (this->template is_embedded()) { - this->copy_embedding(ne, e); - this->copy_embedding(nf, f); + this->template copy_embedding(ne, e); + this->template copy_embedding(nf, f); } if (this->template is_embedded()) { - this->copy_embedding(ne, e); - this->copy_embedding(nf, e); + this->template copy_embedding(ne, e); + this->template copy_embedding(nf, e); } return Vertex(ne); @@ -304,8 +304,8 @@ class CMap2_T : public CMap1_T if (this->template is_embedded()) { - this->copy_embedding(nd, e); - this->copy_embedding(ne, d); + this->template copy_embedding(nd, e); + this->template copy_embedding(ne, d); } if (this->template is_embedded()) @@ -315,14 +315,14 @@ class CMap2_T : public CMap1_T if (this->template is_embedded()) { - this->copy_embedding(nd, d.dart); + this->template copy_embedding(nd, d.dart); this->new_orbit_embedding(Face(ne)); } if (this->template is_embedded()) { - this->copy_embedding(nd, d.dart); - this->copy_embedding(ne, d.dart); + this->template copy_embedding(nd, d.dart); + this->template copy_embedding(ne, d.dart); } } @@ -445,13 +445,13 @@ class CMap2_T : public CMap1_T if (this->template is_embedded()) foreach_dart_of_orbit(new_face, [this] (Dart d) { - this->copy_embedding(d, this->phi1(phi2(d))); + this->template copy_embedding(d, this->phi1(phi2(d))); }); if (this->template is_embedded()) foreach_dart_of_orbit(new_face, [this] (Dart d) { - this->copy_embedding(d, phi2(d)); + this->template copy_embedding(d, phi2(d)); }); if (this->template is_embedded()) @@ -461,10 +461,10 @@ class CMap2_T : public CMap1_T if (this->template is_embedded()) { - const unsigned int idx = this->get_embedding(d); + const unsigned int idx = this->template get_embedding(d); foreach_dart_of_orbit(new_face, [this, idx] (Dart e) { - this->set_embedding(e, idx); + this->template set_embedding(e, idx); }); } } diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index c1ff4cf6..115e8f90 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -364,7 +364,7 @@ class CMap3_T : public CMap2_T { foreach_dart_of_orbit(new_volume, [this] (Dart wd) { - this->copy_embedding(wd, this->phi1(phi3(wd))); + this->template copy_embedding(wd, this->phi1(phi3(wd))); }); } @@ -372,7 +372,7 @@ class CMap3_T : public CMap2_T { foreach_dart_of_orbit(new_volume, [this] (Dart wd) { - this->copy_embedding(wd, phi3(wd)); + this->template copy_embedding(wd, phi3(wd)); }); } @@ -380,7 +380,7 @@ class CMap3_T : public CMap2_T { foreach_dart_of_orbit(new_volume, [this] (Dart wd) { - this->copy_embedding(wd, phi3(wd)); + this->template copy_embedding(wd, phi3(wd)); }); } diff --git a/cgogn/core/tests/cmap/cmap1_topo_test.cpp b/cgogn/core/tests/cmap/cmap1_topo_test.cpp index 8953bf1a..9b2e7a7c 100644 --- a/cgogn/core/tests/cmap/cmap1_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_topo_test.cpp @@ -32,14 +32,13 @@ namespace cgogn { +#define NB_MAX 1000 class CMap1TopoTest: public CMap1, public ::testing::Test { public: - static const int NB_MAX = 1000; - using Vertex = CMap1TopoTest::Vertex; using Face = CMap1TopoTest::Face; @@ -48,7 +47,7 @@ class CMap1TopoTest: public CMap1, public ::testing::Test /*! * \brief Generate a random set of faces. */ - CMap1TopoTest() : nb_darts_(0) + CMap1TopoTest() { std::srand(static_cast(std::time(0))); } @@ -69,7 +68,7 @@ class CMap1TopoTest: public CMap1, public ::testing::Test } int randomDarts() { - int n = std::rand() % NB_MAX; + int n = 1 + std::rand() % (NB_MAX-1); for (int i = 0; i < n; ++i) tdarts_[i] = add_dart(); @@ -79,11 +78,11 @@ class CMap1TopoTest: public CMap1, public ::testing::Test int randomFaces() { int count = 0; for (int i = 0; i < NB_MAX; ++i) { - int n = std::rand() % 100; + int n = 1 + std::rand() % 100; Dart d = add_face_topo(n); count += n; - for (int k = std::rand() % n; k > 0; ++k) + while (std::rand()%10 != 1) d = phi1(d); tdarts_[i] = d; @@ -92,7 +91,6 @@ class CMap1TopoTest: public CMap1, public ::testing::Test } std::array tdarts_; - int nb_darts_; }; @@ -139,79 +137,98 @@ TEST_F(CMap1TopoTest, testPhi1SewUnSew) EXPECT_TRUE(mapIntegrity()); } -TEST_F(CMap1TopoTest, testFaceDegree) -{ - Dart d = this->add_face_topo(10); - EXPECT_EQ(10, this->degree(Face(d))); -} TEST_F(CMap1TopoTest, testSplitVertex) { - Dart d = this->add_face_topo(10); - Dart d1 = this->phi1(d); - - Dart e = this->split_vertex_topo(d); + int n = randomFaces(); + EXPECT_EQ(this->template nb_cells(), n); + EXPECT_EQ(this->template nb_cells(), NB_MAX); + EXPECT_TRUE(mapIntegrity()); - EXPECT_EQ(d1.index, this->phi1(e).index); - EXPECT_EQ(d.index, this->phi_1(e).index); - EXPECT_EQ(11, this->degree(Face(d))); + for (int i = 0; i < NB_MAX; ++i) { + Face d = tdarts_[i]; + unsigned int k = degree(Face(d)); + split_vertex_topo(d); + EXPECT_EQ(degree(Face(d)), k+1); + } + EXPECT_EQ(this->template nb_cells(), n+NB_MAX); + EXPECT_EQ(this->template nb_cells(), NB_MAX); + EXPECT_TRUE(mapIntegrity()); } TEST_F(CMap1TopoTest, testRemoveVertex) { - Dart d = this->add_face_topo(10); - Dart d_1 = this->phi_1(d); - Dart d1 = this->phi1(d); + int n = randomFaces(); + EXPECT_EQ(this->template nb_cells(), n); + EXPECT_EQ(this->template nb_cells(), NB_MAX); + EXPECT_TRUE(mapIntegrity()); - this->remove_vertex(d); + int count = 0; + for (int i = 0; i < NB_MAX; ++i) { + Face d = tdarts_[i]; + unsigned int k = degree(Face(d)); + if (k > 1) { + Dart e = phi1(d); + remove_vertex(Vertex(d)); + ++count; + EXPECT_EQ(degree(Face(e)), k-1); + } + } + EXPECT_EQ(this->template nb_cells(), n-count); + EXPECT_EQ(this->template nb_cells(), NB_MAX); + EXPECT_TRUE(mapIntegrity()); +} - EXPECT_EQ(d1.index, this->phi1(d_1).index); - EXPECT_EQ(9, this->degree(Face(d_1))); +TEST_F(CMap1TopoTest, testAddFace) +{ + EXPECT_EQ(this->template nb_cells(), 0); + EXPECT_EQ(this->template nb_cells(), 0); + EXPECT_TRUE(mapIntegrity()); + int n = randomFaces(); + EXPECT_EQ(this->template nb_cells(), n); + EXPECT_EQ(this->template nb_cells(), NB_MAX); + EXPECT_TRUE(mapIntegrity()); } TEST_F(CMap1TopoTest, testReverseFace) { - Dart d = this->add_face_topo(10); - std::vector successors; - - { - Dart dit = d; - do - { - successors.push_back(this->phi1(dit)); - dit = this->phi1(dit); - } - while(dit != d); - } + int n = randomFaces(); + for (int i = 0; i < NB_MAX; ++i) { + Face f = tdarts_[i]; + unsigned int k = degree(f); + + std::vector face_darts; + foreach_dart_of_orbit(f, [&] (Dart d) { + face_darts.push_back(d); + }); - this->reverse_face_topo(d); + reverse_face_topo(tdarts_[i]); + EXPECT_EQ(degree(Face(tdarts_[i])), k); - { - Dart dit = d; - unsigned i = 0; - do - { - EXPECT_EQ(this->phi_1(dit).index, successors[i].index); - dit = this->phi_1(dit); - ++i; - } - while(dit != d); + f = phi1(f); + foreach_dart_of_orbit(f, [&] (Dart d) { + EXPECT_TRUE(face_darts.back() == d); + face_darts.pop_back(); + }); + EXPECT_TRUE(face_darts.empty()); } } -TEST_F(CMap1TopoTest, testForEachDartOfVertex) +TEST_F(CMap1TopoTest, testDegree) { - + Face f = this->add_face_topo(10); + EXPECT_EQ(degree(f),10); } -TEST_F(CMap1TopoTest, testForEachDartOfEdge) +TEST_F(CMap1TopoTest, testHasDegree) { - + Face f = this->add_face_topo(10); + EXPECT_TRUE(has_degree(f,10)); + EXPECT_FALSE(has_degree(f,0)); + EXPECT_FALSE(has_degree(f,9)); + EXPECT_FALSE(has_degree(f,11)); } -TEST_F(CMap1TopoTest, testForEachDartOfFace) -{ - -} +// The traversal methods are tested through the nb_cells calls and wihtin other methods } // namespace cgogn From 67f724a486a649dd9c691b98fc67d99b07fa0117 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Thu, 25 Feb 2016 17:52:23 +0100 Subject: [PATCH 176/402] =?UTF-8?q?Erreur=20dans=20le=20merge=20pr=C3=A9c?= =?UTF-8?q?=C3=A9dent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cgogn/core/cmap/cmap1.h | 4 ++-- cgogn/core/cmap/cmap2.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index ed234a67..086f4b8f 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -214,7 +214,7 @@ class CMap1_T : public CMap0_T this->new_orbit_embedding(nv); if (this->template is_embedded()) - this->template copy_embedding(nv.dart, v.dart); + this->template copy_embedding(nv.dart, v.dart); return nv; } @@ -335,7 +335,7 @@ class CMap1_T : public CMap0_T return result; }); return (result && degree == 0); - +// // Dart it = f.dart ; // for (unsigned int i=1;i { this->new_orbit_embedding(Vertex(d)); }); + } if (this->template is_embedded()) { From 5f863a7f3cf4f79d64ff9080dd7b2de5b2cdce6a Mon Sep 17 00:00:00 2001 From: David Cazier Date: Thu, 25 Feb 2016 17:55:18 +0100 Subject: [PATCH 177/402] =?UTF-8?q?Erreur=20dans=20le=20merge=20pr=C3=A9c?= =?UTF-8?q?=C3=A9dent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cgogn/core/cmap/cmap1.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 086f4b8f..b58e2139 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -266,10 +266,12 @@ class CMap1_T : public CMap0_T Face f = add_face_topo(size); if (this->template is_embedded()) + { foreach_dart_of_orbit(f, [this] (Dart d) { this->new_orbit_embedding(Vertex(d)); }); + } if (this->template is_embedded()) this->new_orbit_embedding(f); From 546bf7c39a99194faa17e1193955ccf1707540c2 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Thu, 25 Feb 2016 17:59:16 +0100 Subject: [PATCH 178/402] =?UTF-8?q?Erreur=20dans=20le=20merge=20pr=C3=A9c?= =?UTF-8?q?=C3=A9dent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cgogn/core/cmap/cmap2.h | 2 -- cgogn/core/cmap/cmap3.h | 12 +++++------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 002cb1ad..b82adecb 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -474,9 +474,7 @@ class CMap2_T : public CMap1_T } if (this->template is_embedded()) - { this->new_orbit_embedding(new_face); - } if (this->template is_embedded()) { diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 4f046d5c..acb5ae11 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -181,7 +181,7 @@ class CMap3_T : public CMap2_T std::vector m_tableVertDarts; m_tableVertDarts.reserve(n); - // creation of triangles around circunference and storing vertices + // creation of triangles around circumference and storing vertices for (unsigned int i = 0u; i < n; ++i) m_tableVertDarts.push_back(this->Inherit::Inherit::add_face_topo(3u)); @@ -226,9 +226,7 @@ class CMap3_T : public CMap2_T // storing a dart from the vertex pointed by phi1(phi1(d)) for (unsigned int i = 0u; i < n; ++i) - { m_tableVertDarts.emplace_back(this->phi1(this->phi1(m_tableVertDarts[i]))); - } // sewing the quads for (unsigned int i = 0u; i < n-1u; ++i) @@ -237,10 +235,10 @@ class CMap3_T : public CMap2_T const Dart e = this->phi1(m_tableVertDarts[i+1u]); this->phi2_sew(d,e); } - //sewing the last with the first - this->phi2_sew(this->phi1(m_tableVertDarts[0]), this->phi_1(m_tableVertDarts[n-1u])); + // sewing the last with the first + this->phi2_sew(this->phi1(m_tableVertDarts[0u]), this->phi_1(m_tableVertDarts[n-1u])); - //sewing the top & bottom faces + // sewing the top & bottom faces Dart top = this->Inherit::Inherit::add_face_topo(n); Dart bottom = this->Inherit::Inherit::add_face_topo(n); const Dart dres = top; @@ -252,7 +250,7 @@ class CMap3_T : public CMap2_T bottom = this->phi_1(bottom); } - //return a dart from the base + // return a dart from the base return dres; } From eb2f8497841d97e453eef8501c0b0515a7b1d0d1 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Thu, 25 Feb 2016 18:01:51 +0100 Subject: [PATCH 179/402] =?UTF-8?q?Erreur=20dans=20le=20merge=20pr=C3=A9c?= =?UTF-8?q?=C3=A9dent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cgogn/geometry/tests/algos/algos_test.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cgogn/geometry/tests/algos/algos_test.cpp b/cgogn/geometry/tests/algos/algos_test.cpp index 00c124e6..892af6af 100644 --- a/cgogn/geometry/tests/algos/algos_test.cpp +++ b/cgogn/geometry/tests/algos/algos_test.cpp @@ -37,8 +37,7 @@ #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) -//using StdArray = cgogn::geometry::Vec_T>; -using StdArray = Eigen::Vector3d; +using StdArray = cgogn::geometry::Vec_T>; using EigenVec3d = Eigen::Vector3d; using CMap2 = cgogn::CMap2; From 629fa322386a688da04b404a34a879f85a929bb0 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Thu, 25 Feb 2016 18:03:39 +0100 Subject: [PATCH 180/402] =?UTF-8?q?Erreur=20dans=20le=20merge=20pr=C3=A9c?= =?UTF-8?q?=C3=A9dent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cgogn/geometry/types/vec.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cgogn/geometry/types/vec.h b/cgogn/geometry/types/vec.h index 7847bc2f..4a290bdc 100644 --- a/cgogn/geometry/types/vec.h +++ b/cgogn/geometry/types/vec.h @@ -58,7 +58,7 @@ class Vec_T using Self = Vec_T; using Scalar = typename std::remove_cv< typename std::remove_reference::type >::type; -// inline Vec_T() : data_() {} + inline Vec_T() : data_() {} template inline Vec_T(Args... a) : data_({ std::forward(a)... }) From 5b8b4989e3b8f07dfacafebbb00bd520615ecf6a Mon Sep 17 00:00:00 2001 From: David Cazier Date: Thu, 25 Feb 2016 18:28:38 +0100 Subject: [PATCH 181/402] =?UTF-8?q?Erreur=20dans=20le=20merge=20pr=C3=A9c?= =?UTF-8?q?=C3=A9dent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cgogn/geometry/tests/algos/algos_test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/cgogn/geometry/tests/algos/algos_test.cpp b/cgogn/geometry/tests/algos/algos_test.cpp index 892af6af..7e6c0041 100644 --- a/cgogn/geometry/tests/algos/algos_test.cpp +++ b/cgogn/geometry/tests/algos/algos_test.cpp @@ -43,6 +43,7 @@ using EigenVec3d = Eigen::Vector3d; using CMap2 = cgogn::CMap2; template using VertexAttributeHandler = CMap2::VertexAttributeHandler; + using Vertex = CMap2::Vertex; using Edge = CMap2::Edge; using Face = CMap2::Face; From 8fdf0cb72ead87f8670e1ad2ae586e3a79c89d4a Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Thu, 25 Feb 2016 18:39:11 +0100 Subject: [PATCH 182/402] enhancement of update VBO --- cgogn/core/cmap/attribute_handler.h | 1 + cgogn/geometry/types/geometry_traits.h | 18 +++++ cgogn/rendering/examples/simple_viewer.cpp | 35 ++-------- cgogn/rendering/shaders/vbo.h | 81 +++++++++++++++------- 4 files changed, 80 insertions(+), 55 deletions(-) diff --git a/cgogn/core/cmap/attribute_handler.h b/cgogn/core/cmap/attribute_handler.h index dc9b55d6..df404942 100644 --- a/cgogn/core/cmap/attribute_handler.h +++ b/cgogn/core/cmap/attribute_handler.h @@ -115,6 +115,7 @@ class AttributeHandlerOrbit : public AttributeHandlerGen using MapData = typename Inherit::MapData; static const unsigned int CHUNKSIZE = MapData::CHUNKSIZE; + static const Orbit orbit_value = ORBIT; template using ChunkArrayContainer = cgogn::ChunkArrayContainer; diff --git a/cgogn/geometry/types/geometry_traits.h b/cgogn/geometry/types/geometry_traits.h index 4a080d40..61085ba6 100644 --- a/cgogn/geometry/types/geometry_traits.h +++ b/cgogn/geometry/types/geometry_traits.h @@ -56,6 +56,24 @@ struct vector_traits> using Scalar = Scalar_; }; +// specialization 3 & 4: is for uniform manip of vec & scalar (vbo) +// specialization 3 : float +template<> +struct vector_traits +{ + static const std::size_t SIZE = 1; + using Scalar = float; +}; + +// specialization 4 : double +template<> +struct vector_traits +{ + static const std::size_t SIZE = 1; + using Scalar = double; +}; + + } // namespace geometry } // namespace cgogn diff --git a/cgogn/rendering/examples/simple_viewer.cpp b/cgogn/rendering/examples/simple_viewer.cpp index f1cf4adc..78df90f3 100644 --- a/cgogn/rendering/examples/simple_viewer.cpp +++ b/cgogn/rendering/examples/simple_viewer.cpp @@ -106,7 +106,7 @@ void Viewer::import(const std::string& surfaceMesh) cgogn::geometry::compute_normal_vertices(map_, vertex_position_, vertex_normal_); cgogn::geometry::compute_bounding_box(vertex_position_, bb_); - setSceneRadius(bb_.diag_size()); + setSceneRadius(bb_.diag_size()/2.0); Vec3 center = bb_.center(); setSceneCenter(qoglviewer::Vec(center[0], center[1], center[2])); showEntireScene(); @@ -184,7 +184,6 @@ void Viewer::draw() drawer_->callList(proj,view); - drawer2_->callList(proj,view); } void Viewer::init() @@ -197,15 +196,11 @@ void Viewer::init() vbo_norm_ = new cgogn::rendering::VBO(3); cgogn::rendering::update_vbo(vertex_normal_, *vbo_norm_); + // fill a color vbo with abs of normals vbo_color_ = new cgogn::rendering::VBO(3); -// cgogn::rendering::update_vbo(vertex_normal_, *vbo_color_,[] (const Vec3& n) -> std::array -// { -// return {float(std::abs(n[0])), float(std::abs(n[1])), float(std::abs(n[2]))}; -// }); - - cgogn::rendering::update_vbo(vertex_normal_, vertex_normal_, *vbo_color_, [] (const Vec3& n, const Vec3& n2) -> std::array + cgogn::rendering::update_vbo(vertex_normal_, *vbo_color_,[] (const Vec3& n) -> std::array { - return {float(std::abs(n[0])), float(std::abs(n[1])), float(std::abs(n2[2]))}; + return {float(std::abs(n[0])), float(std::abs(n[1])), float(std::abs(n[2]))}; }); @@ -284,28 +279,6 @@ void Viewer::init() drawer_->end(); drawer_->end_list(); - drawer2_ = new cgogn::rendering::Drawer; - drawer2_->new_list(); - drawer2_->begin(GL_TRIANGLES); - drawer2_->color3f(0.0,1.0,1.0); - drawer2_->vertex3f(bb_.min()[0],bb_.min()[1],bb_.min()[2]); - drawer2_->color3f(1.0,1.0,0.0); - drawer2_->vertex3f(bb_.min()[0],bb_.max()[1],bb_.min()[2]); - drawer2_->color3f(1.0,0.0,1.0); - drawer2_->vertex3f(bb_.max()[0],bb_.max()[1],bb_.min()[2]); - drawer2_->end(); - - drawer2_->pointSize(5.0); - drawer2_->begin(GL_POINTS); - drawer2_->color3f(0.0,1.0,1.0); - drawer2_->vertex3f(bb_.min()[0],bb_.min()[1],bb_.max()[2]); - drawer2_->color3f(1.0,1.0,0.0); - drawer2_->vertex3f(bb_.min()[0],bb_.max()[1],bb_.max()[2]); - drawer2_->color3f(1.0,0.0,1.0); - drawer2_->vertex3f(bb_.max()[0],bb_.max()[1],bb_.max()[2]); - drawer2_->end(); - - drawer2_->end_list(); } int main(int argc, char** argv) diff --git a/cgogn/rendering/shaders/vbo.h b/cgogn/rendering/shaders/vbo.h index 7c159e02..c96db2b9 100644 --- a/cgogn/rendering/shaders/vbo.h +++ b/cgogn/rendering/shaders/vbo.h @@ -82,7 +82,11 @@ class VBO if (total != nb_vectors_ * vector_dimension_) // only allocate when > ? buffer_.allocate(total * sizeof(float)); nb_vectors_ = nb_vectors; - vector_dimension_ = vector_dimension; + if (vector_dimension != vector_dimension_) + { + vector_dimension_ = vector_dimension; + std::cout << " Warning, changing the VBO vector_dimension"<< std::endl; + } buffer_.release(); } @@ -124,9 +128,17 @@ class VBO } }; +/** + * @brief update vbo from one AttributeHandler + * @param attr AttributeHandler (must contain float or vec + * @param vbo vbo to update + * @param convert conversion lambda + */ template void update_vbo(const ATTR& attr, VBO& vbo) { + static_assert(std::is_same::Scalar, float>::value || std::is_same::Scalar, double>::value, "only float or double allowed for vbo"); + const typename ATTR::TChunkArray* ca = attr.get_data(); std::vector chunk_addr; @@ -166,32 +178,38 @@ void update_vbo(const ATTR& attr, VBO& vbo) vbo.release_pointer(); delete[] float_buffer; } - else - { - cgogn_assert_not_reached("only float or double allowed for vbo"); - } } - +/** + * @brief update vbo from one AttributeHandler with conversion lambda + * @param attr AttributeHandler + * @param vbo vbo to update + * @param convert conversion lambda + */ template void update_vbo(const ATTR& attr, VBO& vbo, const FUNC& convert) { + // check that convert has 1 param static_assert(function_traits::arity == 1, "convert lambda function must have only one arg"); - const typename ATTR::TChunkArray* ca = attr.get_data(); + // check that convert param is compatible with attr + typedef typename std::remove_cv< typename std::remove_reference::template arg<0>::type>::type >::type InputConvert; + static_assert(std::is_same::value, "wrong parameter 1"); + // get chunk data pointers + const typename ATTR::TChunkArray* ca = attr.get_data(); std::vector chunk_addr; unsigned int byte_chunk_size; unsigned int nb_chunks = ca->get_chunks_pointers(chunk_addr, byte_chunk_size); + // check that out of convert is float or std::array typedef std::array Vec2f; typedef std::array Vec3f; typedef std::array Vec4f; + static_assert(check_func_return_type(FUNC,float) || check_func_return_type(FUNC,Vec2f) || check_func_return_type(FUNC,Vec3f) ||check_func_return_type(FUNC,Vec4f), "convert output must be float or std::array" ); - typedef typename function_traits::result_type OutputConvert; - typedef inside_type(ATTR) InputConvert; - + // set vec dimension unsigned int vec_dim = 0; if (check_func_return_type(FUNC,float) ) vec_dim = 1; @@ -201,14 +219,11 @@ void update_vbo(const ATTR& attr, VBO& vbo, const FUNC& convert) vec_dim = 3; else if (check_func_return_type(FUNC,Vec4f) ) vec_dim = 4; - else - { - cgogn_message_assert(false, "update_vbo: convert output must be float or std::array" ); - } vbo.allocate(nb_chunks * ATTR::CHUNKSIZE, vec_dim); // copy (after conversion) + typedef typename function_traits::result_type OutputConvert; OutputConvert* dst = reinterpret_cast(vbo.lock_pointer()); for (unsigned int i = 0; i < nb_chunks; ++i) { @@ -219,11 +234,32 @@ void update_vbo(const ATTR& attr, VBO& vbo, const FUNC& convert) vbo.release_pointer(); } + +/** + * @brief update vbo from two AttributeHandlers with conversion lambda + * @param attr first AttributeHandler + * @param attr2 second AttributeHandler + * @param vbo vbo to update + * @param convert conversion lambda + */ template void update_vbo(const ATTR& attr, const ATTR2& attr2, VBO& vbo, const FUNC& convert) { + // check that convert has 2 param static_assert(function_traits::arity == 2, "convert lambda function must have two arg"); + //check that attr & attr2 are on same orbit + static_assert(ATTR::orbit_value == ATTR2::orbit_value, "attributes must be on same orbit"); + + // check that convert param 1 is compatible with attr + typedef typename std::remove_cv< typename std::remove_reference::template arg<0>::type>::type >::type InputConvert; + static_assert(std::is_same::value, "wrong parameter 1"); + + // check that convert param 2 is compatible with attr2 + typedef typename std::remove_cv< typename std::remove_reference::template arg<1>::type>::type >::type InputConvert2; + static_assert(std::is_same::value, "wrong parameter 2"); + + // get chunk data pointers const typename ATTR::TChunkArray* ca = attr.get_data(); std::vector chunk_addr; unsigned int byte_chunk_size; @@ -231,17 +267,15 @@ void update_vbo(const ATTR& attr, const ATTR2& attr2, VBO& vbo, const FUNC& conv const typename ATTR::TChunkArray* ca2 = attr2.get_data(); std::vector chunk_addr2; - unsigned int nb_chunks2 = ca2->get_chunks_pointers(chunk_addr2, byte_chunk_size); - + ca2->get_chunks_pointers(chunk_addr2, byte_chunk_size); + // check that out of convert is float or std::array typedef std::array Vec2f; typedef std::array Vec3f; typedef std::array Vec4f; + static_assert(check_func_return_type(FUNC,float) || check_func_return_type(FUNC,Vec2f) || check_func_return_type(FUNC,Vec3f) ||check_func_return_type(FUNC,Vec4f), "convert output must be float or std::array" ); - typedef typename function_traits::result_type OutputConvert; - typedef inside_type(ATTR) InputConvert; - typedef inside_type(ATTR) InputConvert2; - + // set vec dimension unsigned int vec_dim = 0; if (check_func_return_type(FUNC,float) ) vec_dim = 1; @@ -251,14 +285,13 @@ void update_vbo(const ATTR& attr, const ATTR2& attr2, VBO& vbo, const FUNC& conv vec_dim = 3; else if (check_func_return_type(FUNC,Vec4f) ) vec_dim = 4; - else - { - cgogn_message_assert(false, "update_vbo: convert output must be float or std::array" ); - } + // allocate vbo vbo.allocate(nb_chunks * ATTR::CHUNKSIZE, vec_dim); // copy (after conversion) + // out type conversion + typedef typename function_traits::result_type OutputConvert; OutputConvert* dst = reinterpret_cast(vbo.lock_pointer()); for (unsigned int i = 0; i < nb_chunks; ++i) { From d3b13c082a27a29954feceb6fe7f791b60e39b51 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Thu, 25 Feb 2016 19:04:58 +0100 Subject: [PATCH 183/402] shader_bold_line & ogl fix OsX --- cgogn/rendering/CMakeLists.txt | 2 + cgogn/rendering/drawer.cpp | 14 +- cgogn/rendering/drawer.h | 7 +- cgogn/rendering/examples/simple_viewer.cpp | 2 +- cgogn/rendering/shaders/shader_bold_line.cpp | 234 +++++++++++++++++++ cgogn/rendering/shaders/shader_bold_line.h | 87 +++++++ 6 files changed, 336 insertions(+), 10 deletions(-) create mode 100644 cgogn/rendering/shaders/shader_bold_line.cpp create mode 100644 cgogn/rendering/shaders/shader_bold_line.h diff --git a/cgogn/rendering/CMakeLists.txt b/cgogn/rendering/CMakeLists.txt index 86697c9f..4bb30295 100644 --- a/cgogn/rendering/CMakeLists.txt +++ b/cgogn/rendering/CMakeLists.txt @@ -16,6 +16,7 @@ set(HEADER_FILES shaders/shader_flat.h shaders/shader_vector_per_vertex.h shaders/shader_phong.h + shaders/shader_bold_line.h drawer.h ) @@ -26,6 +27,7 @@ set(SOURCE_FILES shaders/shader_flat.cpp shaders/shader_vector_per_vertex.cpp shaders/shader_phong.cpp + shaders/shader_bold_line.cpp drawer.cpp ) diff --git a/cgogn/rendering/drawer.cpp b/cgogn/rendering/drawer.cpp index 3a30ad6d..8f65cb70 100644 --- a/cgogn/rendering/drawer.cpp +++ b/cgogn/rendering/drawer.cpp @@ -36,7 +36,8 @@ namespace rendering ShaderColorPerVertex* Drawer::shader_cpv_= NULL; -Drawer::Drawer() : +Drawer::Drawer(QOpenGLFunctions_3_3_Core* ogl33): + ogl33_(ogl33), current_size_(1.0f) { vbo_pos_ = new VBO(3); @@ -145,7 +146,7 @@ void Drawer::end_list() void Drawer::callList(const QMatrix4x4& projection, const QMatrix4x4& modelview) { - QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); +// QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); if (begins_.empty()) return; @@ -155,19 +156,18 @@ void Drawer::callList(const QMatrix4x4& projection, const QMatrix4x4& modelview) shader_cpv_->bind_vao(vao_); for (auto& pp : begins_point_) { - glPointSize(pp.width); - ogl->glDrawArrays(pp.mode, pp.begin, pp.nb); + ogl33_->glPointSize(pp.width); + ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); } for (auto& pp : begins_line_) { - glLineWidth(3.0); - ogl->glDrawArrays(pp.mode, pp.begin, pp.nb); + ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); } for (auto& pp : begins_face_) { - ogl->glDrawArrays(pp.mode, pp.begin, pp.nb); + ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); } shader_cpv_->release_vao(vao_); diff --git a/cgogn/rendering/drawer.h b/cgogn/rendering/drawer.h index afde7bd4..d391779b 100644 --- a/cgogn/rendering/drawer.h +++ b/cgogn/rendering/drawer.h @@ -28,6 +28,7 @@ #include #include #include +#include //#include namespace cgogn @@ -37,7 +38,7 @@ namespace rendering { -class CGOGN_RENDERING_API Drawer +class CGOGN_RENDERING_API Drawer//: protected QOpenGLFunctions_3_3_Core { struct PrimParam { @@ -65,6 +66,8 @@ class CGOGN_RENDERING_API Drawer float current_size_; static ShaderColorPerVertex* shader_cpv_; + QOpenGLFunctions_3_3_Core* ogl33_; + public: /** @@ -72,7 +75,7 @@ class CGOGN_RENDERING_API Drawer * @param lineMode 0:simple thin Line / 1:line with possible width /2:3D Lines * @Warning need OpenGL context */ - Drawer(); + Drawer(QOpenGLFunctions_3_3_Core* ogl33); /** * release buffers and shader diff --git a/cgogn/rendering/examples/simple_viewer.cpp b/cgogn/rendering/examples/simple_viewer.cpp index 78df90f3..60934ef5 100644 --- a/cgogn/rendering/examples/simple_viewer.cpp +++ b/cgogn/rendering/examples/simple_viewer.cpp @@ -249,7 +249,7 @@ void Viewer::init() // drawer for simple old-school g1 rendering - drawer_ = new cgogn::rendering::Drawer; + drawer_ = new cgogn::rendering::Drawer(this); drawer_->new_list(); drawer_->begin(GL_LINES); drawer_->color3f(0.5,0.5,0.5); diff --git a/cgogn/rendering/shaders/shader_bold_line.cpp b/cgogn/rendering/shaders/shader_bold_line.cpp new file mode 100644 index 00000000..c4833824 --- /dev/null +++ b/cgogn/rendering/shaders/shader_bold_line.cpp @@ -0,0 +1,234 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#define CGOGN_RENDERING_DLL_EXPORT + +#include + +#include +#include + +namespace cgogn +{ + +namespace rendering +{ + +const char* ShaderBoldLine::vertex_shader_source_ = +"#version 150\n" +"in vec3 vertex_pos;\n" +"void main() {\n" +" gl_Position = vec4(vertex_pos,1.0);\n" +"}\n"; + + +const char* ShaderBoldLine::geometry_shader_source_ = +"#version 150\n" +"uniform mat4 projection_matrix;\n" +"uniform mat4 model_view_matrix;\n" +"uniform vec2 lineWidths;\n" +"void main()\n" +"{\n" +" vec4 A = model_view_matrix * gl_in[0].gl_Position;\n" +" vec4 B = model_view_matrix * gl_in[1].gl_Position;\n" +" float nearZ = 1.0;\n" +" if (projection_matrix[2][2] != 1.0)\n" +" nearZ = - projection_matrix[3][2] / (projection_matrix[2][2] - 1.0); \n" +" if ((A.z < nearZ) || (B.z < nearZ))\n" +" {\n" +" if (A.z >= nearZ)\n" +" A = B + (A-B)*(nearZ-B.z)/(A.z-B.z);\n" +" if (B.z >= nearZ)\n" +" B = A + (B-A)*(nearZ-A.z)/(B.z-A.z);\n" +" A = projection_matrix*A;\n" +" B = projection_matrix*B;\n" +" A = A/A.w;\n" +" B = B/B.w;\n" +" vec2 U2 = normalize(vec2(lineWidths[1],lineWidths[0])*(B.xy - A.xy));\n" +" vec2 LWCorr =lineWidths * max(abs(U2.x),abs(U2.y));\n" +" vec3 U = vec3(LWCorr*U2,0.0);\n" +" vec3 V = vec3(LWCorr*vec2(U2[1], -U2[0]), 0.0); \n" +" gl_Position = vec4(A.xyz-U, 1.0);\n" +" EmitVertex();\n" +" gl_Position = vec4(A.xyz+V, 1.0);\n" +" EmitVertex();\n" +" gl_Position = vec4(A.xyz-V, 1.0);\n" +" EmitVertex();\n" +" gl_Position = vec4(B.xyz+V, 1.0);\n" +" EmitVertex();\n" +" gl_Position = vec4(B.xyz-V, 1.0);\n" +" EmitVertex();\n" +" gl_Position = vec4(B.xyz+U, 1.0);\n" +" EmitVertex();\n" +" EndPrimitive();\n" +" }\n" +"}\n"; + + +const char* ShaderBoldLine::fragment_shader_source_ = +"#version 150\n" +"uniform vec4 color;\n" +"out vec3 fragColor;\n" +"void main() {\n" +" fragColor = color;\n" +"}\n"; + + + + + + +const char* ShaderBoldLine::vertex_shader_source2_ = +"#version 150\n" +"in vec3 vertex_pos;\n" +"in vec3 vertex_color;\n" +"out vec3 color_v;\n" +"void main() {\n" +" color_v = vertex_color;\n" +" gl_Position = vec4(vertex_pos,1.0);\n" +"}\n"; + + +const char* ShaderBoldLine::geometry_shader_source2_ = +"#version 150\n" +"in vec3 color_v[];\n" +"out vec3 color_f;\n" +"uniform mat4 projection_matrix;\n" +"uniform mat4 model_view_matrix;\n" +"uniform vec2 lineWidths;\n" +"void main()\n" +"{\n" +" vec4 A = model_view_matrix * gl_in[0].gl_Position;\n" +" vec4 B = model_view_matrix * gl_in[1].gl_Position;\n" +" float nearZ = 1.0;\n" +" if (projection_matrix[2][2] != 1.0)\n" +" nearZ = - projection_matrix[3][2] / (projection_matrix[2][2] - 1.0); \n" +" if ((A.z < nearZ) || (B.z < nearZ))\n" +" {\n" +" if (A.z >= nearZ)\n" +" A = B + (A-B)*(nearZ-B.z)/(A.z-B.z);\n" +" if (B.z >= nearZ)\n" +" B = A + (B-A)*(nearZ-A.z)/(B.z-A.z);\n" +" A = projection_matrix*A;\n" +" B = projection_matrix*B;\n" +" A = A/A.w;\n" +" B = B/B.w;\n" +" vec2 U2 = normalize(vec2(lineWidths[1],lineWidths[0])*(B.xy - A.xy));\n" +" vec2 LWCorr =lineWidths * max(abs(U2.x),abs(U2.y));\n" +" vec3 U = vec3(LWCorr*U2,0.0);\n" +" vec3 V = vec3(LWCorr*vec2(U2[1], -U2[0]), 0.0); \n" +" color_f = vcolor[0];\n" +" gl_Position = vec4(A.xyz-U, 1.0);\n" +" EmitVertex();\n" +" gl_Position = vec4(A.xyz+V, 1.0);\n" +" EmitVertex();\n" +" gl_Position = vec4(A.xyz-V, 1.0);\n" +" EmitVertex();\n" +" color_f = vcolor[1];\n" +" gl_Position = vec4(B.xyz+V, 1.0);\n" +" EmitVertex();\n" +" gl_Position = vec4(B.xyz-V, 1.0);\n" +" EmitVertex();\n" +" gl_Position = vec4(B.xyz+U, 1.0);\n" +" EmitVertex();\n" +" EndPrimitive();\n" +" }\n" +"}\n"; + + +const char* ShaderBoldLine::fragment_shader_source2_ = +"#version 150\n" +"in vec3 color_f;\n" +"out vec3 fragColor;\n" +"void main() {\n" +" fragColor = color_v;\n" +"}\n"; + + + +ShaderBoldLine::ShaderBoldLine() +{ + prg_.addShaderFromSourceCode(QOpenGLShader::Vertex, vertex_shader_source_); + prg_.addShaderFromSourceCode(QOpenGLShader::Geometry, geometry_shader_source_); + prg_.addShaderFromSourceCode(QOpenGLShader::Fragment, fragment_shader_source_); + prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); + prg_.bindAttributeLocation("vertex_color", ATTRIB_COLOR); + prg_.link(); + + get_matrices_uniforms(); + + unif_color_ = prg_.uniformLocation("color"); + unif_width_ = prg_.uniformLocation("lineWidths"); +} + +void ShaderBoldLine::set_color(const QColor& rgb) +{ + prg_.setUniformValue(unif_color_, rgb); +} + +void ShaderBoldLine::set_width(float w) +{ + prg_.setUniformValue(unif_width_, w); +} + +bool ShaderBoldLine::set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color) +{ + if (i >= vaos_.size()) + { + std::cerr << "VAO number " << i << " does not exist" << std::endl; + return false; + } + + QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); + + prg_.bind(); + vaos_[i]->bind(); + + // position vbo + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ATTRIB_POS); + ogl->glVertexAttribPointer(ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + + if (vbo_color) + { + // normal vbo + vbo_color->bind(); + ogl->glEnableVertexAttribArray(ATTRIB_COLOR); + ogl->glVertexAttribPointer(ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_color->release(); + } + else + { + if (unif_color_ == -1) + std::cerr << "ShaderBoldLine no coloe attribute no color uniform"<< std::endl; + } + vaos_[i]->release(); + prg_.release(); + + return true; +} + +} // namespace rendering + +} // namespace cgogn diff --git a/cgogn/rendering/shaders/shader_bold_line.h b/cgogn/rendering/shaders/shader_bold_line.h new file mode 100644 index 00000000..6258e1e1 --- /dev/null +++ b/cgogn/rendering/shaders/shader_bold_line.h @@ -0,0 +1,87 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef RENDERING_SHADERS_BOLDLINE_H_ +#define RENDERING_SHADERS_BOLDLINE_H_ + +#include +#include +#include + +namespace cgogn +{ + +namespace rendering +{ + +class CGOGN_RENDERING_API ShaderBoldLine : public ShaderProgram +{ + static const char* vertex_shader_source_; + static const char* geometry_shader_source_; + static const char* fragment_shader_source_; + + static const char* vertex_shader_source2_; + static const char* geometry_shader_source2_; + static const char* fragment_shader_source2_; + + enum + { + ATTRIB_POS = 0, + ATTRIB_COLOR + }; + + // uniform ids + int unif_color_; + int unif_width_; + +public: + + ShaderBoldLine(); + + /** + * @brief set current color + * @param rgb + */ + void set_color(const QColor& rgb); + + /** + * @brief set the width of lines + * @param w width in pixel + */ + void set_width(float w); + + /** + * @brief set a vao configuration + * @param i vao id (0,1,...) + * @param vbo_pos pointer on position vbo (XYZ) + * @param vbo_color pointer on color vbo + * @return true if ok + */ + bool set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color=NULL); +}; + +} // namespace rendering + +} // namespace cgogn + +#endif // RENDERING_SHADERS_BOLDLINE_H_ From f7bdfff6f1c70458cf0509b3b2e5e89a38f69dda Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Thu, 25 Feb 2016 19:36:37 +0100 Subject: [PATCH 184/402] cleaning viewer --- cgogn/rendering/examples/simple_viewer.cpp | 197 ++++++++++++++------- 1 file changed, 130 insertions(+), 67 deletions(-) diff --git a/cgogn/rendering/examples/simple_viewer.cpp b/cgogn/rendering/examples/simple_viewer.cpp index 60934ef5..b1ce9317 100644 --- a/cgogn/rendering/examples/simple_viewer.cpp +++ b/cgogn/rendering/examples/simple_viewer.cpp @@ -25,6 +25,7 @@ #include #include +#include #include @@ -63,6 +64,8 @@ class Viewer : public QOGLViewer virtual void draw(); virtual void init(); + + virtual void keyPressEvent(QKeyEvent *); void import(const std::string& surfaceMesh); virtual ~Viewer(); @@ -80,13 +83,20 @@ class Viewer : public QOGLViewer cgogn::rendering::VBO* vbo_color_; - cgogn::rendering::ShaderSimpleColor* shader1_; - cgogn::rendering::ShaderFlat* shader2_; - cgogn::rendering::ShaderVectorPerVertex* shader3_; + cgogn::rendering::ShaderSimpleColor* shader_vertex_edge_; + cgogn::rendering::ShaderFlat* shader_flat_; + cgogn::rendering::ShaderVectorPerVertex* shader_normal_; cgogn::rendering::ShaderPhong* shader_phong_; cgogn::rendering::Drawer* drawer_; - cgogn::rendering::Drawer* drawer2_; +// cgogn::rendering::Drawer* drawer2_; + + bool phong_rendering_; + bool flat_rendering_; + bool vertices_rendering_; + bool edge_rendering_; + bool normal_rendering_; + bool bb_rendering_; }; @@ -118,9 +128,9 @@ Viewer::~Viewer() delete vbo_pos_; delete vbo_norm_; delete vbo_color_; - delete shader1_; - delete shader2_; - delete shader3_; + delete shader_vertex_edge_; + delete shader_flat_; + delete shader_normal_; delete shader_phong_; } @@ -132,11 +142,49 @@ Viewer::Viewer() : render_(nullptr), vbo_pos_(nullptr), vbo_norm_(nullptr), - shader1_(nullptr), - shader2_(nullptr), - shader3_(nullptr) + shader_vertex_edge_(nullptr), + shader_flat_(nullptr), + shader_normal_(nullptr), + phong_rendering_(true), + flat_rendering_(false), + vertices_rendering_(false), + edge_rendering_(false), + normal_rendering_(false), + bb_rendering_(true) {} +void Viewer::keyPressEvent(QKeyEvent *ev) +{ + switch (ev->key()) { + case Qt::Key_P: + phong_rendering_ = true; + flat_rendering_ = false; + break; + case Qt::Key_F: + flat_rendering_ = true; + phong_rendering_ = false; + break; + case Qt::Key_N: + normal_rendering_ = !normal_rendering_; + break; + case Qt::Key_E: + edge_rendering_ = !edge_rendering_; + break; + case Qt::Key_V: + vertices_rendering_ = !vertices_rendering_; + break; + case Qt::Key_B: + bb_rendering_ = !bb_rendering_; + break; + case Qt::Key_Escape: + exit(0); + break; + default: + break; + } + update(); +} + void Viewer::draw() { QMatrix4x4 proj; @@ -144,46 +192,61 @@ void Viewer::draw() camera()->getProjectionMatrix(proj); camera()->getModelViewMatrix(view); -// shader1_->bind(); -// shader1_->set_matrices(proj,view); -// shader1_->bind_vao(0); + shader_vertex_edge_->bind(); + shader_vertex_edge_->set_matrices(proj,view); + shader_vertex_edge_->bind_vao(0); -// glPointSize(5.0f); -// shader1_->set_color(QColor(255,0,0)); -// render_->draw(cgogn::rendering::POINTS); - -// shader1_->set_color(QColor(255,255,0)); -// render_->draw(cgogn::rendering::LINES); + if (vertices_rendering_) + { + glPointSize(3.0f); + shader_vertex_edge_->set_color(QColor(255,0,0)); + render_->draw(cgogn::rendering::POINTS); + } -// shader1_->release_vao(0); -// shader1_->release(); + if (edge_rendering_) + { + shader_vertex_edge_->set_color(QColor(255,255,0)); + render_->draw(cgogn::rendering::LINES); + } -// glEnable(GL_POLYGON_OFFSET_FILL); -// glPolygonOffset(1.0f, 1.0f); + shader_vertex_edge_->release_vao(0); + shader_vertex_edge_->release(); -// shader2_->bind(); -// shader2_->set_matrices(proj,view); -// shader2_->bind_vao(0); -// render_->draw(cgogn::rendering::TRIANGLES); -// shader2_->release_vao(0); -// shader2_->release(); + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1.0f, 1.0f); -// shader3_->bind(); -// shader3_->set_matrices(proj,view); -// shader3_->bind_vao(0); -// render_->draw(cgogn::rendering::POINTS); -// shader3_->release_vao(0); -// shader3_->release(); + if (flat_rendering_) + { + shader_flat_->bind(); + shader_flat_->set_matrices(proj,view); + shader_flat_->bind_vao(0); + render_->draw(cgogn::rendering::TRIANGLES); + shader_flat_->release_vao(0); + shader_flat_->release(); + } - shader_phong_->bind(); - shader_phong_->set_matrices(proj,view); - shader_phong_->bind_vao(0); - render_->draw(cgogn::rendering::TRIANGLES); - shader_phong_->release_vao(0); - shader_phong_->release(); + if (phong_rendering_) + { + shader_phong_->bind(); + shader_phong_->set_matrices(proj,view); + shader_phong_->bind_vao(0); + render_->draw(cgogn::rendering::TRIANGLES); + shader_phong_->release_vao(0); + shader_phong_->release(); + } + if (normal_rendering_) + { + shader_normal_->bind(); + shader_normal_->set_matrices(proj,view); + shader_normal_->bind_vao(0); + render_->draw(cgogn::rendering::POINTS); + shader_normal_->release_vao(0); + shader_normal_->release(); + } - drawer_->callList(proj,view); + if (bb_rendering_) + drawer_->callList(proj,view); } void Viewer::init() @@ -210,28 +273,28 @@ void Viewer::init() render_->init_primitives(map_, cgogn::rendering::LINES, vertex_position_); render_->init_primitives(map_, cgogn::rendering::TRIANGLES, vertex_position_); - shader1_ = new cgogn::rendering::ShaderSimpleColor; - shader1_->add_vao(); - shader1_->set_vao(0, vbo_pos_); + shader_vertex_edge_ = new cgogn::rendering::ShaderSimpleColor; + shader_vertex_edge_->add_vao(); + shader_vertex_edge_->set_vao(0, vbo_pos_); - shader2_ = new cgogn::rendering::ShaderFlat; - shader2_->add_vao(); - shader2_->set_vao(0, vbo_pos_); + shader_flat_ = new cgogn::rendering::ShaderFlat; + shader_flat_->add_vao(); + shader_flat_->set_vao(0, vbo_pos_); - shader2_->bind(); - shader2_->set_front_color(QColor(0,200,0)); - shader2_->set_back_color(QColor(0,0,200)); - shader2_->set_ambiant_color(QColor(5,5,5)); - shader2_->release(); + shader_flat_->bind(); + shader_flat_->set_front_color(QColor(0,200,0)); + shader_flat_->set_back_color(QColor(0,0,200)); + shader_flat_->set_ambiant_color(QColor(5,5,5)); + shader_flat_->release(); - shader3_ = new cgogn::rendering::ShaderVectorPerVertex; - shader3_->add_vao(); - shader3_->set_vao(0, vbo_pos_, vbo_norm_); + shader_normal_ = new cgogn::rendering::ShaderVectorPerVertex; + shader_normal_->add_vao(); + shader_normal_->set_vao(0, vbo_pos_, vbo_norm_); - shader3_->bind(); - shader3_->set_color(QColor(200,0,0)); - shader3_->set_length(bb_.diag_size()/50); - shader3_->release(); + shader_normal_->bind(); + shader_normal_->set_color(QColor(200,0,200)); + shader_normal_->set_length(bb_.diag_size()/50); + shader_normal_->release(); shader_phong_ = new cgogn::rendering::ShaderPhong(true); @@ -239,8 +302,8 @@ void Viewer::init() shader_phong_->set_vao(0, vbo_pos_, vbo_norm_, vbo_color_); shader_phong_->bind(); - shader_phong_->set_front_color(QColor(0,200,0)); - shader_phong_->set_back_color(QColor(0,0,200)); +// shader_phong_->set_front_color(QColor(0,200,0)); +// shader_phong_->set_back_color(QColor(0,0,200)); shader_phong_->set_ambiant_color(QColor(5,5,5)); shader_phong_->set_double_side(true); shader_phong_->set_specular_color(QColor(255,255,255)); @@ -251,11 +314,11 @@ void Viewer::init() // drawer for simple old-school g1 rendering drawer_ = new cgogn::rendering::Drawer(this); drawer_->new_list(); - drawer_->begin(GL_LINES); - drawer_->color3f(0.5,0.5,0.5); - drawer_->vertex3fv(bb_.min().data()); // fv work with float & double - drawer_->vertex3fv(bb_.max().data()); - drawer_->end(); +// drawer_->begin(GL_LINES); +// drawer_->color3f(0.5,0.5,0.5); +// drawer_->vertex3fv(bb_.min().data()); // fv work with float & double +// drawer_->vertex3fv(bb_.max().data()); +// drawer_->end(); drawer_->begin(GL_LINE_LOOP); drawer_->color3f(1.0,1.0,1.0); drawer_->vertex3f(bb_.min()[0],bb_.min()[1],bb_.min()[2]); From 69e7e4667a0a42848dd0d6b33e4fa56ddd9a19c0 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Fri, 26 Feb 2016 09:37:52 +0100 Subject: [PATCH 185/402] Restore has_degree(n) --- cgogn/core/cmap/cmap1.h | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index b58e2139..87b6b43f 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -327,26 +327,15 @@ class CMap1_T : public CMap0_T inline bool has_degree(Face f, unsigned int degree) { - bool result = true; - - foreach_dart_of_orbit_until(f, [&result,°ree] (Dart d) { - if (degree == 0) { - result = false; - } - --degree; - return result; - }); - return (result && degree == 0); -// -// Dart it = f.dart ; -// for (unsigned int i=1;i Date: Fri, 26 Feb 2016 09:56:18 +0100 Subject: [PATCH 186/402] keep only one version of set/copy_embedding (with CellType template parameter) --- cgogn/core/cmap/cmap2_builder.h | 4 ++-- cgogn/core/cmap/cmap3_builder.h | 2 +- cgogn/core/cmap/map_base.h | 3 ++- cgogn/core/cmap/map_base_data.h | 17 ++++------------- cgogn/io/surface_import.h | 2 +- 5 files changed, 10 insertions(+), 18 deletions(-) diff --git a/cgogn/core/cmap/cmap2_builder.h b/cgogn/core/cmap/cmap2_builder.h index ae3f3c04..37f20002 100644 --- a/cgogn/core/cmap/cmap2_builder.h +++ b/cgogn/core/cmap/cmap2_builder.h @@ -62,10 +62,10 @@ class CMap2Builder_T map_.attributes_[ORBIT].swap(cac); } - template + template inline void set_embedding(Dart d, unsigned int emb) { - map_.template set_embedding(d, emb); + map_.template set_embedding(d, emb); } inline void phi2_sew(Dart d, Dart e) diff --git a/cgogn/core/cmap/cmap3_builder.h b/cgogn/core/cmap/cmap3_builder.h index 5a89e2d4..a0210b55 100644 --- a/cgogn/core/cmap/cmap3_builder.h +++ b/cgogn/core/cmap/cmap3_builder.h @@ -67,7 +67,7 @@ class CMap3Builder_T { map_.foreach_dart_of_PHI21(d, [&] (Dart dit) { - map_.template set_embedding(dit, emb); + map_.template set_embedding(dit, emb); }); } diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 6173bbba..1279903e 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -353,9 +353,10 @@ class MapBase : public MapBaseData template inline unsigned int new_orbit_embedding(Cell c) { + using CellType = Cell; const unsigned int emb = add_attribute_element(); to_concrete()->foreach_dart_of_orbit(c, [this, emb] (Dart d) { - this->template set_embedding(d, emb); + this->template set_embedding(d, emb); }); return emb; } diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index 97c253b6..58ffa201 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -266,9 +266,10 @@ class MapBaseData : public MapGen protected: - template + template inline void set_embedding(Dart d, unsigned int emb) { + static const Orbit ORBIT = CellType::ORBIT; static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); cgogn_message_assert(is_embedded(), "Invalid parameter: orbit not embedded"); cgogn_message_assert(emb != EMBNULL,"cannot set an embedding to EMBNULL."); @@ -284,22 +285,12 @@ class MapBaseData : public MapGen } template - inline void set_embedding(Dart d, unsigned int emb) - { - set_embedding(d, emb); - } - - template inline void copy_embedding(Dart dest, Dart src) { + static const Orbit ORBIT = CellType::ORBIT; static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - this->template set_embedding(dest, get_embedding(Cell(src))); - } - template - inline void copy_embedding(Dart dest, Dart src) - { - copy_embedding(dest, src); + this->template set_embedding(dest, get_embedding(CellType(src))); } /******************************************************************************* diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index aeaeb4e8..9f649497 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -207,7 +207,7 @@ class SurfaceImport for (unsigned int j = 0u; j < nbe; ++j) { const unsigned int vertex_index = vertices_buffer[j]; - mbuild.template set_embedding(d, vertex_index); + mbuild.template set_embedding(d, vertex_index); darts_per_vertex[vertex_index].push_back(d); d = map.phi1(d); } From a16959da58cd8ce920cee0bbc41365a052b78d36 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Fri, 26 Feb 2016 10:19:57 +0100 Subject: [PATCH 187/402] CMap1Test : embedded operators --- cgogn/core/tests/cmap/cmap1_test.cpp | 108 ++++++++++++++++++++-- cgogn/core/tests/cmap/cmap1_topo_test.cpp | 69 ++++++++++---- 2 files changed, 150 insertions(+), 27 deletions(-) diff --git a/cgogn/core/tests/cmap/cmap1_test.cpp b/cgogn/core/tests/cmap/cmap1_test.cpp index 882d9f83..4fa6c91e 100644 --- a/cgogn/core/tests/cmap/cmap1_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_test.cpp @@ -31,37 +31,125 @@ namespace cgogn { +#define NB_MAX 1000 + class CMap1Test: public ::testing::Test { public: - using myCMap1 = CMap1; - using Vertex = myCMap1::Vertex; - using Face = myCMap1::Face; + + using testCMap1 = CMap1; + using Vertex = testCMap1::Vertex; + using Face = testCMap1::Face; protected: - myCMap1 cmap_; + + testCMap1 cmap_; CMap1Test() - {} + { + std::srand(static_cast(std::time(0))); + + cmap_.add_attribute("vertices"); + cmap_.add_attribute("faces"); + } + int randomFaces() { + int count = 0; + for (int i = 0; i < NB_MAX; ++i) { + int n = 1 + std::rand() % 100; + Dart d = cmap_.add_face(n); + count += n; + while (std::rand()%10 != 1) + d = cmap_.phi1(d); + + tdarts_[i] = d; + } + return count; + } + + std::array tdarts_; }; +TEST_F(CMap1Test, testCMap1Constructor) +{ + EXPECT_EQ(cmap_.nb_cells(), 0u); + EXPECT_EQ(cmap_.nb_cells(), 0u); +} + TEST_F(CMap1Test, addFace) { - cmap_.add_attribute("int_f"); - cmap_.add_attribute("int_v"); - Face f = cmap_.add_face(10); + int n = randomFaces(); - cmap_.split_vertex(f.dart); + EXPECT_EQ(cmap_.nb_cells(), n); + EXPECT_EQ(cmap_.nb_cells(), NB_MAX); + EXPECT_TRUE(is_well_embedded(cmap_)); + EXPECT_TRUE(is_well_embedded(cmap_)); + EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); + EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); +} + +TEST_F(CMap1Test, testSplitVertex) +{ + int n = randomFaces(); + for (int i = 0; i < NB_MAX; ++i) { + Face d = tdarts_[i]; + unsigned int k = cmap_.degree(Face(d)); + cmap_.split_vertex(Vertex(d)); + } + EXPECT_EQ(cmap_.nb_cells(), n+NB_MAX); + EXPECT_EQ(cmap_.nb_cells(), NB_MAX); + EXPECT_TRUE(is_well_embedded(cmap_)); EXPECT_TRUE(is_well_embedded(cmap_)); + EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); + EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); +} + +TEST_F(CMap1Test, testRemoveVertex) +{ + int n = randomFaces(); + + int countVertex = n; + int countFace = NB_MAX; + for (int i = 0; i < NB_MAX; ++i) { + Face d = tdarts_[i]; + unsigned int k = cmap_.degree(d); + cmap_.remove_vertex(Vertex(d)); + --countVertex; + if (k == 1u) --countFace; + } + + EXPECT_EQ(cmap_.nb_cells(), countVertex); + EXPECT_EQ(cmap_.nb_cells(), countFace); EXPECT_TRUE(is_well_embedded(cmap_)); + EXPECT_TRUE(is_well_embedded(cmap_)); + EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); - EXPECT_TRUE(is_container_well_referenced(cmap_)); +} + +TEST_F(CMap1Test, testRemoveFace) +{ + int n = randomFaces(); + + int countVertex = n; + int countFace = NB_MAX; + for (int i = 0; i < NB_MAX; ++i) { + Face d = tdarts_[i]; + unsigned int k = cmap_.degree(d); + cmap_.remove_face(d); + countVertex -= k; + --countFace; + } + EXPECT_EQ(cmap_.nb_cells(), countVertex); + EXPECT_EQ(cmap_.nb_cells(), countFace); + EXPECT_TRUE(is_well_embedded(cmap_)); + EXPECT_TRUE(is_well_embedded(cmap_)); + EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); + EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); } } // namespace cgogn diff --git a/cgogn/core/tests/cmap/cmap1_topo_test.cpp b/cgogn/core/tests/cmap/cmap1_topo_test.cpp index 9b2e7a7c..0fd2fabc 100644 --- a/cgogn/core/tests/cmap/cmap1_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_topo_test.cpp @@ -44,6 +44,11 @@ class CMap1TopoTest: public CMap1, public ::testing::Test protected: + /*! + * \brief An array of randomly genrated darts on which the methods are tested. + */ + std::array tdarts_; + /*! * \brief Generate a random set of faces. */ @@ -89,14 +94,19 @@ class CMap1TopoTest: public CMap1, public ::testing::Test } return count; } - - std::array tdarts_; }; +TEST_F(CMap1TopoTest, testCMap1Constructor) +{ + EXPECT_EQ(nb_darts(), 0u); + EXPECT_EQ(this->template nb_cells(), 0u); + EXPECT_EQ(this->template nb_cells(), 0u); +} TEST_F(CMap1TopoTest, testAddDart) { int n = randomDarts(); + EXPECT_EQ(nb_darts(), n); EXPECT_TRUE(mapIntegrity()); } @@ -104,6 +114,7 @@ TEST_F(CMap1TopoTest, testAddDart) TEST_F(CMap1TopoTest, testDeleteDart) { int n = randomDarts(); + int count = n; for (int i = 0; i < n; ++i) { if (std::rand() % 3 == 1) { @@ -111,6 +122,7 @@ TEST_F(CMap1TopoTest, testDeleteDart) --count; } } + EXPECT_EQ(nb_darts(), count); EXPECT_TRUE(mapIntegrity()); } @@ -118,6 +130,7 @@ TEST_F(CMap1TopoTest, testDeleteDart) TEST_F(CMap1TopoTest, testPhi1SewUnSew) { int n = randomDarts(); + for (int i = 0; i < 1000; ++i) { Dart d = tdarts_[std::rand() % n]; Dart e = tdarts_[std::rand() % n]; @@ -133,17 +146,23 @@ TEST_F(CMap1TopoTest, testPhi1SewUnSew) EXPECT_TRUE(phi1(nf1) == nf1); EXPECT_TRUE(phi1(f) == nf2); } + EXPECT_EQ(nb_darts(), n); EXPECT_TRUE(mapIntegrity()); } - -TEST_F(CMap1TopoTest, testSplitVertex) +TEST_F(CMap1TopoTest, testAddFace) { int n = randomFaces(); + EXPECT_EQ(this->template nb_cells(), n); EXPECT_EQ(this->template nb_cells(), NB_MAX); EXPECT_TRUE(mapIntegrity()); +} + +TEST_F(CMap1TopoTest, testSplitVertex) +{ + int n = randomFaces(); for (int i = 0; i < NB_MAX; ++i) { Face d = tdarts_[i]; @@ -151,6 +170,7 @@ TEST_F(CMap1TopoTest, testSplitVertex) split_vertex_topo(d); EXPECT_EQ(degree(Face(d)), k+1); } + EXPECT_EQ(this->template nb_cells(), n+NB_MAX); EXPECT_EQ(this->template nb_cells(), NB_MAX); EXPECT_TRUE(mapIntegrity()); @@ -159,40 +179,53 @@ TEST_F(CMap1TopoTest, testSplitVertex) TEST_F(CMap1TopoTest, testRemoveVertex) { int n = randomFaces(); - EXPECT_EQ(this->template nb_cells(), n); - EXPECT_EQ(this->template nb_cells(), NB_MAX); - EXPECT_TRUE(mapIntegrity()); - int count = 0; + int countVertex = n; + int countFace = NB_MAX; for (int i = 0; i < NB_MAX; ++i) { Face d = tdarts_[i]; unsigned int k = degree(Face(d)); if (k > 1) { Dart e = phi1(d); remove_vertex(Vertex(d)); - ++count; + --countVertex; EXPECT_EQ(degree(Face(e)), k-1); } + else { + remove_vertex(Vertex(d)); + --countFace; + --countVertex; + } } - EXPECT_EQ(this->template nb_cells(), n-count); - EXPECT_EQ(this->template nb_cells(), NB_MAX); + + EXPECT_EQ(this->template nb_cells(), countVertex); + EXPECT_EQ(this->template nb_cells(), countFace); EXPECT_TRUE(mapIntegrity()); } -TEST_F(CMap1TopoTest, testAddFace) +TEST_F(CMap1TopoTest, testRemoveFace) { - EXPECT_EQ(this->template nb_cells(), 0); - EXPECT_EQ(this->template nb_cells(), 0); - EXPECT_TRUE(mapIntegrity()); int n = randomFaces(); - EXPECT_EQ(this->template nb_cells(), n); - EXPECT_EQ(this->template nb_cells(), NB_MAX); + + int countVertex = n; + int countFace = NB_MAX; + for (int i = 0; i < NB_MAX; ++i) { + Face d = tdarts_[i]; + unsigned int k = degree(Face(d)); + remove_face(d); + countVertex -= k; + --countFace; + } + + EXPECT_EQ(this->template nb_cells(), countVertex); + EXPECT_EQ(this->template nb_cells(), countFace); EXPECT_TRUE(mapIntegrity()); } TEST_F(CMap1TopoTest, testReverseFace) { int n = randomFaces(); + for (int i = 0; i < NB_MAX; ++i) { Face f = tdarts_[i]; unsigned int k = degree(f); @@ -217,12 +250,14 @@ TEST_F(CMap1TopoTest, testReverseFace) TEST_F(CMap1TopoTest, testDegree) { Face f = this->add_face_topo(10); + EXPECT_EQ(degree(f),10); } TEST_F(CMap1TopoTest, testHasDegree) { Face f = this->add_face_topo(10); + EXPECT_TRUE(has_degree(f,10)); EXPECT_FALSE(has_degree(f,0)); EXPECT_FALSE(has_degree(f,9)); From 184b664b108c997d12886d4769d368105f2dcf78 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Fri, 26 Feb 2016 10:28:43 +0100 Subject: [PATCH 188/402] Cleanup some Cell declarations --- cgogn/core/cmap/cmap2.h | 4 ++-- cgogn/core/cmap/map_base.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index b82adecb..2da19fca 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -49,10 +49,10 @@ class CMap2_T : public CMap1_T friend class DartMarker_T; friend class cgogn::DartMarkerStore; - using CDart = Cell; + using CDart = typename Inherit::Vertex; using Vertex = Cell; using Edge = Cell; - using Face = Cell; + using Face = typename Inherit::Face; using Volume = Cell; template diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 2600f482..cd43272a 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -388,7 +388,6 @@ class MapBase : public MapBaseData bool is_well_embedded(Cell c) const { const ConcreteMap* cmap = to_concrete(); - //unsigned int index = this->get_embedding(c); bool result = true; std::map emb_set; From a58ff6e8f25713ab04884e92c0eadf1a5928f6fe Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Fri, 26 Feb 2016 10:48:10 +0100 Subject: [PATCH 189/402] Tests for CMap0 --- cgogn/core/tests/CMakeLists.txt | 5 ++ cgogn/core/tests/cmap/cmap0_test.cpp | 97 ++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 cgogn/core/tests/cmap/cmap0_test.cpp diff --git a/cgogn/core/tests/CMakeLists.txt b/cgogn/core/tests/CMakeLists.txt index a47001c0..f511bfcd 100644 --- a/cgogn/core/tests/CMakeLists.txt +++ b/cgogn/core/tests/CMakeLists.txt @@ -5,9 +5,14 @@ project(cgogn_core_test set(SOURCE_FILES basic/dart_test.cpp basic/cell_test.cpp + container/chunk_array_container_test.cpp + + cmap/cmap0_topo_test.cpp + cmap/cmap0_test.cpp cmap/cmap1_topo_test.cpp cmap/cmap1_test.cpp + utils/name_types_test.cpp main.cpp diff --git a/cgogn/core/tests/cmap/cmap0_test.cpp b/cgogn/core/tests/cmap/cmap0_test.cpp new file mode 100644 index 00000000..dd5fd06d --- /dev/null +++ b/cgogn/core/tests/cmap/cmap0_test.cpp @@ -0,0 +1,97 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#include +#include + +#include +#include +#include + +namespace cgogn +{ + +#define NB_MAX 1000 + +class CMap0Test: public ::testing::Test +{ + +public: + + using testCMap0 = CMap0; + using Vertex = testCMap0::Vertex; + +protected: + + testCMap0 cmap_; + + CMap0Test() + { + std::srand(static_cast(std::time(0))); + + cmap_.add_attribute("vertices"); + } + + std::array tdarts_; + + int randomVertices() { + for (int i = 0; i < NB_MAX; ++i) + tdarts_[i] = cmap_.add_vertex(); + + return NB_MAX; + } +}; + +TEST_F(CMap0Test, testCMap0Constructor) +{ + EXPECT_EQ(cmap_.nb_cells(), 0u); +} + +TEST_F(CMap0Test, testAddVertex) +{ + int n = randomVertices(); + + EXPECT_EQ(cmap_.nb_cells(), n); + EXPECT_TRUE(is_well_embedded(cmap_)); + EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); +} + +TEST_F(CMap0Test, testRemoveVertex) +{ + int n = randomVertices(); + + int countVertex = n; + for (int i = 0; i < n; ++i) { + Vertex d = tdarts_[i]; + if (std::rand() % 2 == 1) { + cmap_.remove_vertex(Vertex(d)); + --countVertex; + } + } + + EXPECT_EQ(cmap_.nb_cells(), countVertex); + EXPECT_TRUE(is_well_embedded(cmap_)); + EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); +} + +} // namespace cgogn From 72a0e72f2ecfead36afce77c39d8fc3a64f07b6b Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Fri, 26 Feb 2016 12:17:22 +0100 Subject: [PATCH 190/402] Clean includes --- cgogn/core/tests/CMakeLists.txt | 2 ++ cgogn/core/tests/cmap/cmap0_test.cpp | 14 +++++--------- cgogn/core/tests/cmap/cmap1_test.cpp | 5 +++-- cgogn/core/tests/cmap/cmap1_topo_test.cpp | 9 +++++---- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/cgogn/core/tests/CMakeLists.txt b/cgogn/core/tests/CMakeLists.txt index f511bfcd..1e258273 100644 --- a/cgogn/core/tests/CMakeLists.txt +++ b/cgogn/core/tests/CMakeLists.txt @@ -12,6 +12,8 @@ set(SOURCE_FILES cmap/cmap0_test.cpp cmap/cmap1_topo_test.cpp cmap/cmap1_test.cpp +# cmap/cmap2_topo_test.cpp +# cmap/cmap2_test.cpp utils/name_types_test.cpp diff --git a/cgogn/core/tests/cmap/cmap0_test.cpp b/cgogn/core/tests/cmap/cmap0_test.cpp index dd5fd06d..e4d76cf9 100644 --- a/cgogn/core/tests/cmap/cmap0_test.cpp +++ b/cgogn/core/tests/cmap/cmap0_test.cpp @@ -21,11 +21,9 @@ * * *******************************************************************************/ -#include #include -#include -#include +#include #include namespace cgogn @@ -47,14 +45,12 @@ class CMap0Test: public ::testing::Test CMap0Test() { - std::srand(static_cast(std::time(0))); - cmap_.add_attribute("vertices"); } std::array tdarts_; - int randomVertices() { + int addVertices() { for (int i = 0; i < NB_MAX; ++i) tdarts_[i] = cmap_.add_vertex(); @@ -69,7 +65,7 @@ TEST_F(CMap0Test, testCMap0Constructor) TEST_F(CMap0Test, testAddVertex) { - int n = randomVertices(); + int n = addVertices(); EXPECT_EQ(cmap_.nb_cells(), n); EXPECT_TRUE(is_well_embedded(cmap_)); @@ -78,12 +74,12 @@ TEST_F(CMap0Test, testAddVertex) TEST_F(CMap0Test, testRemoveVertex) { - int n = randomVertices(); + int n = addVertices(); int countVertex = n; for (int i = 0; i < n; ++i) { Vertex d = tdarts_[i]; - if (std::rand() % 2 == 1) { + if (i%2 == 1) { cmap_.remove_vertex(Vertex(d)); --countVertex; } diff --git a/cgogn/core/tests/cmap/cmap1_test.cpp b/cgogn/core/tests/cmap/cmap1_test.cpp index 4fa6c91e..0dce2528 100644 --- a/cgogn/core/tests/cmap/cmap1_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_test.cpp @@ -21,11 +21,12 @@ * * *******************************************************************************/ -#include +#include +#include + #include #include -#include #include namespace cgogn diff --git a/cgogn/core/tests/cmap/cmap1_topo_test.cpp b/cgogn/core/tests/cmap/cmap1_topo_test.cpp index 0fd2fabc..f0e45ba0 100644 --- a/cgogn/core/tests/cmap/cmap1_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_topo_test.cpp @@ -24,7 +24,6 @@ #include #include -#include #include #include @@ -58,16 +57,17 @@ class CMap1TopoTest: public CMap1, public ::testing::Test } bool dartIntegrity(Dart d) { - return (phi1(phi_1(d)) == d && phi_1(phi1(d)) == d); + return (phi1(phi_1(d)) == d && + phi_1(phi1(d)) == d); } bool mapIntegrity() { bool result = true; - foreach_dart( [&] (Dart d) { + foreach_dart_until( [&] (Dart d) { if (!dartIntegrity(d)) { result = false; - return ; } + return result; }); return result; } @@ -106,6 +106,7 @@ TEST_F(CMap1TopoTest, testCMap1Constructor) TEST_F(CMap1TopoTest, testAddDart) { int n = randomDarts(); + (*phi1_)[tdarts_[n-1].index] = Dart(1024); EXPECT_EQ(nb_darts(), n); EXPECT_TRUE(mapIntegrity()); From 1ba1f8c07d8edfbcb7862c1ff44985964b9ca496 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Fri, 26 Feb 2016 15:55:22 +0100 Subject: [PATCH 191/402] cmap0_topo_test.cpp --- cgogn/core/tests/cmap/cmap0_topo_test.cpp | 92 +++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 cgogn/core/tests/cmap/cmap0_topo_test.cpp diff --git a/cgogn/core/tests/cmap/cmap0_topo_test.cpp b/cgogn/core/tests/cmap/cmap0_topo_test.cpp new file mode 100644 index 00000000..d1767be8 --- /dev/null +++ b/cgogn/core/tests/cmap/cmap0_topo_test.cpp @@ -0,0 +1,92 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#include + +#include + +namespace cgogn +{ + +#define NB_MAX 1000 + +class CMap0TopoTest: public ::testing::Test +{ + +public: + + using testCMap0 = CMap0; + using Vertex = testCMap0::Vertex; + +protected: + + testCMap0 cmap_; + + CMap0TopoTest() + { + } + + std::array tdarts_; + + int addVertices() { + for (int i = 0; i < NB_MAX; ++i) + tdarts_[i] = cmap_.add_vertex(); + + return NB_MAX; + } +}; + +TEST_F(CMap0TopoTest, testCMap0Constructor) +{ + EXPECT_EQ(cmap_.nb_darts(), 0u); + EXPECT_EQ(cmap_.nb_cells(), 0u); +} + +TEST_F(CMap0TopoTest, testAddVertex) +{ + int n = addVertices(); + + EXPECT_EQ(cmap_.nb_darts(), n); + EXPECT_EQ(cmap_.nb_cells(), n); + EXPECT_TRUE(cmap_.check_map_integrity()); +} + +TEST_F(CMap0TopoTest, testRemoveVertex) +{ + int n = addVertices(); + + int countVertex = n; + for (int i = 0; i < n; ++i) { + Vertex d = tdarts_[i]; + if (i%2 == 1) { + cmap_.remove_vertex(Vertex(d)); + --countVertex; + } + } + + EXPECT_EQ(cmap_.nb_darts(), countVertex); + EXPECT_EQ(cmap_.nb_cells(), countVertex); + EXPECT_TRUE(cmap_.check_map_integrity()); +} + +} // namespace cgogn From a71fdf0fcbe471bb2af5c45bea85c30e045e737d Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Fri, 26 Feb 2016 17:31:55 +0100 Subject: [PATCH 192/402] using instead of typedef --- cgogn/rendering/shaders/vbo.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/cgogn/rendering/shaders/vbo.h b/cgogn/rendering/shaders/vbo.h index c96db2b9..2d5eb174 100644 --- a/cgogn/rendering/shaders/vbo.h +++ b/cgogn/rendering/shaders/vbo.h @@ -194,7 +194,7 @@ void update_vbo(const ATTR& attr, VBO& vbo, const FUNC& convert) static_assert(function_traits::arity == 1, "convert lambda function must have only one arg"); // check that convert param is compatible with attr - typedef typename std::remove_cv< typename std::remove_reference::template arg<0>::type>::type >::type InputConvert; + using InputConvert = typename std::remove_cv< typename std::remove_reference::template arg<0>::type>::type >::type; static_assert(std::is_same::value, "wrong parameter 1"); // get chunk data pointers @@ -204,9 +204,9 @@ void update_vbo(const ATTR& attr, VBO& vbo, const FUNC& convert) unsigned int nb_chunks = ca->get_chunks_pointers(chunk_addr, byte_chunk_size); // check that out of convert is float or std::array - typedef std::array Vec2f; - typedef std::array Vec3f; - typedef std::array Vec4f; + using Vec2f = std::array; + using Vec3f = std::array; + using Vec4f = std::array; static_assert(check_func_return_type(FUNC,float) || check_func_return_type(FUNC,Vec2f) || check_func_return_type(FUNC,Vec3f) ||check_func_return_type(FUNC,Vec4f), "convert output must be float or std::array" ); // set vec dimension @@ -223,7 +223,7 @@ void update_vbo(const ATTR& attr, VBO& vbo, const FUNC& convert) vbo.allocate(nb_chunks * ATTR::CHUNKSIZE, vec_dim); // copy (after conversion) - typedef typename function_traits::result_type OutputConvert; + using OutputConvert = typename function_traits::result_type; OutputConvert* dst = reinterpret_cast(vbo.lock_pointer()); for (unsigned int i = 0; i < nb_chunks; ++i) { @@ -252,11 +252,11 @@ void update_vbo(const ATTR& attr, const ATTR2& attr2, VBO& vbo, const FUNC& conv static_assert(ATTR::orbit_value == ATTR2::orbit_value, "attributes must be on same orbit"); // check that convert param 1 is compatible with attr - typedef typename std::remove_cv< typename std::remove_reference::template arg<0>::type>::type >::type InputConvert; + using InputConvert = typename std::remove_cv< typename std::remove_reference::template arg<0>::type>::type >::type; static_assert(std::is_same::value, "wrong parameter 1"); // check that convert param 2 is compatible with attr2 - typedef typename std::remove_cv< typename std::remove_reference::template arg<1>::type>::type >::type InputConvert2; + using InputConvert2 = typename std::remove_cv< typename std::remove_reference::template arg<1>::type>::type >::type; static_assert(std::is_same::value, "wrong parameter 2"); // get chunk data pointers @@ -270,9 +270,9 @@ void update_vbo(const ATTR& attr, const ATTR2& attr2, VBO& vbo, const FUNC& conv ca2->get_chunks_pointers(chunk_addr2, byte_chunk_size); // check that out of convert is float or std::array - typedef std::array Vec2f; - typedef std::array Vec3f; - typedef std::array Vec4f; + using Vec2f = std::array; + using Vec3f = std::array; + using Vec4f = std::array; static_assert(check_func_return_type(FUNC,float) || check_func_return_type(FUNC,Vec2f) || check_func_return_type(FUNC,Vec3f) ||check_func_return_type(FUNC,Vec4f), "convert output must be float or std::array" ); // set vec dimension @@ -291,7 +291,7 @@ void update_vbo(const ATTR& attr, const ATTR2& attr2, VBO& vbo, const FUNC& conv // copy (after conversion) // out type conversion - typedef typename function_traits::result_type OutputConvert; + using OutputConvert = typename function_traits::result_type; OutputConvert* dst = reinterpret_cast(vbo.lock_pointer()); for (unsigned int i = 0; i < nb_chunks; ++i) { From 76f427fba89be8045eaa482599650c4da5163d58 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Fri, 26 Feb 2016 17:32:35 +0100 Subject: [PATCH 193/402] aa bold lines --- cgogn/rendering/shaders/shader_bold_line.cpp | 116 ++++++++++++------- cgogn/rendering/shaders/shader_bold_line.h | 2 +- 2 files changed, 74 insertions(+), 44 deletions(-) diff --git a/cgogn/rendering/shaders/shader_bold_line.cpp b/cgogn/rendering/shaders/shader_bold_line.cpp index c4833824..1a292cbb 100644 --- a/cgogn/rendering/shaders/shader_bold_line.cpp +++ b/cgogn/rendering/shaders/shader_bold_line.cpp @@ -44,9 +44,13 @@ const char* ShaderBoldLine::vertex_shader_source_ = const char* ShaderBoldLine::geometry_shader_source_ = "#version 150\n" +"layout (lines) in;\n" +"layout (triangle_strip, max_vertices=6) out;\n" +"out vec4 color_f;\n" "uniform mat4 projection_matrix;\n" "uniform mat4 model_view_matrix;\n" "uniform vec2 lineWidths;\n" +"uniform vec4 lineColor;\n" "void main()\n" "{\n" " vec4 A = model_view_matrix * gl_in[0].gl_Position;\n" @@ -66,20 +70,27 @@ const char* ShaderBoldLine::geometry_shader_source_ = " B = B/B.w;\n" " vec2 U2 = normalize(vec2(lineWidths[1],lineWidths[0])*(B.xy - A.xy));\n" " vec2 LWCorr =lineWidths * max(abs(U2.x),abs(U2.y));\n" -" vec3 U = vec3(LWCorr*U2,0.0);\n" +" vec3 U = vec3(0.5*LWCorr*U2,0.0);\n" " vec3 V = vec3(LWCorr*vec2(U2[1], -U2[0]), 0.0); \n" -" gl_Position = vec4(A.xyz-U, 1.0);\n" -" EmitVertex();\n" -" gl_Position = vec4(A.xyz+V, 1.0);\n" -" EmitVertex();\n" +" vec3 color3 = lineColor.rgb;\n" +" color_f = vec4(color3,0.0);\n" " gl_Position = vec4(A.xyz-V, 1.0);\n" " EmitVertex();\n" -" gl_Position = vec4(B.xyz+V, 1.0);\n" -" EmitVertex();\n" +" color_f = vec4(color3,0.0);\n" " gl_Position = vec4(B.xyz-V, 1.0);\n" " EmitVertex();\n" +" color_f = vec4(color3,1.0);\n" +" gl_Position = vec4(A.xyz-U, 1.0);\n" +" EmitVertex();\n" +" color_f = vec4(color3,1.0);\n" " gl_Position = vec4(B.xyz+U, 1.0);\n" " EmitVertex();\n" +" color_f = vec4(color3,0.0);\n" +" gl_Position = vec4(A.xyz+V, 1.0);\n" +" EmitVertex();\n" +" color_f = vec4(color3,0.0);\n" +" gl_Position = vec4(B.xyz+V, 1.0);\n" +" EmitVertex();\n" " EndPrimitive();\n" " }\n" "}\n"; @@ -87,17 +98,15 @@ const char* ShaderBoldLine::geometry_shader_source_ = const char* ShaderBoldLine::fragment_shader_source_ = "#version 150\n" -"uniform vec4 color;\n" -"out vec3 fragColor;\n" +"in vec4 color_f;\n" +"out vec4 fragColor;\n" "void main() {\n" -" fragColor = color;\n" +" fragColor = color_f;\n" "}\n"; - - const char* ShaderBoldLine::vertex_shader_source2_ = "#version 150\n" "in vec3 vertex_pos;\n" @@ -111,8 +120,10 @@ const char* ShaderBoldLine::vertex_shader_source2_ = const char* ShaderBoldLine::geometry_shader_source2_ = "#version 150\n" +"layout (lines) in;\n" +"layout (triangle_strip, max_vertices=6) out;\n" "in vec3 color_v[];\n" -"out vec3 color_f;\n" +"out vec4 color_f;\n" "uniform mat4 projection_matrix;\n" "uniform mat4 model_view_matrix;\n" "uniform vec2 lineWidths;\n" @@ -137,20 +148,24 @@ const char* ShaderBoldLine::geometry_shader_source2_ = " vec2 LWCorr =lineWidths * max(abs(U2.x),abs(U2.y));\n" " vec3 U = vec3(LWCorr*U2,0.0);\n" " vec3 V = vec3(LWCorr*vec2(U2[1], -U2[0]), 0.0); \n" -" color_f = vcolor[0];\n" -" gl_Position = vec4(A.xyz-U, 1.0);\n" -" EmitVertex();\n" -" gl_Position = vec4(A.xyz+V, 1.0);\n" -" EmitVertex();\n" +" color_f = vec4(color_v[0],0.0);\n" " gl_Position = vec4(A.xyz-V, 1.0);\n" " EmitVertex();\n" -" color_f = vcolor[1];\n" -" gl_Position = vec4(B.xyz+V, 1.0);\n" -" EmitVertex();\n" +" color_f = vec4(color_v[1],0.0);\n" " gl_Position = vec4(B.xyz-V, 1.0);\n" " EmitVertex();\n" +" color_f = vec4(color_v[0],1.0);\n" +" gl_Position = vec4(A.xyz-U, 1.0);\n" +" EmitVertex();\n" +" color_f = vec4(color_v[1],1.0);\n" " gl_Position = vec4(B.xyz+U, 1.0);\n" " EmitVertex();\n" +" color_f = vec4(color_v[0],0.0);\n" +" gl_Position = vec4(A.xyz+V, 1.0);\n" +" EmitVertex();\n" +" color_f = vec4(color_v[1],0.0);\n" +" gl_Position = vec4(B.xyz+V, 1.0);\n" +" EmitVertex();\n" " EndPrimitive();\n" " }\n" "}\n"; @@ -158,37 +173,56 @@ const char* ShaderBoldLine::geometry_shader_source2_ = const char* ShaderBoldLine::fragment_shader_source2_ = "#version 150\n" -"in vec3 color_f;\n" -"out vec3 fragColor;\n" +"in vec4 color_f;\n" +"out vec4 fragColor;\n" "void main() {\n" -" fragColor = color_v;\n" +" fragColor = color_f;\n" "}\n"; -ShaderBoldLine::ShaderBoldLine() +ShaderBoldLine::ShaderBoldLine(bool color_per_vertex) { - prg_.addShaderFromSourceCode(QOpenGLShader::Vertex, vertex_shader_source_); - prg_.addShaderFromSourceCode(QOpenGLShader::Geometry, geometry_shader_source_); - prg_.addShaderFromSourceCode(QOpenGLShader::Fragment, fragment_shader_source_); - prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); - prg_.bindAttributeLocation("vertex_color", ATTRIB_COLOR); - prg_.link(); + if (color_per_vertex) + { + prg_.addShaderFromSourceCode(QOpenGLShader::Vertex, vertex_shader_source2_); + prg_.addShaderFromSourceCode(QOpenGLShader::Geometry, geometry_shader_source2_); + prg_.addShaderFromSourceCode(QOpenGLShader::Fragment, fragment_shader_source2_); + prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); + prg_.bindAttributeLocation("vertex_color", ATTRIB_COLOR); + prg_.link(); + + get_matrices_uniforms(); + unif_width_ = prg_.uniformLocation("lineWidths"); + } + else + { + prg_.addShaderFromSourceCode(QOpenGLShader::Vertex, vertex_shader_source_); + prg_.addShaderFromSourceCode(QOpenGLShader::Geometry, geometry_shader_source_); + prg_.addShaderFromSourceCode(QOpenGLShader::Fragment, fragment_shader_source_); + prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); + prg_.link(); + + get_matrices_uniforms(); + unif_color_ = prg_.uniformLocation("lineColor"); + unif_width_ = prg_.uniformLocation("lineWidths"); + } +} - get_matrices_uniforms(); - unif_color_ = prg_.uniformLocation("color"); - unif_width_ = prg_.uniformLocation("lineWidths"); -} void ShaderBoldLine::set_color(const QColor& rgb) { prg_.setUniformValue(unif_color_, rgb); } -void ShaderBoldLine::set_width(float w) +void ShaderBoldLine::set_width(float wpix) { - prg_.setUniformValue(unif_width_, w); + QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); + int viewport[4]; + ogl->glGetIntegerv(GL_VIEWPORT, viewport); + QSizeF wd(wpix / float(viewport[2]), wpix / float(viewport[3])); + prg_.setUniformValue(unif_width_, wd); } bool ShaderBoldLine::set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color) @@ -212,17 +246,13 @@ bool ShaderBoldLine::set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color) if (vbo_color) { - // normal vbo + // color vbo vbo_color->bind(); ogl->glEnableVertexAttribArray(ATTRIB_COLOR); ogl->glVertexAttribPointer(ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); vbo_color->release(); } - else - { - if (unif_color_ == -1) - std::cerr << "ShaderBoldLine no coloe attribute no color uniform"<< std::endl; - } + vaos_[i]->release(); prg_.release(); diff --git a/cgogn/rendering/shaders/shader_bold_line.h b/cgogn/rendering/shaders/shader_bold_line.h index 6258e1e1..a563cd23 100644 --- a/cgogn/rendering/shaders/shader_bold_line.h +++ b/cgogn/rendering/shaders/shader_bold_line.h @@ -56,7 +56,7 @@ class CGOGN_RENDERING_API ShaderBoldLine : public ShaderProgram public: - ShaderBoldLine(); + ShaderBoldLine(bool color_per_vertex = false); /** * @brief set current color From 481584fc46639aaa6c6f046c603013e63d8e76c7 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Fri, 26 Feb 2016 17:35:08 +0100 Subject: [PATCH 194/402] drawer use bold line --- cgogn/rendering/drawer.cpp | 84 +++++++++++++++++++++++--------------- cgogn/rendering/drawer.h | 7 +++- 2 files changed, 58 insertions(+), 33 deletions(-) diff --git a/cgogn/rendering/drawer.cpp b/cgogn/rendering/drawer.cpp index 8f65cb70..731c74cd 100644 --- a/cgogn/rendering/drawer.cpp +++ b/cgogn/rendering/drawer.cpp @@ -27,6 +27,7 @@ #include #include +#include namespace cgogn { @@ -35,6 +36,7 @@ namespace rendering { ShaderColorPerVertex* Drawer::shader_cpv_= NULL; +ShaderBoldLine* Drawer::shader_bl_= NULL; Drawer::Drawer(QOpenGLFunctions_3_3_Core* ogl33): ogl33_(ogl33), @@ -46,10 +48,17 @@ Drawer::Drawer(QOpenGLFunctions_3_3_Core* ogl33): if (shader_cpv_ == NULL) shader_cpv_ = new ShaderColorPerVertex(); - vao_ = shader_cpv_->add_vao(); shader_cpv_->set_vao(vao_,vbo_pos_,vbo_col_); + if (shader_bl_ == NULL) + shader_bl_ = new ShaderBoldLine(false); + + vao2_ = shader_bl_->add_vao(); + shader_bl_->bind(); + shader_bl_->set_color(QColor(255,255,0,255)); + shader_bl_->release(); + shader_bl_->set_vao(vao2_,vbo_pos_/*,vbo_col_*/); } Drawer::~Drawer() @@ -61,20 +70,36 @@ void Drawer::new_list() { data_pos_.clear(); data_col_.clear(); - begins_.clear(); + begins_point_.clear(); + begins_line_.clear(); + begins_face_.clear(); } void Drawer::begin(GLenum mode) { - if (mode == GL_POINTS) - begins_.push_back(PrimParam(data_pos_.size(), mode, current_size_)); - else - begins_.push_back(PrimParam(data_pos_.size(), mode, 1.0)); + switch (mode) + { + case GL_POINTS: + begins_point_.push_back(PrimParam(data_pos_.size(), mode, current_size_)); + current_begin_ = &begins_point_; + break; + case GL_LINES: + case GL_LINE_STRIP: + case GL_LINE_LOOP: + begins_line_.push_back(PrimParam(data_pos_.size(), mode, current_size_)); + current_begin_ = &begins_line_; + break; + default: + begins_face_.push_back(PrimParam(data_pos_.size(), mode, 1.0f)); + current_begin_ = &begins_face_; + break; + } + } void Drawer::end() { - begins_.back().nb = data_pos_.size() - begins_.back().begin; + current_begin_->back().nb = data_pos_.size() - current_begin_->back().begin; } @@ -124,33 +149,12 @@ void Drawer::end_list() data_pos_.shrink_to_fit(); data_col_.clear(); data_col_.shrink_to_fit(); - - for (const auto& beg : begins_) - { - switch (beg.mode) - { - case GL_POINTS: - begins_point_.push_back(beg); - break; - case GL_LINES: - case GL_LINE_STRIP: - case GL_LINE_LOOP: - begins_line_.push_back(beg); - break; - default: - begins_face_.push_back(beg); - break; - } - } } void Drawer::callList(const QMatrix4x4& projection, const QMatrix4x4& modelview) { // QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); - if (begins_.empty()) - return; - shader_cpv_->bind(); shader_cpv_->set_matrices(projection,modelview); shader_cpv_->bind_vao(vao_); @@ -160,10 +164,6 @@ void Drawer::callList(const QMatrix4x4& projection, const QMatrix4x4& modelview) ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); } - for (auto& pp : begins_line_) - { - ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); - } for (auto& pp : begins_face_) { @@ -173,6 +173,26 @@ void Drawer::callList(const QMatrix4x4& projection, const QMatrix4x4& modelview) shader_cpv_->release_vao(vao_); shader_cpv_->release(); + + shader_bl_->bind(); + shader_bl_->set_matrices(projection,modelview); + shader_bl_->bind_vao(vao2_); + + ogl33_->glEnable(GL_BLEND); + ogl33_->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + for (auto& pp : begins_line_) + { + shader_bl_->set_width(pp.width); + shader_bl_->set_color(QColor(255,255,0)); + ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); + } + ogl33_->glDisable(GL_BLEND); + + shader_bl_->release_vao(vao2_); + shader_bl_->release(); + + } diff --git a/cgogn/rendering/drawer.h b/cgogn/rendering/drawer.h index d391779b..adce1fbe 100644 --- a/cgogn/rendering/drawer.h +++ b/cgogn/rendering/drawer.h @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -55,16 +56,20 @@ class CGOGN_RENDERING_API Drawer//: protected QOpenGLFunctions_3_3_Core VBO* vbo_pos_; VBO* vbo_col_; unsigned int vao_; + unsigned int vao2_; + std::vector data_pos_; std::vector data_col_; - std::vector begins_; std::vector begins_point_; std::vector begins_line_; std::vector begins_face_; + std::vector* current_begin_; + float current_size_; static ShaderColorPerVertex* shader_cpv_; + static ShaderBoldLine* shader_bl_; QOpenGLFunctions_3_3_Core* ogl33_; From 240a4addb707f307da6c033274fed2f3081db7e5 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Fri, 26 Feb 2016 17:52:11 +0100 Subject: [PATCH 195/402] First steps in CMap2Test + new check_map_integrity() method --- cgogn/core/cmap/cmap0.h | 24 +++ cgogn/core/cmap/cmap1.h | 20 +- cgogn/core/cmap/cmap2.h | 24 +++ cgogn/core/cmap/cmap3.h | 24 +++ cgogn/core/cmap/map_base.h | 73 +++++++- cgogn/core/cmap/sanity_check.h | 19 -- cgogn/core/tests/CMakeLists.txt | 4 +- cgogn/core/tests/cmap/cmap0_test.cpp | 6 +- cgogn/core/tests/cmap/cmap0_topo_test.cpp | 92 ++++++++++ cgogn/core/tests/cmap/cmap1_test.cpp | 20 +- cgogn/core/tests/cmap/cmap1_topo_test.cpp | 32 +--- cgogn/core/tests/cmap/cmap2_test.cpp | 97 ++++++++++ cgogn/core/tests/cmap/cmap2_topo_test.cpp | 211 ++++++++++++++++++++++ cgogn/io/examples/cmap2_import.cpp | 8 +- 14 files changed, 583 insertions(+), 71 deletions(-) create mode 100644 cgogn/core/tests/cmap/cmap0_topo_test.cpp create mode 100644 cgogn/core/tests/cmap/cmap2_test.cpp create mode 100644 cgogn/core/tests/cmap/cmap2_topo_test.cpp diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index 3196d48b..ce88cffa 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -76,6 +76,19 @@ class CMap0_T : public MapBase Self& operator=(Self const&) = delete; Self& operator=(Self &&) = delete; + /*! + * \brief Check the integrity of embedding information + */ + inline bool check_embedding_integrity() + { + bool result = true; + + if (this->template is_embedded()) + result = result && this->template is_well_embedded(); + + return result; + } + /******************************************************************************* * Low-level topological operations *******************************************************************************/ @@ -89,6 +102,9 @@ class CMap0_T : public MapBase { } + inline bool check_integrity(Dart d) const { + return true; + } /******************************************************************************* * High-level embedded and topological operations *******************************************************************************/ @@ -127,12 +143,20 @@ class CMap0_T : public MapBase *******************************************************************************/ protected: + template inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const { static_assert(ORBIT == Orbit::DART, "Orbit not supported in a CMap0"); f(c.dart); } + + template + inline void foreach_dart_of_orbit_until(Cell c, const FUNC& f) const + { + static_assert(ORBIT == Orbit::DART, "Orbit not supported in a CMap0"); + f(c.dart); + } }; template diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 87b6b43f..6e7731a7 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -45,7 +45,7 @@ class CMap1_T : public CMap0_T friend class DartMarker_T; friend class cgogn::DartMarkerStore; - using Vertex = Cell; + using Vertex = typename Inherit::Vertex; using Face = Cell; template @@ -92,6 +92,19 @@ class CMap1_T : public CMap0_T Self& operator=(Self const&) = delete; Self& operator=(Self &&) = delete; + /*! + * \brief Check the integrity of embedding information + */ + inline bool check_embedding_integrity() + { + bool result = Inherit::check_embedding_integrity(); + + if (this->template is_embedded()) + result = result && this->template is_well_embedded(); + + return result; + } + /******************************************************************************* * Low-level topological operations *******************************************************************************/ @@ -109,6 +122,11 @@ class CMap1_T : public CMap0_T (*phi_1_)[d.index] = d; } + inline bool check_integrity(Dart d) const { + return (phi1(phi_1(d)) == d && + phi_1(phi1(d)) == d); + } + /*! * \brief Link two darts with the phi1 permutation what either merge or split their orbit(s). * @param d: the first dart diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 2da19fca..ef9c5e21 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -101,6 +101,25 @@ class CMap2_T : public CMap1_T Self& operator=(Self const&) = delete; Self& operator=(Self &&) = delete; + /*! + * \brief Check the integrity of embedding information + */ + inline bool check_embedding_integrity() + { + bool result = Inherit::check_embedding_integrity(); + + if (this->template is_embedded()) + result = result && this->template is_well_embedded(); + + if (this->template is_embedded()) + result = result && this->template is_well_embedded(); + + if (this->template is_embedded()) + result = result && this->template is_well_embedded(); + + return result; + } + /******************************************************************************* * Low-level topological operations *******************************************************************************/ @@ -117,6 +136,11 @@ class CMap2_T : public CMap1_T (*phi2_)[d.index] = d; } + inline bool check_integrity(Dart d) const { + return (Inherit::check_integrity(d) && + phi2(phi2(d)) == d); + } + /** * \brief Link dart d with dart e by the phi2 involution * @param d,e the darts to link diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index acb5ae11..631c08ed 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -104,6 +104,25 @@ class CMap3_T : public CMap2_T Self& operator=(Self const&) = delete; Self& operator=(Self &&) = delete; + /*! + * \brief Check the integrity of embedding information + */ + inline bool check_embedding_integrity() + { + bool result = Inherit::check_embedding_integrity(); + + if (this->template is_embedded()) + result = result && this->template is_well_embedded(); + + if (this->template is_embedded()) + result = result && this->template is_well_embedded(); + + if (this->template is_embedded()) + result = result && this->template is_well_embedded(); + + return result; + } + /******************************************************************************* * Low-level topological operations *******************************************************************************/ @@ -120,6 +139,11 @@ class CMap3_T : public CMap2_T (*phi3_)[d.index] = d; } + inline bool check_integrity(Dart d) const { + return (Inherit::check_integrity(d) && + phi3(phi3(d)) == d); + } + /** * \brief Link dart d with dart e by an involution * @param d,e the darts to link diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index e41f922a..b8150811 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -404,13 +404,84 @@ class MapBase : public MapBaseData result = false; std::map::iterator it; for (auto const& de : emb_set) - std::cout << "\t dart #" << de.second << " has embed index #" << de.first << std::endl; + std::cout << "\t dart #" << de.second << " has embed index #" << de.first << std::endl; std::cout << std::endl; } return result; } + /** + * \brief Tests if all \p ORBIT orbits are well embedded + * \details An orbit is well embedded if all its darts + * have the same embedding (index) + * + * \tparam ORBIT [description] + * \return [description] + */ + template + bool is_well_embedded() + { + static const Orbit ORBIT = CellType::ORBIT; + static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); + cgogn_message_assert(this->template is_embedded(), "Invalid parameter: orbit not embedded"); + + const ConcreteMap* cmap = to_concrete(); + CellMarker marker(*cmap); + bool result = true; + + cmap->foreach_cell_until_dart_marking([&] (CellType c) + { + // insure that two cells do not share the same index + if (marker.is_marked(c)) + { + result = false; + return false; + } + marker.mark(c); + // check used indices are valid + unsigned int idx = this->get_embedding(c); + if (idx == EMBNULL) + { + result = false; + return false; + } + // check all darts of the cell use the same index (and thus not equal to EMBNULL) + cmap->foreach_dart_of_orbit_until(c, [&] (Dart d) + { + if (this->template get_embedding(d) != idx) + result = false; + return result; + }); + + return result; + + }); + return result; + } + + bool check_map_integrity() + { + ConcreteMap* cmap = to_concrete(); + bool result = true; + + foreach_dart_until( [&cmap,&result] (Dart d) { + if (!cmap->check_integrity(d)) result = false; + return result; + }); + if (!result) { + std::cerr << "Integrity of the topology is broken" << std::endl; + return false; + } + + result = cmap->check_embedding_integrity(); + if (!result) { + std::cerr << "Integrity of the embeddings is broken" << std::endl; + return false; + } + return true; + } + /******************************************************************************* * Topo caches management *******************************************************************************/ diff --git a/cgogn/core/cmap/sanity_check.h b/cgogn/core/cmap/sanity_check.h index d6e5fa25..1a846ab2 100644 --- a/cgogn/core/cmap/sanity_check.h +++ b/cgogn/core/cmap/sanity_check.h @@ -27,25 +27,6 @@ namespace cgogn { -/** - * \brief Tests if all \p ORBIT orbits are well embedded - * \details An orbit is well embedded if all its darts - * have the same embedding (index) - * - * \tparam ORBIT [description] - * \return [description] - */ -template -bool is_well_embedded(const MAP& map) -{ - bool result = true; - map.foreach_cell([&] (Cell c) - { - result = map.template is_well_embedded(c); - }); - return result; -} - /** * \brief Tests if each \p ORBIT orbit of the map has a unique index in the \p ORBIT attribute container * \details This is a injectivity test from the darts embedding to the attribute indices diff --git a/cgogn/core/tests/CMakeLists.txt b/cgogn/core/tests/CMakeLists.txt index 1e258273..0fb82863 100644 --- a/cgogn/core/tests/CMakeLists.txt +++ b/cgogn/core/tests/CMakeLists.txt @@ -12,8 +12,8 @@ set(SOURCE_FILES cmap/cmap0_test.cpp cmap/cmap1_topo_test.cpp cmap/cmap1_test.cpp -# cmap/cmap2_topo_test.cpp -# cmap/cmap2_test.cpp + cmap/cmap2_topo_test.cpp + cmap/cmap2_test.cpp utils/name_types_test.cpp diff --git a/cgogn/core/tests/cmap/cmap0_test.cpp b/cgogn/core/tests/cmap/cmap0_test.cpp index e4d76cf9..9c6c35d4 100644 --- a/cgogn/core/tests/cmap/cmap0_test.cpp +++ b/cgogn/core/tests/cmap/cmap0_test.cpp @@ -68,8 +68,7 @@ TEST_F(CMap0Test, testAddVertex) int n = addVertices(); EXPECT_EQ(cmap_.nb_cells(), n); - EXPECT_TRUE(is_well_embedded(cmap_)); - EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); + EXPECT_TRUE(cmap_.check_map_integrity()); } TEST_F(CMap0Test, testRemoveVertex) @@ -86,8 +85,7 @@ TEST_F(CMap0Test, testRemoveVertex) } EXPECT_EQ(cmap_.nb_cells(), countVertex); - EXPECT_TRUE(is_well_embedded(cmap_)); - EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); + EXPECT_TRUE(cmap_.check_map_integrity()); } } // namespace cgogn diff --git a/cgogn/core/tests/cmap/cmap0_topo_test.cpp b/cgogn/core/tests/cmap/cmap0_topo_test.cpp new file mode 100644 index 00000000..d1767be8 --- /dev/null +++ b/cgogn/core/tests/cmap/cmap0_topo_test.cpp @@ -0,0 +1,92 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#include + +#include + +namespace cgogn +{ + +#define NB_MAX 1000 + +class CMap0TopoTest: public ::testing::Test +{ + +public: + + using testCMap0 = CMap0; + using Vertex = testCMap0::Vertex; + +protected: + + testCMap0 cmap_; + + CMap0TopoTest() + { + } + + std::array tdarts_; + + int addVertices() { + for (int i = 0; i < NB_MAX; ++i) + tdarts_[i] = cmap_.add_vertex(); + + return NB_MAX; + } +}; + +TEST_F(CMap0TopoTest, testCMap0Constructor) +{ + EXPECT_EQ(cmap_.nb_darts(), 0u); + EXPECT_EQ(cmap_.nb_cells(), 0u); +} + +TEST_F(CMap0TopoTest, testAddVertex) +{ + int n = addVertices(); + + EXPECT_EQ(cmap_.nb_darts(), n); + EXPECT_EQ(cmap_.nb_cells(), n); + EXPECT_TRUE(cmap_.check_map_integrity()); +} + +TEST_F(CMap0TopoTest, testRemoveVertex) +{ + int n = addVertices(); + + int countVertex = n; + for (int i = 0; i < n; ++i) { + Vertex d = tdarts_[i]; + if (i%2 == 1) { + cmap_.remove_vertex(Vertex(d)); + --countVertex; + } + } + + EXPECT_EQ(cmap_.nb_darts(), countVertex); + EXPECT_EQ(cmap_.nb_cells(), countVertex); + EXPECT_TRUE(cmap_.check_map_integrity()); +} + +} // namespace cgogn diff --git a/cgogn/core/tests/cmap/cmap1_test.cpp b/cgogn/core/tests/cmap/cmap1_test.cpp index 0dce2528..b8d632fe 100644 --- a/cgogn/core/tests/cmap/cmap1_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_test.cpp @@ -85,10 +85,7 @@ TEST_F(CMap1Test, addFace) EXPECT_EQ(cmap_.nb_cells(), n); EXPECT_EQ(cmap_.nb_cells(), NB_MAX); - EXPECT_TRUE(is_well_embedded(cmap_)); - EXPECT_TRUE(is_well_embedded(cmap_)); - EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); - EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); + EXPECT_TRUE(cmap_.check_map_integrity()); } TEST_F(CMap1Test, testSplitVertex) @@ -103,10 +100,7 @@ TEST_F(CMap1Test, testSplitVertex) EXPECT_EQ(cmap_.nb_cells(), n+NB_MAX); EXPECT_EQ(cmap_.nb_cells(), NB_MAX); - EXPECT_TRUE(is_well_embedded(cmap_)); - EXPECT_TRUE(is_well_embedded(cmap_)); - EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); - EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); + EXPECT_TRUE(cmap_.check_map_integrity()); } TEST_F(CMap1Test, testRemoveVertex) @@ -125,10 +119,7 @@ TEST_F(CMap1Test, testRemoveVertex) EXPECT_EQ(cmap_.nb_cells(), countVertex); EXPECT_EQ(cmap_.nb_cells(), countFace); - EXPECT_TRUE(is_well_embedded(cmap_)); - EXPECT_TRUE(is_well_embedded(cmap_)); - EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); - EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); + EXPECT_TRUE(cmap_.check_map_integrity()); } TEST_F(CMap1Test, testRemoveFace) @@ -147,10 +138,7 @@ TEST_F(CMap1Test, testRemoveFace) EXPECT_EQ(cmap_.nb_cells(), countVertex); EXPECT_EQ(cmap_.nb_cells(), countFace); - EXPECT_TRUE(is_well_embedded(cmap_)); - EXPECT_TRUE(is_well_embedded(cmap_)); - EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); - EXPECT_TRUE(is_orbit_embedding_unique(cmap_)); + EXPECT_TRUE(cmap_.check_map_integrity()); } } // namespace cgogn diff --git a/cgogn/core/tests/cmap/cmap1_topo_test.cpp b/cgogn/core/tests/cmap/cmap1_topo_test.cpp index f0e45ba0..264153d1 100644 --- a/cgogn/core/tests/cmap/cmap1_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_topo_test.cpp @@ -56,22 +56,6 @@ class CMap1TopoTest: public CMap1, public ::testing::Test std::srand(static_cast(std::time(0))); } - bool dartIntegrity(Dart d) { - return (phi1(phi_1(d)) == d && - phi_1(phi1(d)) == d); - } - - bool mapIntegrity() { - bool result = true; - foreach_dart_until( [&] (Dart d) { - if (!dartIntegrity(d)) { - result = false; - } - return result; - }); - return result; - } - int randomDarts() { int n = 1 + std::rand() % (NB_MAX-1); for (int i = 0; i < n; ++i) @@ -106,10 +90,9 @@ TEST_F(CMap1TopoTest, testCMap1Constructor) TEST_F(CMap1TopoTest, testAddDart) { int n = randomDarts(); - (*phi1_)[tdarts_[n-1].index] = Dart(1024); EXPECT_EQ(nb_darts(), n); - EXPECT_TRUE(mapIntegrity()); + EXPECT_TRUE(check_map_integrity()); } TEST_F(CMap1TopoTest, testDeleteDart) @@ -125,7 +108,7 @@ TEST_F(CMap1TopoTest, testDeleteDart) } EXPECT_EQ(nb_darts(), count); - EXPECT_TRUE(mapIntegrity()); + EXPECT_TRUE(check_map_integrity()); } TEST_F(CMap1TopoTest, testPhi1SewUnSew) @@ -149,7 +132,7 @@ TEST_F(CMap1TopoTest, testPhi1SewUnSew) } EXPECT_EQ(nb_darts(), n); - EXPECT_TRUE(mapIntegrity()); + EXPECT_TRUE(check_map_integrity()); } TEST_F(CMap1TopoTest, testAddFace) @@ -158,7 +141,7 @@ TEST_F(CMap1TopoTest, testAddFace) EXPECT_EQ(this->template nb_cells(), n); EXPECT_EQ(this->template nb_cells(), NB_MAX); - EXPECT_TRUE(mapIntegrity()); + EXPECT_TRUE(check_map_integrity()); } TEST_F(CMap1TopoTest, testSplitVertex) @@ -174,7 +157,7 @@ TEST_F(CMap1TopoTest, testSplitVertex) EXPECT_EQ(this->template nb_cells(), n+NB_MAX); EXPECT_EQ(this->template nb_cells(), NB_MAX); - EXPECT_TRUE(mapIntegrity()); + EXPECT_TRUE(check_map_integrity()); } TEST_F(CMap1TopoTest, testRemoveVertex) @@ -201,7 +184,7 @@ TEST_F(CMap1TopoTest, testRemoveVertex) EXPECT_EQ(this->template nb_cells(), countVertex); EXPECT_EQ(this->template nb_cells(), countFace); - EXPECT_TRUE(mapIntegrity()); + EXPECT_TRUE(check_map_integrity()); } TEST_F(CMap1TopoTest, testRemoveFace) @@ -220,7 +203,7 @@ TEST_F(CMap1TopoTest, testRemoveFace) EXPECT_EQ(this->template nb_cells(), countVertex); EXPECT_EQ(this->template nb_cells(), countFace); - EXPECT_TRUE(mapIntegrity()); + EXPECT_TRUE(check_map_integrity()); } TEST_F(CMap1TopoTest, testReverseFace) @@ -246,6 +229,7 @@ TEST_F(CMap1TopoTest, testReverseFace) }); EXPECT_TRUE(face_darts.empty()); } + EXPECT_TRUE(check_map_integrity()); } TEST_F(CMap1TopoTest, testDegree) diff --git a/cgogn/core/tests/cmap/cmap2_test.cpp b/cgogn/core/tests/cmap/cmap2_test.cpp new file mode 100644 index 00000000..e199268f --- /dev/null +++ b/cgogn/core/tests/cmap/cmap2_test.cpp @@ -0,0 +1,97 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#include +#include + +#include + +#include +#include + +namespace cgogn +{ + +#define NB_MAX 1000 + +class CMap2Test: public ::testing::Test +{ + +public: + + using testCMap2 = CMap2; + using Vertex = testCMap2::Vertex; + using Edge = testCMap2::Edge; + using Face = testCMap2::Face; + using Volume = testCMap2::Volume; + +protected: + + testCMap2 cmap_; + + CMap2Test() + { + std::srand(static_cast(std::time(0))); + + cmap_.add_attribute("vertices"); + cmap_.add_attribute("faces"); + } + + int randomFaces() { + int count = 0; + for (int i = 0; i < NB_MAX; ++i) { + int n = 1 + std::rand() % 100; + Dart d = cmap_.add_face(n); + count += n; + + while (std::rand()%10 != 1) + d = cmap_.phi1(d); + + tdarts_[i] = d; + } + return count; + } + + std::array tdarts_; +}; + +TEST_F(CMap2Test, testCMap2Constructor) +{ + EXPECT_EQ(cmap_.nb_cells(), 0u); + EXPECT_EQ(cmap_.nb_cells(), 0u); + EXPECT_EQ(cmap_.nb_cells(), 0u); + EXPECT_EQ(cmap_.nb_cells(), 0u); +} + +TEST_F(CMap2Test, addFace) +{ + int n = randomFaces(); + + EXPECT_EQ(cmap_.nb_cells(), n); + EXPECT_EQ(cmap_.nb_cells(), n); + EXPECT_EQ(cmap_.nb_cells(), 2*NB_MAX); + EXPECT_EQ(cmap_.nb_cells(), NB_MAX); + EXPECT_TRUE(cmap_.check_map_integrity()); +} + +} // namespace cgogn diff --git a/cgogn/core/tests/cmap/cmap2_topo_test.cpp b/cgogn/core/tests/cmap/cmap2_topo_test.cpp new file mode 100644 index 00000000..00b886a2 --- /dev/null +++ b/cgogn/core/tests/cmap/cmap2_topo_test.cpp @@ -0,0 +1,211 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#include +#include + +#include + +#include + +namespace cgogn +{ + +#define NB_MAX 1000 + +class CMap2TopoTest: public CMap2, public ::testing::Test +{ + +public: + + using Vertex = CMap2TopoTest::Vertex; + using Face = CMap2TopoTest::Face; + +protected: + + /*! + * \brief An array of randomly genrated darts on which the methods are tested. + */ + std::array tdarts_; + + /*! + * \brief Generate a random set of faces. + */ + CMap2TopoTest() + { + std::srand(static_cast(std::time(0))); + } + + int randomDarts() { + int n = 1 + std::rand() % (NB_MAX-1); + for (int i = 0; i < n; ++i) + tdarts_[i] = add_dart(); + + return n; + } + + int randomFaces() { + int count = 0; + for (int i = 0; i < NB_MAX; ++i) { + int n = 1 + std::rand() % 100; + Dart d = add_face_topo(n); + count += n; + + while (std::rand()%10 != 1) + d = phi1(d); + + tdarts_[i] = d; + } + return count; + } +}; + +TEST_F(CMap2TopoTest, testCMap2Constructor) +{ + EXPECT_EQ(nb_darts(), 0u); + EXPECT_EQ(this->template nb_cells(), 0u); + EXPECT_EQ(this->template nb_cells(), 0u); + EXPECT_EQ(this->template nb_cells(), 0u); + EXPECT_EQ(this->template nb_cells(), 0u); +} + +TEST_F(CMap2TopoTest, testAddDart) +{ + int n = randomDarts(); + + EXPECT_EQ(nb_darts(), n); + EXPECT_TRUE(check_map_integrity()); +} + +TEST_F(CMap2TopoTest, testDeleteDart) +{ + int n = randomDarts(); + + int count = n; + for (int i = 0; i < n; ++i) { + if (std::rand() % 3 == 1) { + remove_dart(tdarts_[i]); + --count; + } + } + + EXPECT_EQ(nb_darts(), count); + EXPECT_TRUE(check_map_integrity()); +} + +TEST_F(CMap2TopoTest, testPhi2SewUnSew) +{ + int n = randomDarts(); + + for (int i = 0; i < 1000; ++i) { + Dart d0 = tdarts_[std::rand() % n]; + Dart d2 = phi2(d0); + if (d0 != d2) { + phi2_unsew(d0); + EXPECT_FALSE(phi2(d0) == d2); + EXPECT_TRUE(phi2(d0) == d0); + EXPECT_TRUE(phi2(d2) == d2); + } + Dart e0 = d0; + while (e0 == d0) e0 = tdarts_[std::rand() % n]; + EXPECT_FALSE(d0 == e0); + phi2_unsew(e0); + EXPECT_TRUE(phi2(e0) == e0); + + phi2_sew(d0,e0); + EXPECT_TRUE(phi2(d0) == e0); + EXPECT_TRUE(phi2(e0) == d0); + } + + EXPECT_EQ(nb_darts(), n); + EXPECT_TRUE(check_map_integrity()); +} + +TEST_F(CMap2TopoTest, testAddFace) +{ + int n = randomFaces(); + + EXPECT_EQ(this->template nb_cells(), n); + EXPECT_EQ(this->template nb_cells(), n); + EXPECT_EQ(this->template nb_cells(), 2*NB_MAX); + EXPECT_EQ(this->template nb_cells(), NB_MAX); + EXPECT_TRUE(check_map_integrity()); +} + +TEST_F(CMap2TopoTest, testCutEdge) +{ + int n = randomFaces(); + + for (int i = 0; i < NB_MAX; ++i) { + Dart d = tdarts_[i]; + unsigned int k = degree(Face(d)); + cut_edge_topo(d); + EXPECT_EQ(degree(Face(d)), k+1); + } + + EXPECT_EQ(this->template nb_cells(), n+NB_MAX); + EXPECT_EQ(this->template nb_cells(), n+NB_MAX); + EXPECT_EQ(this->template nb_cells(), 2*NB_MAX); + EXPECT_EQ(this->template nb_cells(), NB_MAX); + EXPECT_TRUE(check_map_integrity()); +} + +TEST_F(CMap2TopoTest, testCutFace) +{ + int n = randomFaces(); + + int countEdges = n; + int countFaces = 2*NB_MAX; + + for (int i = 0; i < NB_MAX; ++i) { + Dart d = tdarts_[i]; + Dart e = d; + while (std::rand()%10 != 1) e = phi1(e); + if (e == d) e = phi1(e); + + unsigned int k = degree(Face(d)); + if (k>1) { + cut_face_topo(d, e); + ++countEdges; + ++countFaces; + EXPECT_EQ(degree(Face(d))+degree(Face(e)), k+2); + } + } + + EXPECT_EQ(this->template nb_cells(), n); + EXPECT_EQ(this->template nb_cells(), countEdges); + EXPECT_EQ(this->template nb_cells(), countFaces); + EXPECT_EQ(this->template nb_cells(), NB_MAX); + EXPECT_TRUE(check_map_integrity()); +} + +TEST_F(CMap2TopoTest, testFaceDegree) +{ + Face f = this->add_face_topo(10); + + EXPECT_EQ(degree(f),10); +} + +// The traversal methods are tested through the nb_cells calls and wihtin other methods + +} // namespace cgogn diff --git a/cgogn/io/examples/cmap2_import.cpp b/cgogn/io/examples/cmap2_import.cpp index 70b8eb27..d3385c83 100644 --- a/cgogn/io/examples/cmap2_import.cpp +++ b/cgogn/io/examples/cmap2_import.cpp @@ -70,11 +70,11 @@ int main(int argc, char** argv) map.enable_topo_cache(); - std::cout << "Vertex orbits are well embedded ? -> " << std::boolalpha << cgogn::is_well_embedded(map) << std::endl; - std::cout << "Face orbits are well embedded ? -> " << std::boolalpha << cgogn::is_well_embedded(map) << std::endl; +// std::cout << "Vertex orbits are well embedded ? -> " << std::boolalpha << cgogn::is_well_embedded(map) << std::endl; +// std::cout << "Face orbits are well embedded ? -> " << std::boolalpha << cgogn::is_well_embedded(map) << std::endl; - std::cout << "Vertex orbit is uniquely embedded ? -> " << std::boolalpha << cgogn::is_orbit_embedding_unique(map) << std::endl; - std::cout << "Face orbit is uniquely embedded ? -> " << std::boolalpha << cgogn::is_orbit_embedding_unique(map) << std::endl; +// std::cout << "Vertex orbit is uniquely embedded ? -> " << std::boolalpha << cgogn::is_orbit_embedding_unique(map) << std::endl; +// std::cout << "Face orbit is uniquely embedded ? -> " << std::boolalpha << cgogn::is_orbit_embedding_unique(map) << std::endl; std::cout << "Vertex container is well referenced ? -> " << std::boolalpha << cgogn::is_container_well_referenced(map) << std::endl; std::cout << "Face container is well referenced ? -> " << std::boolalpha << cgogn::is_container_well_referenced(map) << std::endl; From 4789361dfa405c04587166146f6be604f037df45 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Fri, 26 Feb 2016 18:08:23 +0100 Subject: [PATCH 196/402] Duplication of code in check_embedding_integrity() to avoid confusion --- cgogn/core/cmap/cmap1.h | 5 ++++- cgogn/core/cmap/cmap2.h | 8 +++++++- cgogn/core/cmap/cmap3.h | 23 +++++++++++++++++++---- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 6e7731a7..4357056a 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -97,7 +97,10 @@ class CMap1_T : public CMap0_T */ inline bool check_embedding_integrity() { - bool result = Inherit::check_embedding_integrity(); + bool result = true; + + if (this->template is_embedded()) + result = result && this->template is_well_embedded(); if (this->template is_embedded()) result = result && this->template is_well_embedded(); diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index ef9c5e21..64f36136 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -106,7 +106,10 @@ class CMap2_T : public CMap1_T */ inline bool check_embedding_integrity() { - bool result = Inherit::check_embedding_integrity(); + bool result = true; + + if (this->template is_embedded()) + result = result && this->template is_well_embedded(); if (this->template is_embedded()) result = result && this->template is_well_embedded(); @@ -114,6 +117,9 @@ class CMap2_T : public CMap1_T if (this->template is_embedded()) result = result && this->template is_well_embedded(); + if (this->template is_embedded()) + result = result && this->template is_well_embedded(); + if (this->template is_embedded()) result = result && this->template is_well_embedded(); diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 631c08ed..6538b270 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -50,13 +50,13 @@ class CMap3_T : public CMap2_T friend class cgogn::DartMarkerStore; using CDart = typename Inherit::CDart; + using Vertex2 = typename Inherit::Vertex; using Vertex = Cell; + using Edge2 = typename Inherit::Edge; using Edge = Cell; + using Face2 = typename Inherit::Face; using Face = Cell; using Volume = typename Inherit::Volume; - using Vertex2 = typename Inherit::Vertex; - using Edge2 = typename Inherit::Edge; - using Face2 = typename Inherit::Face; template using ChunkArray = typename Inherit::template ChunkArray; @@ -109,17 +109,32 @@ class CMap3_T : public CMap2_T */ inline bool check_embedding_integrity() { - bool result = Inherit::check_embedding_integrity(); + bool result = true; + + if (this->template is_embedded()) + result = result && this->template is_well_embedded(); + + if (this->template is_embedded()) + result = result && this->template is_well_embedded(); if (this->template is_embedded()) result = result && this->template is_well_embedded(); + if (this->template is_embedded()) + result = result && this->template is_well_embedded(); + if (this->template is_embedded()) result = result && this->template is_well_embedded(); + if (this->template is_embedded()) + result = result && this->template is_well_embedded(); + if (this->template is_embedded()) result = result && this->template is_well_embedded(); + if (this->template is_embedded()) + result = result && this->template is_well_embedded(); + return result; } From 7049e4f6a46592af7fbc132b23f601a133110e42 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Fri, 26 Feb 2016 18:13:09 +0100 Subject: [PATCH 197/402] Complete check_integrity(Dart) in CMap3 --- cgogn/core/cmap/cmap3.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 6538b270..0582bc97 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -156,7 +156,8 @@ class CMap3_T : public CMap2_T inline bool check_integrity(Dart d) const { return (Inherit::check_integrity(d) && - phi3(phi3(d)) == d); + phi3(phi3(d)) == d && + phi3(this->phi1(phi3(this->phi1(d)))) == d); } /** From 13d50e39ab80767cd6d2a111af70a8f3be9e8c01 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Fri, 26 Feb 2016 18:23:33 +0100 Subject: [PATCH 198/402] Go Home --- cgogn/core/tests/cmap/cmap0_test.cpp | 18 ++++++++++-------- cgogn/core/tests/cmap/cmap0_topo_test.cpp | 20 ++++++++++---------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/cgogn/core/tests/cmap/cmap0_test.cpp b/cgogn/core/tests/cmap/cmap0_test.cpp index 9c6c35d4..d39f8f1a 100644 --- a/cgogn/core/tests/cmap/cmap0_test.cpp +++ b/cgogn/core/tests/cmap/cmap0_test.cpp @@ -29,7 +29,7 @@ namespace cgogn { -#define NB_MAX 1000 +#define NB_MAX 100 class CMap0Test: public ::testing::Test { @@ -65,9 +65,11 @@ TEST_F(CMap0Test, testCMap0Constructor) TEST_F(CMap0Test, testAddVertex) { - int n = addVertices(); - - EXPECT_EQ(cmap_.nb_cells(), n); + for (int i = 1; i< NB_MAX; ++i) { + cmap_.add_vertex(); + EXPECT_EQ(cmap_.nb_darts(), i); + EXPECT_EQ(cmap_.nb_cells(), i); + } EXPECT_TRUE(cmap_.check_map_integrity()); } @@ -75,16 +77,16 @@ TEST_F(CMap0Test, testRemoveVertex) { int n = addVertices(); - int countVertex = n; + int countVertices = n; for (int i = 0; i < n; ++i) { Vertex d = tdarts_[i]; if (i%2 == 1) { cmap_.remove_vertex(Vertex(d)); - --countVertex; + --countVertices; + EXPECT_EQ(cmap_.nb_darts(), countVertices); + EXPECT_EQ(cmap_.nb_cells(), countVertices); } } - - EXPECT_EQ(cmap_.nb_cells(), countVertex); EXPECT_TRUE(cmap_.check_map_integrity()); } diff --git a/cgogn/core/tests/cmap/cmap0_topo_test.cpp b/cgogn/core/tests/cmap/cmap0_topo_test.cpp index d1767be8..7b951727 100644 --- a/cgogn/core/tests/cmap/cmap0_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap0_topo_test.cpp @@ -28,7 +28,7 @@ namespace cgogn { -#define NB_MAX 1000 +#define NB_MAX 100 class CMap0TopoTest: public ::testing::Test { @@ -64,10 +64,11 @@ TEST_F(CMap0TopoTest, testCMap0Constructor) TEST_F(CMap0TopoTest, testAddVertex) { - int n = addVertices(); - - EXPECT_EQ(cmap_.nb_darts(), n); - EXPECT_EQ(cmap_.nb_cells(), n); + for (int i = 1; i< NB_MAX; ++i) { + cmap_.add_vertex(); + EXPECT_EQ(cmap_.nb_darts(), i); + EXPECT_EQ(cmap_.nb_cells(), i); + } EXPECT_TRUE(cmap_.check_map_integrity()); } @@ -75,17 +76,16 @@ TEST_F(CMap0TopoTest, testRemoveVertex) { int n = addVertices(); - int countVertex = n; + int countVertices = n; for (int i = 0; i < n; ++i) { Vertex d = tdarts_[i]; if (i%2 == 1) { cmap_.remove_vertex(Vertex(d)); - --countVertex; + --countVertices; + EXPECT_EQ(cmap_.nb_darts(), countVertices); + EXPECT_EQ(cmap_.nb_cells(), countVertices); } } - - EXPECT_EQ(cmap_.nb_darts(), countVertex); - EXPECT_EQ(cmap_.nb_cells(), countVertex); EXPECT_TRUE(cmap_.check_map_integrity()); } From 7297ba51d2bf8b2fae61855e4bb79748e05334e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Fri, 26 Feb 2016 18:50:43 +0100 Subject: [PATCH 199/402] Moved star_convex.off to meshes/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- data/{ => meshes}/star_convex.off | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename data/{ => meshes}/star_convex.off (100%) diff --git a/data/star_convex.off b/data/meshes/star_convex.off similarity index 100% rename from data/star_convex.off rename to data/meshes/star_convex.off From 518d3e729b3b15472817fc5c58e090b3d237bcaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Fri, 26 Feb 2016 18:53:33 +0100 Subject: [PATCH 200/402] Added some legacy vtk meshes (unstructured grids). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- data/meshes/OneQuadLegacyUgrid.vtk | 13 +++++++++++ data/meshes/TwoQuadsLegacyUgrid.vtk | 17 ++++++++++++++ .../TwoQuadsOneTriangleStripLegacyUgrid.vtk | 23 +++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 data/meshes/OneQuadLegacyUgrid.vtk create mode 100644 data/meshes/TwoQuadsLegacyUgrid.vtk create mode 100644 data/meshes/TwoQuadsOneTriangleStripLegacyUgrid.vtk diff --git a/data/meshes/OneQuadLegacyUgrid.vtk b/data/meshes/OneQuadLegacyUgrid.vtk new file mode 100644 index 00000000..5244a521 --- /dev/null +++ b/data/meshes/OneQuadLegacyUgrid.vtk @@ -0,0 +1,13 @@ +# vtk DataFile Version 3.0 +vtk output +ASCII +DATASET UNSTRUCTURED_GRID +POINTS 4 float +0 0 0 +1 0 0 +0 1 0 +1.1 3.1 0 +CELLS 1 5 +4 0 1 3 2 +CELL_TYPES 1 +9 diff --git a/data/meshes/TwoQuadsLegacyUgrid.vtk b/data/meshes/TwoQuadsLegacyUgrid.vtk new file mode 100644 index 00000000..2c0dba53 --- /dev/null +++ b/data/meshes/TwoQuadsLegacyUgrid.vtk @@ -0,0 +1,17 @@ +# vtk DataFile Version 3.0 +vtk output +ASCII +DATASET UNSTRUCTURED_GRID +POINTS 6 float +0 0 0 +1 0 0 +0 1 0 +1.1 3.1 0 +2 0 0 +2 5 0 +CELLS 2 10 +4 0 1 3 2 +4 3 1 4 5 +CELL_TYPES 2 +9 +9 diff --git a/data/meshes/TwoQuadsOneTriangleStripLegacyUgrid.vtk b/data/meshes/TwoQuadsOneTriangleStripLegacyUgrid.vtk new file mode 100644 index 00000000..5619f52d --- /dev/null +++ b/data/meshes/TwoQuadsOneTriangleStripLegacyUgrid.vtk @@ -0,0 +1,23 @@ +# vtk DataFile Version 3.0 +vtk output +ASCII +DATASET UNSTRUCTURED_GRID +POINTS 10 float +0 0 0 +1 0 0 +0 1 0 +1.1 3.1 0 +2 0 0 +2 5 0 +3 0 0 +3 5 0 +4 0 0 +4 5 0 +CELLS 3 17 +4 0 1 3 2 +4 3 1 4 5 +6 4 5 6 7 8 9 +CELL_TYPES 3 +9 +9 +6 From 4970d517b1d3c7019d39b29e298a44146b7d7238 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Fri, 26 Feb 2016 18:54:31 +0100 Subject: [PATCH 201/402] added swap_endianness. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added functions to change the endianness of floating point numbers. Signed-off-by: Étienne Schmitt --- cgogn/core/utils/endian.h | 65 +++++++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/cgogn/core/utils/endian.h b/cgogn/core/utils/endian.h index b4380bb8..289d5e55 100644 --- a/cgogn/core/utils/endian.h +++ b/cgogn/core/utils/endian.h @@ -61,41 +61,74 @@ inline std::uint64_t swap_endianness64(std::uint64_t x) ((x << 40) & 0x00FF000000000000) | ((x << 56) & 0xFF00000000000000); } -template -inline UINT swap_endianness_if(UINT x) +inline float swap_endianness_float(float x) { - static_assert(std::is_same::value || - std::is_same::value || - std::is_same::value, "This function is specialized for 16, 32 or 64 bits uints."); + union U32F32 + { + std::uint32_t as_u32; + float as_f32; + } u; + u.as_f32 = x; + u.as_u32 = swap_endianness32(u.as_u32); + return u.as_f32; +} + +inline double swap_endianness_double(double x) +{ + union U64F64 + { + std::uint64_t as_u64; + double as_f64; + } u; + u.as_f64 = x; + u.as_u64 = swap_endianness64(u.as_u64); + return u.as_f64; +} + +template +inline T swap_endianness_if(T x) +{ + static_assert(std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value, "This function is specialized for 16, 32 or 64 bits uints, floats and doubles."); if (COND) { - if (std::is_same::value) + if (std::is_same::value) return swap_endianness16(x); - if (std::is_same::value) + if (std::is_same::value) return swap_endianness32(x); - if (std::is_same::value) + if (std::is_same::value) return swap_endianness64(x); + if (std::is_same::value) + return swap_endianness_float(x); + if (std::is_same::value) + return swap_endianness_double(x); } return x; } } // namespace internal - -template -inline UINT swap_endianness_system_big(UINT x) +template +inline T swap_endianness(T x) { - return internal::swap_endianness_if(x); + return internal::swap_endianness_if(x); } -template -inline UINT swap_endianness_system_little(UINT x) +template +inline T swap_endianness_system_big(T x) { - return internal::swap_endianness_if(x); + return internal::swap_endianness_if(x); } - +template +inline T swap_endianness_system_little(T x) +{ + return internal::swap_endianness_if(x); +} } // namespace cgogn From 772920fcb297b8634aac155ded5914de0c1392a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Fri, 26 Feb 2016 18:56:19 +0100 Subject: [PATCH 202/402] Very beginning of a work to import and export meshes including attributes. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/CMakeLists.txt | 1 + cgogn/io/surface_import.h | 316 +++++++++++++++++++++++++++++++++++--- cgogn/io/vtk_cell_types.h | 56 +++++++ 3 files changed, 349 insertions(+), 24 deletions(-) create mode 100644 cgogn/io/vtk_cell_types.h diff --git a/cgogn/io/CMakeLists.txt b/cgogn/io/CMakeLists.txt index 2a752f71..8a8cc6d2 100644 --- a/cgogn/io/CMakeLists.txt +++ b/cgogn/io/CMakeLists.txt @@ -8,6 +8,7 @@ set(HEADER_FILES map_import.h map_export.h import_ply_data.h + vtk_cell_types.h dll.h ) diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index aeaeb4e8..6b3971a7 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -25,13 +25,21 @@ #define IO_SURFACE_IMPORT_H_ #include +#include +#include +#include #include +#include #include #include #include #include + +#include + #include +#include #include @@ -41,12 +49,138 @@ namespace cgogn namespace io { +inline std::string vtk_data_type_to_cgogn_name_of_type(const std::string& vtk_type_str) +{ + const std::string& data_type = to_lower(vtk_type_str); + if (data_type == "char" || data_type == "int8") + return name_of_type(std::int8_t()); + if (data_type == "unsigned_char" || data_type == "uint8") + return name_of_type(std::uint8_t()); + if (data_type == "short" || data_type == "int16") + return name_of_type(std::int16_t()); + if (data_type == "unsigned_short" || data_type == "uint16") + return name_of_type(std::uint16_t()); + if (data_type == "int" || data_type == "int32") + return name_of_type(std::int32_t()); + if (data_type == "unsigned_int" || data_type == "uint32") + return name_of_type(std::uint32_t()); + if (data_type == "long" || data_type == "int64") + return name_of_type(std::int64_t()); + if (data_type == "unsigned_long" || data_type == "uint64") + return name_of_type(std::uint64_t()); + if (data_type == "float" || data_type == "float32") + return name_of_type(float()); + if (data_type == "double" || data_type == "float64") + return name_of_type(double()); + + std::cerr << "vtk_data_type_to_cgogn_name_of_type : unknown vtk type : " << vtk_type_str << std::endl; + return std::string(); +} + + +template +inline std::unique_ptr> read_n_scalars(std::ifstream& fp, std::size_t n, bool binary, bool big_endian) +{ + using VecT = std::vector; + using VecU = std::vector; + + std::cerr << "read_n_scalars called with T = " << name_of_type(T()) << " and U = " << name_of_type(U()) << std::endl; + std::unique_ptr res = make_unique(); + res->reserve(n); + + std::unique_ptr buffer = make_unique(n); + + if (binary) + { + fp.read(reinterpret_cast(std::addressof(buffer->operator[](0))), n * sizeof(U)); + + if (big_endian != internal::cgogn_is_little_endian) + { + for (auto & x : *buffer) + x = swap_endianness(x); + } + if (fp.eof() || fp.bad()) + buffer->clear(); + + } else { + std::string line; + line.reserve(256); + std::size_t i = 0ul; + for (; i < n && (!fp.eof()) && (!fp.bad()); ) + { + std::getline(fp,line); + std::istringstream line_stream(line); + while (i < n && (line_stream >> buffer->operator[](i))) + ++i; + } + + if (i < n) + buffer->clear(); + } + + if (std::is_same::value) + res.reset(reinterpret_cast(buffer.release())); + else + { + for (auto buffer_it = buffer->begin(), end = buffer->end(); buffer_it != end; ++buffer_it) + res->push_back(*buffer_it); + } + + return res; +} + +template +inline std::unique_ptr> read_n_scalars(std::ifstream& fp, const std::string& type_name, std::size_t n, bool binary, bool big_endian) +{ + using VecT = std::vector; + std::unique_ptr> res; + std::cerr << "read_n_scalars called with type " << type_name << std::endl; + const std::string& type = vtk_data_type_to_cgogn_name_of_type(type_name); + + if (type == name_of_type(float())) + { + std::unique_ptr> scalars(std::move(read_n_scalars(fp,n,binary,big_endian))); + res.reset(reinterpret_cast(scalars.release())); + } + if (type == name_of_type(double())) + { + std::unique_ptr> scalars(std::move(read_n_scalars(fp,n,binary,big_endian))); + res.reset(reinterpret_cast(scalars.release())); + } + + if (type == name_of_type(std::uint32_t())) + { + std::unique_ptr> scalars(std::move(read_n_scalars(fp,n,binary,big_endian))); + res.reset(reinterpret_cast(scalars.release())); + } + + return res; +} + +template +inline std::unique_ptr> read_n_vec(std::ifstream& fp, const std::string& type_name, std::size_t n, bool binary, bool big_endian) +{ + using Scalar = typename geometry::vector_traits::Scalar; + const std::size_t size = geometry::vector_traits::SIZE; + std::unique_ptr> scalars(std::move(read_n_scalars(fp, type_name,n*size,binary,big_endian))); + std::unique_ptr> res = make_unique>(); + res->reserve(n); + for (auto it = scalars->begin(), end = scalars->end() ; it != end;) + { + res->emplace_back(Scalar(*it++), Scalar(*it++), Scalar(*it++)); + } + + return res; +} + + enum SurfaceFileType { SurfaceFileType_UNKNOWN = 0, SurfaceFileType_OFF, SurfaceFileType_OBJ, - SurfaceFileType_PLY + SurfaceFileType_PLY, + SurfaceFileType_VTK_LEGACY }; inline SurfaceFileType get_file_type(const std::string& filename) @@ -58,6 +192,8 @@ inline SurfaceFileType get_file_type(const std::string& filename) return SurfaceFileType_OBJ; if (extension == "ply") return SurfaceFileType_PLY; + if (extension == "vtk") + return SurfaceFileType_VTK_LEGACY; return SurfaceFileType_UNKNOWN; } @@ -93,10 +229,10 @@ class SurfaceImport SurfaceImport() : nb_vertices_(0u) - ,nb_edges_(0u) - ,nb_faces_(0u) - ,faces_nb_edges_() - ,faces_vertex_indices_() + ,nb_edges_(0u) + ,nb_faces_(0u) + ,faces_nb_edges_() + ,faces_vertex_indices_() {} ~SurfaceImport() @@ -138,20 +274,23 @@ class SurfaceImport bool result = false; switch (type) { - case SurfaceFileType_UNKNOWN : - std::cout << "Unknown file type " << filename << std::endl; - result = false; - break; - case SurfaceFileType_OFF : - result = import_OFF(fp); - break; - case SurfaceFileType_OBJ : - result = import_OBJ(fp); - break; - case SurfaceFileType_PLY : - fp.close(); - result = import_ply(filename); - break; + case SurfaceFileType_UNKNOWN : + std::cout << "Unknown file type " << filename << std::endl; + result = false; + break; + case SurfaceFileType_OFF : + result = import_OFF(fp); + break; + case SurfaceFileType_OBJ : + result = import_OBJ(fp); + break; + case SurfaceFileType_VTK_LEGACY : + result = import_vtk_legacy(fp); + break; + case SurfaceFileType_PLY : + fp.close(); + result = import_ply(filename); + break; } @@ -175,7 +314,7 @@ class SurfaceImport mbuild.template swap_chunk_array_container(this->vertex_attributes_); VertexAttributeHandler> darts_per_vertex = - map.template add_attribute, Vertex::ORBIT>("darts_per_vertex"); + map.template add_attribute, Vertex::ORBIT>("darts_per_vertex"); unsigned int faces_vertex_index = 0; std::vector vertices_buffer; @@ -228,8 +367,8 @@ class SurfaceImport bool first_OK = true; for (auto it = next_vertex_darts.begin(); - it != next_vertex_darts.end() && !phi2_found; - ++it) + it != next_vertex_darts.end() && !phi2_found; + ++it) { if (map.get_embedding(Vertex(map.phi1(*it))) == vertex_index) { @@ -468,7 +607,7 @@ class SurfaceImport using Scalar = typename VEC3::Scalar; ChunkArray* position = - vertex_attributes_.template add_attribute("position"); + vertex_attributes_.template add_attribute("position"); std::string line, tag; @@ -583,7 +722,7 @@ class SurfaceImport ChunkArray* color; if (pid.has_colors()) { - color = vertex_attributes_.template add_attribute("color"); + color = vertex_attributes_.template add_attribute("color"); } nb_vertices_ = pid.nb_vertices(); @@ -631,7 +770,136 @@ class SurfaceImport return true; } + template + bool import_vtk_legacy(std::ifstream& fp) + { + enum VTK_TYPE + { + UNKNOWN = 0, + UNSTRUCTURED_GRID, + POLYDATA + }; + + VTK_TYPE vtk_type(VTK_TYPE::UNKNOWN); + + std::cerr << "Opening a vtk file" << std::endl; + using Scalar = typename VEC3::Scalar; + std::string line; + std::string word; + line.reserve(512); + word.reserve(128); + + // printing the 2 first lines + std::getline(fp, line); + std::cout << line << std::endl; + std::getline(fp, line); + std::cout << line << std::endl; + + fp >> word; + bool ascii_file = to_upper(word) == "ASCII"; + cgogn_assert(ascii_file || to_upper(word) == "BINARY"); + + fp >> word; + cgogn_assert(to_upper(word) == "DATASET"); + fp >> word; + const std::string& dataset = to_upper(word); + if (dataset == "UNSTRUCTURED_GRID") + vtk_type = VTK_TYPE::UNSTRUCTURED_GRID; + else { + if (dataset == "POLYDATA") + vtk_type = VTK_TYPE::POLYDATA; + } + + std::unique_ptr> cells; + std::unique_ptr> cell_types; + ChunkArray* position = vertex_attributes_.template add_attribute("position"); + std::vector verticesID; + + if (vtk_type == VTK_TYPE::UNSTRUCTURED_GRID) + { + while(!fp.eof()) + { + std::getline(fp,line); + word.clear(); + std::istringstream sstream(line); + sstream >> word; + if (to_upper(word) == "POINTS") + { + std::string type_str; + sstream >> this->nb_vertices_ >> type_str; + type_str = to_lower(type_str); + std::cout << nb_vertices_ << " points" << " of type " << type_str << std::endl; + verticesID.reserve(nb_vertices_); + std::unique_ptr> pos(std::move(read_n_scalars(fp, type_str, 3*nb_vertices_, !ascii_file, false /*don't deal with endianness yet*/))); + cgogn_assert(pos); + for (std::size_t i = 0ul ; i < 3ul*nb_vertices_ ; i+=3ul) + { + VEC3 P(Scalar((*pos)[i]), Scalar((*pos)[i+1ul]), Scalar((*pos)[i+2ul])); + std::cout << P[0] << " " << P[1] << " " << P[2] << std::endl; + unsigned int id = vertex_attributes_.template insert_lines<1>(); + position->operator [](id) = P; + verticesID.push_back(id); + } + } + + if (to_upper(word) == "CELLS") + { + std::cerr << line << std::endl; + unsigned int size; + sstream >> this->nb_faces_ >> size; + std::cerr << "nb cells " << nb_faces_ << " and size " << size << std::endl; + cells = std::move(read_n_scalars(fp, "unsigned_int", size, !ascii_file, false)); + std::size_t i = 0ul; + } + + if (to_upper(word) == "CELL_TYPES") + { + std::cerr << line << std::endl; + unsigned int nbc; + sstream >> nbc; + std::cerr << "nb cells " << nbc << std::endl; + cell_types = std::move(read_n_scalars(fp, "unsigned_int", nbc, !ascii_file, false)); + } + } + } + + auto cell_type_it = cell_types->begin(); + for (auto cell_it = cells->begin(), end = cells->end(); cell_it != end ; ++cell_type_it) + { + const std::size_t nb_vert = *cell_it++; + + if ((*cell_type_it) != VTK_CELL_TYPES::VTK_TRIANGLE_STRIP) + { + faces_nb_edges_.push_back(nb_vert); + for (std::size_t i = 0ul ; i < nb_vert;++i) + { + faces_vertex_indices_.push_back(*cell_it++); + } + } else { + std::vector vertexIDS; + vertexIDS.reserve(nb_vert); + for (std::size_t i = 0ul ; i < nb_vert;++i) + { + vertexIDS.push_back(*cell_it++); + } + + for (unsigned int i = 0u ; i < nb_vert -2u; ++i) + { + if (i != 0u) + ++nb_faces_; + faces_nb_edges_.push_back(3); + faces_vertex_indices_.push_back(vertexIDS[i]); + faces_vertex_indices_.push_back(vertexIDS[i+1]); + faces_vertex_indices_.push_back(vertexIDS[i+2]); + if (i % 2u == 0u) + std::swap(faces_vertex_indices_.back(), *(faces_vertex_indices_.end()-2)); + } + } + } + + return true; + } }; #if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_SURFACE_IMPORT_CPP_)) diff --git a/cgogn/io/vtk_cell_types.h b/cgogn/io/vtk_cell_types.h new file mode 100644 index 00000000..3cacbff3 --- /dev/null +++ b/cgogn/io/vtk_cell_types.h @@ -0,0 +1,56 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef IO_VTK_CELL_TYPES_H_ +#define IO_VTK_CELL_TYPES_H_ + +namespace cgogn +{ + +enum VTK_CELL_TYPES +{ + VTK_VERTEX = 1, + VTK_POLY_VERTEX = 2, + VTK_LINE = 3, + VTK_POLY_LINE = 4, + VTK_TRIANGLE = 5, + VTK_TRIANGLE_STRIP = 6, + VTK_POLYGON = 7, + VTK_PIXEL = 8, + VTK_QUAD = 9, + + VTK_TETRA = 10, + VTK_VOXEL = 11, + VTK_HEXAHEDRON = 12, + VTK_WEDGE = 13, + VTK_PYRAMID = 14, + + VTK_QUADRATIC_EDGE = 21, + VTK_QUADRATIC_TRIANGLE = 22, + VTK_QUADRATIC_QUAD = 23, + VTK_QUADRATIC_TETRA = 24, + VTK_QUADRATIC_HEXAHEDRON = 25 +}; + +} // namespace cgogn +#endif // IO_VTK_CELL_TYPES_H_ From de3598d76cb50c424bd12fd84340b367662765cb Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Sat, 27 Feb 2016 15:50:01 +0100 Subject: [PATCH 203/402] using TYPED_TEST in geometry tests. Signed-off-by: Etienne Schmitt --- cgogn/geometry/algos/normal.h | 5 +- cgogn/geometry/tests/algos/algos_test.cpp | 297 +++++-------- cgogn/geometry/tests/functions/area_test.cpp | 37 +- .../geometry/tests/functions/normal_test.cpp | 65 ++- .../tests/types/bounding_box_test.cpp | 129 +++--- cgogn/geometry/tests/types/plane_3d_test.cpp | 79 ++-- cgogn/geometry/tests/types/vec_test.cpp | 397 +++++++----------- 7 files changed, 388 insertions(+), 621 deletions(-) diff --git a/cgogn/geometry/algos/normal.h b/cgogn/geometry/algos/normal.h index 453b49c3..9625b6d4 100644 --- a/cgogn/geometry/algos/normal.h +++ b/cgogn/geometry/algos/normal.h @@ -30,7 +30,7 @@ #include #include #include - +#include namespace cgogn { @@ -53,7 +53,8 @@ inline VEC3 triangle_normal(const MAP& map, Cell f, const typename template inline VEC3 newell_normal(const MAP& map, Cell f, const typename MAP::template VertexAttributeHandler& position) { - VEC3 n{0.,0.,0.}; + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + VEC3 n{Scalar(0), Scalar(0), Scalar(0)}; map.foreach_incident_vertex(f, [&] (Cell v) { const VEC3& p = position[v.dart]; diff --git a/cgogn/geometry/tests/algos/algos_test.cpp b/cgogn/geometry/tests/algos/algos_test.cpp index 7e6c0041..34c60c19 100644 --- a/cgogn/geometry/tests/algos/algos_test.cpp +++ b/cgogn/geometry/tests/algos/algos_test.cpp @@ -37,235 +37,134 @@ #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) -using StdArray = cgogn::geometry::Vec_T>; +using StdArrayf = cgogn::geometry::Vec_T>; +using StdArrayd = cgogn::geometry::Vec_T>; +using EigenVec3f = Eigen::Vector3f; using EigenVec3d = Eigen::Vector3d; +using VecTypes = testing::Types; using CMap2 = cgogn::CMap2; template using VertexAttributeHandler = CMap2::VertexAttributeHandler; - using Vertex = CMap2::Vertex; using Edge = CMap2::Edge; using Face = CMap2::Face; -TEST(Algos_TEST, TriangleArea) +template +class Algos_TEST : public testing::Test { - { - CMap2 map; - cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); - VertexAttributeHandler vertex_position = map.get_attribute("position"); - const double area = cgogn::geometry::triangle_area(map, *map.begin(), vertex_position); - const double cf_area = cgogn::geometry::convex_face_area(map, *map.begin(), vertex_position); - EXPECT_DOUBLE_EQ(area, 12.5); - EXPECT_DOUBLE_EQ(cf_area, 12.5); - } - { -// CMap2 map; -// cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); -// VertexAttributeHandler vertex_position = map.get_attribute("position"); -// const double area = cgogn::geometry::triangle_area(map, *map.begin(), vertex_position); -// const double cf_area = cgogn::geometry::convex_face_area(map, *map.begin(), vertex_position); -// EXPECT_DOUBLE_EQ(area, 12.5); -// EXPECT_DOUBLE_EQ(cf_area, 12.5); - } -} +protected : + CMap2 map2_; +}; -TEST(Algos_TEST, QuadArea) -{ - { - CMap2 map; - cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); - VertexAttributeHandler vertex_position = map.get_attribute("position"); - const double area = cgogn::geometry::convex_face_area(map, *map.begin(), vertex_position); - EXPECT_DOUBLE_EQ(area, 10); - } - { -// CMap2 map; -// cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); -// VertexAttributeHandler vertex_position = map.get_attribute("position"); -// const double area = cgogn::geometry::convex_face_area(map, *map.begin(), vertex_position); -// EXPECT_DOUBLE_EQ(area, 10); - } -} +TYPED_TEST_CASE(Algos_TEST, VecTypes ); -TEST(Algos_TEST, TriangleCentroid) +TYPED_TEST(Algos_TEST, TriangleArea) { - { - CMap2 map; - cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); - VertexAttributeHandler vertex_position = map.get_attribute("position"); - const StdArray centroid = cgogn::geometry::centroid(map, CMap2::Face(*map.begin()), vertex_position); - EXPECT_DOUBLE_EQ(centroid[0], 5.0/3.0); - EXPECT_DOUBLE_EQ(centroid[1], 5.0/3.0); - EXPECT_DOUBLE_EQ(centroid[2], 0); - } - - { -// CMap2 map; -// cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); -// VertexAttributeHandler vertex_position = map.get_attribute("position"); -// const EigenVec3d centroid = cgogn::geometry::centroid(map, CMap2::Face(*map.begin()), vertex_position); -// EXPECT_DOUBLE_EQ(centroid[0], 5.0/3.0); -// EXPECT_DOUBLE_EQ(centroid[1], 5.0/3.0); -// EXPECT_DOUBLE_EQ(centroid[2], 0); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + cgogn::io::import_surface(this->map2_, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); + VertexAttributeHandler vertex_position = this->map2_.template get_attribute("position"); + const Scalar area = cgogn::geometry::triangle_area(this->map2_, *this->map2_.begin(), vertex_position); + const Scalar cf_area = cgogn::geometry::convex_face_area(this->map2_, *this->map2_.begin(), vertex_position); + EXPECT_DOUBLE_EQ(area, Scalar(12.5f)); + EXPECT_DOUBLE_EQ(cf_area, Scalar(12.5f)); } -TEST(Algos_TEST, QuadCentroid) +TYPED_TEST(Algos_TEST, QuadArea) { - { - CMap2 map; - cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); - VertexAttributeHandler vertex_position = map.get_attribute("position"); - const StdArray centroid = cgogn::geometry::centroid(map, CMap2::Face(*map.begin()), vertex_position); - EXPECT_DOUBLE_EQ(centroid[0], 2.5); - EXPECT_DOUBLE_EQ(centroid[1], 1); - EXPECT_DOUBLE_EQ(centroid[2], 0); - } - - { -// CMap2 map; -// cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); -// VertexAttributeHandler vertex_position = map.get_attribute("position"); -// const EigenVec3d centroid = cgogn::geometry::centroid(map, CMap2::Face(*map.begin()), vertex_position); -// EXPECT_DOUBLE_EQ(centroid[0], 2.5); -// EXPECT_DOUBLE_EQ(centroid[1], 1); -// EXPECT_DOUBLE_EQ(centroid[2], 0); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + cgogn::io::import_surface(this->map2_, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); + VertexAttributeHandler vertex_position = this->map2_.template get_attribute("position"); + const Scalar area = cgogn::geometry::convex_face_area(this->map2_, *this->map2_.begin(), vertex_position); + EXPECT_DOUBLE_EQ(area, Scalar(10)); } -TEST(Algos_TEST, TriangleNormal) +TYPED_TEST(Algos_TEST, TriangleCentroid) { - { - CMap2 map; - cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); - VertexAttributeHandler vertex_position = map.get_attribute("position"); - const StdArray& n1 = cgogn::geometry::triangle_normal(map, CMap2::Face(*map.begin()), vertex_position); - const StdArray& n2 = cgogn::geometry::face_normal(map, CMap2::Face(*map.begin()), vertex_position); - EXPECT_TRUE(cgogn::almost_equal_relative(n1[0], n2[0])); - EXPECT_TRUE(cgogn::almost_equal_relative(n1[1], n2[1])); - EXPECT_TRUE(cgogn::almost_equal_relative(n1[2], n2[2])); + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + cgogn::io::import_surface(this->map2_, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); + VertexAttributeHandler vertex_position = this->map2_.template get_attribute("position"); + const TypeParam centroid = cgogn::geometry::centroid(this->map2_, CMap2::Face(*this->map2_.begin()), vertex_position); + EXPECT_DOUBLE_EQ(centroid[0], Scalar(5)/Scalar(3)); + EXPECT_DOUBLE_EQ(centroid[1], Scalar(5)/Scalar(3)); + EXPECT_DOUBLE_EQ(centroid[2], Scalar(0)); +} - const StdArray& cross = n1.cross(StdArray(0.,0.,1.)); - EXPECT_TRUE(cgogn::almost_equal_relative(cross[0], 0.)); - EXPECT_TRUE(cgogn::almost_equal_relative(cross[1], 0.)); - EXPECT_TRUE(cgogn::almost_equal_relative(cross[2], 0.)); - } - { -// CMap2 map; -// cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); -// VertexAttributeHandler vertex_position = map.get_attribute("position"); -// const EigenVec3d& n1 = cgogn::geometry::triangle_normal(map, CMap2::Face(*map.begin()), vertex_position); -// const EigenVec3d& n2 = cgogn::geometry::face_normal(map, CMap2::Face(*map.begin()), vertex_position); -// EXPECT_TRUE(cgogn::almost_equal_relative(n1[0], n2[0])); -// EXPECT_TRUE(cgogn::almost_equal_relative(n1[1], n2[1])); -// EXPECT_TRUE(cgogn::almost_equal_relative(n1[2], n2[2])); +TYPED_TEST(Algos_TEST, QuadCentroid) +{ + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + cgogn::io::import_surface(this->map2_, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); + VertexAttributeHandler vertex_position = this->map2_.template get_attribute("position"); + const TypeParam centroid = cgogn::geometry::centroid(this->map2_, CMap2::Face(*this->map2_.begin()), vertex_position); + EXPECT_DOUBLE_EQ(centroid[0], Scalar(2.5f)); + EXPECT_DOUBLE_EQ(centroid[1], Scalar(1)); + EXPECT_DOUBLE_EQ(centroid[2], Scalar(0)); +} -// const EigenVec3d& cross = n1.cross(EigenVec3d(0,0,1)); -// EXPECT_TRUE(cgogn::almost_equal_relative(cross[0], 0.)); -// EXPECT_TRUE(cgogn::almost_equal_relative(cross[1], 0.)); -// EXPECT_TRUE(cgogn::almost_equal_relative(cross[2], 0.)); - } +TYPED_TEST(Algos_TEST, TriangleNormal) +{ + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + cgogn::io::import_surface(this->map2_, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); + VertexAttributeHandler vertex_position = this->map2_.template get_attribute("position"); + const TypeParam& n1 = cgogn::geometry::triangle_normal(this->map2_, CMap2::Face(*this->map2_.begin()), vertex_position); + const TypeParam& n2 = cgogn::geometry::face_normal(this->map2_, CMap2::Face(*this->map2_.begin()), vertex_position); + EXPECT_TRUE(cgogn::almost_equal_relative(n1[0], n2[0])); + EXPECT_TRUE(cgogn::almost_equal_relative(n1[1], n2[1])); + EXPECT_TRUE(cgogn::almost_equal_relative(n1[2], n2[2])); + + const TypeParam& cross = n1.cross(TypeParam(Scalar(0), Scalar(0), Scalar(1))); + EXPECT_TRUE(cgogn::almost_equal_relative(cross[0], Scalar(0))); + EXPECT_TRUE(cgogn::almost_equal_relative(cross[1], Scalar(0))); + EXPECT_TRUE(cgogn::almost_equal_relative(cross[2], Scalar(0))); } -TEST(Algos_TEST, QuadNormal) +TYPED_TEST(Algos_TEST, QuadNormal) { - { - CMap2 map; - cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); - VertexAttributeHandler vertex_position = map.get_attribute("position"); - const StdArray& n1 = cgogn::geometry::face_normal(map, CMap2::Face(*map.begin()), vertex_position); - const StdArray& cross = n1.cross(StdArray(0.,0.,1.)); - EXPECT_TRUE(cgogn::almost_equal_relative(cross[0], 0.)); - EXPECT_TRUE(cgogn::almost_equal_relative(cross[1], 0.)); - EXPECT_TRUE(cgogn::almost_equal_relative(cross[2], 0.)); - } - { -// CMap2 map; -// cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); -// VertexAttributeHandler vertex_position = map.get_attribute("position"); -// const EigenVec3d& n1 = cgogn::geometry::triangle_normal(map, CMap2::Face(*map.begin()), vertex_position); -// const EigenVec3d& cross = n1.cross(EigenVec3d(0,0,1)); -// EXPECT_TRUE(cgogn::almost_equal_relative(cross[0], 0.)); -// EXPECT_TRUE(cgogn::almost_equal_relative(cross[1], 0.)); -// EXPECT_TRUE(cgogn::almost_equal_relative(cross[2], 0.)); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + cgogn::io::import_surface(this->map2_, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); + VertexAttributeHandler vertex_position = this->map2_.template get_attribute("position"); + const TypeParam& n1 = cgogn::geometry::face_normal(this->map2_, CMap2::Face(*this->map2_.begin()), vertex_position); + const TypeParam& cross = n1.cross(TypeParam(Scalar(0), Scalar(0), Scalar(1))); + EXPECT_TRUE(cgogn::almost_equal_relative(cross[0], Scalar(0))); + EXPECT_TRUE(cgogn::almost_equal_relative(cross[1], Scalar(0))); + EXPECT_TRUE(cgogn::almost_equal_relative(cross[2], Scalar(0))); } -TEST(Algos_TEST, EarTriangulation) +TYPED_TEST(Algos_TEST, EarTriangulation) { - // with array + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + VertexAttributeHandler vertex_position = this->map2_.template add_attribute("position"); + + Face f = this->map2_.add_face(5); + cgogn::Dart d = f.dart; + + vertex_position[Vertex(d)] = TypeParam(Scalar(0), Scalar(0), Scalar(0)); + d = this->map2_.phi1(d); + vertex_position[Vertex(d)] = TypeParam(Scalar(10), Scalar(0), Scalar(0)); + d = this->map2_.phi1(d); + vertex_position[Vertex(d)] = TypeParam(Scalar(10), Scalar(10), Scalar(0)); + d = this->map2_.phi1(d); + vertex_position[Vertex(d)] = TypeParam(Scalar(5), Scalar(5), Scalar(0)); + d = this->map2_.phi1(d); + vertex_position[Vertex(d)] = TypeParam(Scalar(0), Scalar(10), Scalar(0)); + + std::vector indices; + cgogn::geometry::compute_ear_triangulation(this->map2_,f,vertex_position,indices); + EXPECT_TRUE(indices.size() == 9); + + Scalar area = 0; + for (size_t i=0; i vertex_position = map.add_attribute("position"); - - Face f = map.add_face(5); - cgogn::Dart d = f.dart; - - vertex_position[Vertex(d)] = StdArray(0.0,0.0,0.0); - d = map.phi1(d); - vertex_position[Vertex(d)] = StdArray(10.0,0.0,0.0); - d = map.phi1(d); - vertex_position[Vertex(d)] = StdArray(10.0,10.0,0.0); - d = map.phi1(d); - vertex_position[Vertex(d)] = StdArray(5.0,5.0,0.0); - d = map.phi1(d); - vertex_position[Vertex(d)] = StdArray(0.0,10.0,0.0); - - std::vector indices; - cgogn::geometry::compute_ear_triangulation(map,f,vertex_position,indices); - EXPECT_TRUE(indices.size() == 9); - - double area = 0.0; - for (size_t i=0; i(map,f,vertex_position); - EXPECT_TRUE(map.nb_cells()==4); - EXPECT_TRUE(map.nb_cells()==7); + const TypeParam& A = vertex_position[indices[i]]; + const TypeParam& B = vertex_position[indices[i+1]]; + const TypeParam& C = vertex_position[indices[i+2]]; + area += cgogn::geometry::triangle_area(A,B,C); } - // with Eigen - { - CMap2 map; - VertexAttributeHandler vertex_position = map.add_attribute("position"); + EXPECT_DOUBLE_EQ(area,75.0); - Face f = map.add_face(5); - cgogn::Dart d = f.dart; - - vertex_position[CMap2::Vertex(d)] = EigenVec3d(0,0,0); - d = map.phi1(d); - vertex_position[CMap2::Vertex(d)] = EigenVec3d(10,0,0); - d = map.phi1(d); - vertex_position[CMap2::Vertex(d)] = EigenVec3d(10,10,0); - d = map.phi1(d); - vertex_position[CMap2::Vertex(d)] = EigenVec3d(5,5,0); - d = map.phi1(d); - vertex_position[CMap2::Vertex(d)] = EigenVec3d(0,10,0); - - std::vector indices; - cgogn::geometry::compute_ear_triangulation(map,f,vertex_position,indices); - EXPECT_TRUE(indices.size() == 9); - - double area = 0.0; - for (size_t i=0; i(map,f,vertex_position); - EXPECT_TRUE(map.nb_cells()==4); - EXPECT_TRUE(map.nb_cells()==7); - } + cgogn::geometry::apply_ear_triangulation(this->map2_,f,vertex_position); + EXPECT_TRUE(this->map2_.template nb_cells()==4); + EXPECT_TRUE(this->map2_.template nb_cells()==7); } diff --git a/cgogn/geometry/tests/functions/area_test.cpp b/cgogn/geometry/tests/functions/area_test.cpp index 8591000e..b40c10ae 100644 --- a/cgogn/geometry/tests/functions/area_test.cpp +++ b/cgogn/geometry/tests/functions/area_test.cpp @@ -23,25 +23,30 @@ #include #include +#include #include + #include -#include -using StdArray = cgogn::geometry::Vec_T>; -//using EigenVec3d = Eigen::Vector3d; +using StdArrayf = cgogn::geometry::Vec_T>; +using StdArrayd = cgogn::geometry::Vec_T>; +using EigenVec3f = Eigen::Vector3f; +using EigenVec3d = Eigen::Vector3d; +using VecTypes = testing::Types; + +template +class Area_TEST : public testing::Test +{ +}; + + +TYPED_TEST_CASE(Area_TEST, VecTypes ); -TEST(Area_TEST, TriangleArea) +TYPED_TEST(Area_TEST, TriangleArea) { - { - StdArray p0(0.,0.,0.); - StdArray p1(2.,0.,0.); - StdArray p2(0.,2.,0.); - EXPECT_DOUBLE_EQ(cgogn::geometry::triangle_area(p0,p1,p2), 2.0); - } - { -// EigenVec3d p0(0,0,0); -// EigenVec3d p1(2,0,0); -// EigenVec3d p2(0,2,0); -// EXPECT_DOUBLE_EQ(cgogn::geometry::triangle_area(p0,p1,p2), 2.0); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + TypeParam p0(Scalar(0), Scalar(0), Scalar(0)); + TypeParam p1(Scalar(2), Scalar(0), Scalar(0)); + TypeParam p2(Scalar(0), Scalar(2), Scalar(0)); + EXPECT_DOUBLE_EQ(cgogn::geometry::triangle_area(p0,p1,p2), Scalar(2)); } diff --git a/cgogn/geometry/tests/functions/normal_test.cpp b/cgogn/geometry/tests/functions/normal_test.cpp index 1fa1b70b..a8c7545c 100644 --- a/cgogn/geometry/tests/functions/normal_test.cpp +++ b/cgogn/geometry/tests/functions/normal_test.cpp @@ -25,41 +25,40 @@ #include #include #include +#include + #include -#include -using StdArray = cgogn::geometry::Vec_T>; -//using EigenVec3d = Eigen::Vector3d; +using StdArrayf = cgogn::geometry::Vec_T>; +using StdArrayd = cgogn::geometry::Vec_T>; +using EigenVec3f = Eigen::Vector3f; +using EigenVec3d = Eigen::Vector3d; +using VecTypes = testing::Types; + +template +class Normal_TEST : public testing::Test {}; + +TYPED_TEST_CASE(Normal_TEST, VecTypes ); + -TEST(Normal_TEST, TriangleNormal) +TYPED_TEST(Normal_TEST, TriangleNormal) { - { - StdArray p0(1.,3.,-5.); - StdArray p1(7.,-4.,0.1); - StdArray p2(-15.,-2.,15.); - StdArray n = cgogn::geometry::triangle_normal(p0,p1,p2); - cgogn::almost_equal_relative(n.dot(p1-p0), 0.); -// EXPECT_TRUE(cgogn::almost_equal_relative(n.dot(p1-p0),0.)); // is false ! - EXPECT_TRUE(cgogn::almost_equal_absolute(n.dot(p1-p0), 0., 1e-8)); - EXPECT_TRUE(cgogn::almost_equal_relative(n.dot(p2-p0), 0.)); - EXPECT_TRUE(cgogn::almost_equal_relative(n.dot(p2-p1), 0.)); -// EXPECT_DOUBLE_EQ(n.dot(p1-p0), 0.); // is false ! - EXPECT_NEAR(n.dot(p1-p0), 0., 1e-8); - EXPECT_DOUBLE_EQ(n.dot(p2-p0), 0.); - EXPECT_DOUBLE_EQ(n.dot(p2-p1), 0.); - } - { -// EigenVec3d p0(1,3,-5); -// EigenVec3d p1(7,-4,0.1); -// EigenVec3d p2(-15,-2,15); -// EigenVec3d n = cgogn::geometry::triangle_normal(p0,p1,p2); -//// EXPECT_TRUE(cgogn::almost_equal_relative(n.dot(p1-p0),0.)); // is false ! -// EXPECT_TRUE(cgogn::almost_equal_absolute(n.dot(p1-p0), 0., 1e-8)); -// EXPECT_TRUE(cgogn::almost_equal_relative(n.dot(p2-p0), 0.)); -// EXPECT_TRUE(cgogn::almost_equal_relative(n.dot(p2-p1), 0.)); -//// EXPECT_DOUBLE_EQ(n.dot(p1-p0),0); // is false ! -// EXPECT_NEAR(n.dot(p1-p0), 0., 1e-8); -// EXPECT_DOUBLE_EQ(n.dot(p2-p0), 0.); -// EXPECT_DOUBLE_EQ(n.dot(p2-p1), 0.); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + const Scalar tolerence = std::is_same::value ? Scalar(1e-8) : Scalar(1e-4f); + TypeParam p0(Scalar(1), Scalar(3), Scalar(-5)); + TypeParam p1(Scalar(7), Scalar(-4), Scalar(0.1f)); + TypeParam p2(Scalar(-15), Scalar(-2), Scalar(15));; + + TypeParam n = cgogn::geometry::triangle_normal(p0,p1,p2); + + cgogn::almost_equal_relative(n.dot(p1-p0), Scalar(0)); + // EXPECT_TRUE(cgogn::almost_equal_relative(n.dot(p1-p0),0.)); // is false ! + EXPECT_TRUE(cgogn::almost_equal_absolute(n.dot(p1-p0), Scalar(0), tolerence)); + EXPECT_TRUE(cgogn::almost_equal_relative(n.dot(p2-p0), Scalar(0))); + EXPECT_TRUE(cgogn::almost_equal_relative(n.dot(p2-p1), Scalar(0))); + // EXPECT_DOUBLE_EQ(n.dot(p1-p0), 0.); // is false ! + EXPECT_NEAR(n.dot(p1-p0), Scalar(0), tolerence); + EXPECT_DOUBLE_EQ(n.dot(p2-p0), Scalar(0)); + EXPECT_DOUBLE_EQ(n.dot(p2-p1), Scalar(0)); } diff --git a/cgogn/geometry/tests/types/bounding_box_test.cpp b/cgogn/geometry/tests/types/bounding_box_test.cpp index 70c49a90..be930782 100644 --- a/cgogn/geometry/tests/types/bounding_box_test.cpp +++ b/cgogn/geometry/tests/types/bounding_box_test.cpp @@ -21,100 +21,75 @@ * * *******************************************************************************/ +#include #include +#include + #include -#include -#include -using StdArray = cgogn::geometry::Vec_T>; -//using EigenVec3d = Eigen::Vector3d; -using BoundingBox_Array = cgogn::geometry::BoundingBox; -//using BoundingBox_Eigen = cgogn::geometry::BoundingBox; +using StdArrayf = cgogn::geometry::Vec_T>; +using StdArrayd = cgogn::geometry::Vec_T>; +using EigenVec3f = Eigen::Vector3f; +using EigenVec3d = Eigen::Vector3d; +using VecTypes = testing::Types; + +template +class BoundingBox_TEST : public testing::Test +{ +protected : + cgogn::geometry::BoundingBox bb_; +}; + + +TYPED_TEST_CASE(BoundingBox_TEST, VecTypes ); + TEST(BoundingBox_TEST, NameOfType) { - EXPECT_EQ(cgogn::name_of_type(BoundingBox_Array()), "cgogn::geometry::BoundingBox>>"); -// EXPECT_EQ(cgogn::name_of_type(BoundingBox_Eigen()), "cgogn::geometry::BoundingBox>"); + EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::BoundingBox()), "cgogn::geometry::BoundingBox>>"); + EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::BoundingBox()), "cgogn::geometry::BoundingBox>"); + EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::BoundingBox()), "cgogn::geometry::BoundingBox>>"); + EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::BoundingBox()), "cgogn::geometry::BoundingBox>"); } -TEST(BoundingBox_TEST, Basics) +TYPED_TEST(BoundingBox_TEST, Basics) { - { - BoundingBox_Array bb; - bb.add_point(StdArray({0.5,0.4,0.3})); - bb.add_point(StdArray({-1.,-2.,-3.})); - bb.add_point(StdArray({1.,2.,3.})); - - EXPECT_EQ(bb.min(), StdArray({-1.,-2.,-3.})); - EXPECT_EQ(bb.max(), StdArray({1.,2.,3.})); - EXPECT_EQ(bb.max_size(), 6); - EXPECT_EQ(bb.min_size(), 2); - EXPECT_TRUE(cgogn::almost_equal_relative(bb.diag_size(), std::sqrt(2.0*2+4*4+6*6))); - - std::cout << bb.center()[0] << "," << bb.center()[1] << "," << bb.center()[2] << std::endl; - EXPECT_EQ(bb.center(), StdArray({0.,0.,0.})); - } - { -// BoundingBox_Eigen bb; -// bb.add_point(EigenVec3d(0.5,0.4,0.3)); -// bb.add_point(EigenVec3d(-1,2,-3)); -// bb.add_point(EigenVec3d(1,-2,3)); - -// EXPECT_EQ(bb.min(), EigenVec3d(-1,-2,-3)); -// EXPECT_EQ(bb.max(), EigenVec3d(1,2,3)); -// EXPECT_EQ(bb.max_size(), 6); -// EXPECT_EQ(bb.min_size(), 2); -// EXPECT_TRUE(cgogn::almost_equal_relative(bb.diag_size(), std::sqrt(2.0*2+4*4+6*6))); -// EXPECT_EQ(bb.center(), EigenVec3d(0,0,0)); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + this->bb_.add_point(TypeParam({Scalar(0.5f), Scalar(0.4f), Scalar(0.3f)})); + this->bb_.add_point(TypeParam({Scalar(-1), Scalar(-2), Scalar(-3)})); + this->bb_.add_point(TypeParam({Scalar(1), Scalar(2), Scalar(3)})); + + EXPECT_EQ(this->bb_.min(), TypeParam({Scalar(-1), Scalar(-2), Scalar(-3)})); + EXPECT_EQ(this->bb_.max(), TypeParam({Scalar(1), Scalar(2), Scalar(3)})); + EXPECT_EQ(this->bb_.max_size(), Scalar(6)); + EXPECT_EQ(this->bb_.min_size(), Scalar(2)); + EXPECT_TRUE(cgogn::almost_equal_relative(this->bb_.diag_size(), std::sqrt(Scalar(2*2+4*4+6*6)))); + EXPECT_EQ(this->bb_.center(), TypeParam({Scalar(0), Scalar(0), Scalar(0)})); } -TEST(BoundingBox_TEST, testing) +TYPED_TEST(BoundingBox_TEST, testing) { - { - BoundingBox_Array bb; - bb.add_point(StdArray({0.5,0.4,0.3})); - bb.add_point(StdArray({-1.,-2.,-3.})); - bb.add_point(StdArray({1.,2.,3.})); - - EXPECT_TRUE(bb.contains(StdArray({1.,1.,1.}))); - - BoundingBox_Array bb2; - bb2.add_point(StdArray({0.,0.,0.})); - bb2.add_point(StdArray({4.,5.,2.})); - - EXPECT_TRUE(bb.intersects(bb2)); - - BoundingBox_Array bb3; - bb3.add_point(StdArray({0.,0.,0.})); - bb3.add_point(StdArray({1.,1.,1.})); - - EXPECT_TRUE(bb.contains(bb3)); + using Scalar = typename cgogn::geometry::vector_traits::Scalar; - EXPECT_TRUE(bb.ray_intersect(StdArray({-9.,-9.,-9.}), StdArray({1.,1.,1.}))); - EXPECT_FALSE(bb.ray_intersect(StdArray({-9.,-9.,-9.}), StdArray({1.,-1.,0.}))); - } - { -// BoundingBox_Eigen bb; -// bb.add_point(EigenVec3d(0.5,0.4,0.3)); -// bb.add_point(EigenVec3d(-1,2,-3)); -// bb.add_point(EigenVec3d(1,-2,3)); + this->bb_.add_point(TypeParam({Scalar(0.5f), Scalar(0.4f), Scalar(0.3f)})); + this->bb_.add_point(TypeParam({Scalar(-1), Scalar(-2), Scalar(-3)})); + this->bb_.add_point(TypeParam({Scalar(1), Scalar(2), Scalar(3)})); -// EXPECT_TRUE(bb.contains(EigenVec3d(1,1,1))); + EXPECT_TRUE(this->bb_.contains(TypeParam({Scalar(1), Scalar(1), Scalar(1)}))); -// BoundingBox_Eigen bb2; -// bb2.add_point(EigenVec3d(0,0,0)); -// bb2.add_point(EigenVec3d(4,5,2)); + cgogn::geometry::BoundingBox bb2; + bb2.add_point(TypeParam({Scalar(0), Scalar(0), Scalar(0)})); + bb2.add_point(TypeParam({Scalar(4), Scalar(5), Scalar(2)})); -// EXPECT_TRUE(bb.intersects(bb2)); + EXPECT_TRUE(this->bb_.intersects(bb2)); -// BoundingBox_Eigen bb3; -// bb3.add_point(EigenVec3d(0,0,0)); -// bb3.add_point(EigenVec3d(1,1,1)); + cgogn::geometry::BoundingBox bb3; + bb3.add_point(TypeParam({Scalar(0), Scalar(0), Scalar(0)})); + bb3.add_point(TypeParam({Scalar(1), Scalar(1), Scalar(1)})); -// EXPECT_TRUE(bb.contains(bb3)); + EXPECT_TRUE(this->bb_.contains(bb3)); -// EXPECT_TRUE(bb.ray_intersect(EigenVec3d(-9,-9,-9), EigenVec3d(1,1,1))); -// EXPECT_FALSE(bb.ray_intersect(EigenVec3d(-9,-9,-9), EigenVec3d(1,-1,0))); - } + EXPECT_TRUE(this->bb_.ray_intersect(TypeParam({Scalar(-9), Scalar(-9), Scalar(-9)}), TypeParam({Scalar(1), Scalar(1), Scalar(1)}))); + EXPECT_FALSE(this->bb_.ray_intersect(TypeParam({Scalar(-9), Scalar(-9), Scalar(-9)}), TypeParam({Scalar(1), Scalar(-1), Scalar(0)}))); } diff --git a/cgogn/geometry/tests/types/plane_3d_test.cpp b/cgogn/geometry/tests/types/plane_3d_test.cpp index 8867d4cd..b9234c98 100644 --- a/cgogn/geometry/tests/types/plane_3d_test.cpp +++ b/cgogn/geometry/tests/types/plane_3d_test.cpp @@ -22,58 +22,51 @@ *******************************************************************************/ #include +#include + #include -#include -using StdArray = cgogn::geometry::Vec_T>; -//using EigenVec3d = Eigen::Vector3d; -using Plane3D_Array = cgogn::geometry::Plane3D; -//using Plane3D_Eigen = cgogn::geometry::Plane3D; +using StdArrayf = cgogn::geometry::Vec_T>; +using StdArrayd = cgogn::geometry::Vec_T>; +using EigenVec3f = Eigen::Vector3f; +using EigenVec3d = Eigen::Vector3d; +using VecTypes = testing::Types; + + +template +class Plane3D_TEST : public testing::Test {}; + +TYPED_TEST_CASE(Plane3D_TEST, VecTypes ); TEST(Plane3D_TEST, NameOfType) { - EXPECT_EQ(cgogn::name_of_type(Plane3D_Array(StdArray(),0.)), "cgogn::geometry::Plane3D>>"); -// EXPECT_EQ(cgogn::name_of_type(Plane3D_Eigen(EigenVec3d(),0.)), "cgogn::geometry::Plane3D>"); + EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::Plane3D(StdArrayf(),0)), "cgogn::geometry::Plane3D>>"); + EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::Plane3D(EigenVec3f(),0)), "cgogn::geometry::Plane3D>"); + EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::Plane3D(StdArrayd(),0)), "cgogn::geometry::Plane3D>>"); + EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::Plane3D(EigenVec3d(),0)), "cgogn::geometry::Plane3D>"); } -TEST(Plane3D_TEST, Project) +TYPED_TEST(Plane3D_TEST, Project) { - { - Plane3D_Array plane(StdArray{4.,0.,0.}, StdArray{0.,0.,0.}); - StdArray p{5.,8.,12.}; - plane.project(p); - EXPECT_EQ(p[0], 0.); - EXPECT_EQ(p[1], 8.); - EXPECT_EQ(p[2], 12.); - } - { -// Plane3D_Eigen plane(EigenVec3d{4,0,0}, EigenVec3d{0,0,0}); -// EigenVec3d p{5,8,12}; -// plane.project(p); -// EXPECT_EQ(p[0], 0.); -// EXPECT_EQ(p[1], 8.); -// EXPECT_EQ(p[2], 12.); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + cgogn::geometry::Plane3D plane(TypeParam{Scalar(4), Scalar(0), Scalar(0)}, TypeParam{Scalar(0), Scalar(0), Scalar(0)}); + TypeParam p{Scalar(5), Scalar(8), Scalar(12)}; + plane.project(p); + EXPECT_EQ(p[0], Scalar(0)); + EXPECT_EQ(p[1], Scalar(8)); + EXPECT_EQ(p[2], Scalar(12)); } -TEST(Plane3D_TEST, Orient) +TYPED_TEST(Plane3D_TEST, Orient) { - { - Plane3D_Array plane(StdArray{0.,0.,15.}, StdArray{0.,0.,0.}); - StdArray p1{546854.,864.,12.}; - StdArray p2{-5.,886486.,-12.}; - StdArray p3{44552.,7.,0.}; - EXPECT_EQ(plane.orient(p1), cgogn::geometry::Orientation3D::OVER); - EXPECT_EQ(plane.orient(p2), cgogn::geometry::Orientation3D::UNDER); - EXPECT_EQ(plane.orient(p3), cgogn::geometry::Orientation3D::ON); - } - { -// EigenVec3d p1{546854,864,12}; -// EigenVec3d p2{-5,886486,-12}; -// EigenVec3d p3{44552,7,0}; -// EXPECT_EQ(plane.orient(p1), cgogn::geometry::Orientation3D::OVER); -// EXPECT_EQ(plane.orient(p2), cgogn::geometry::Orientation3D::UNDER); -// Plane3D_Eigen plane(EigenVec3d{0,0,15}, EigenVec3d{0,0,0}); -// EXPECT_EQ(plane.orient(p3), cgogn::geometry::Orientation3D::ON); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + cgogn::geometry::Plane3D plane(TypeParam{Scalar(0), Scalar(0), Scalar(15)}, TypeParam{Scalar(0), Scalar(0), Scalar(0)}); + TypeParam p1{Scalar(546854), Scalar(864), Scalar(12)}; + TypeParam p2{Scalar(-5), Scalar(886486), Scalar(-12)}; + TypeParam p3{Scalar(44552), Scalar(7), Scalar(0)}; + EXPECT_EQ(plane.orient(p1), cgogn::geometry::Orientation3D::OVER); + EXPECT_EQ(plane.orient(p2), cgogn::geometry::Orientation3D::UNDER); + EXPECT_EQ(plane.orient(p3), cgogn::geometry::Orientation3D::ON); } diff --git a/cgogn/geometry/tests/types/vec_test.cpp b/cgogn/geometry/tests/types/vec_test.cpp index e3cc6e83..a61de2e3 100644 --- a/cgogn/geometry/tests/types/vec_test.cpp +++ b/cgogn/geometry/tests/types/vec_test.cpp @@ -23,332 +23,227 @@ #include #include +#include #include -using StdArray = cgogn::geometry::Vec_T>; -//using EigenVec3d = Eigen::Vector3d; +using StdArrayf = cgogn::geometry::Vec_T>; +using StdArrayd = cgogn::geometry::Vec_T>; +using EigenVec3f = Eigen::Vector3f; +using EigenVec3d = Eigen::Vector3d; +using VecTypes = testing::Types; + +template +class VEC_OP_TEST : public testing::Test +{ +}; + +TYPED_TEST_CASE(VEC_OP_TEST, VecTypes ); TEST(VEC_OP_TEST, CGOGN_Typename) { - EXPECT_EQ(cgogn::name_of_type(StdArray()),"cgogn::geometry::Vec_T>"); -// EXPECT_EQ(cgogn::name_of_type(EigenVec3d()), "Eigen::Matrix"); + EXPECT_EQ(cgogn::name_of_type(StdArrayf()),"cgogn::geometry::Vec_T>"); + EXPECT_EQ(cgogn::name_of_type(EigenVec3f()), "Eigen::Matrix"); + EXPECT_EQ(cgogn::name_of_type(StdArrayd()),"cgogn::geometry::Vec_T>"); + EXPECT_EQ(cgogn::name_of_type(EigenVec3d()), "Eigen::Matrix"); } -TEST(VEC_OP_TEST, Constructor) +TYPED_TEST(VEC_OP_TEST, Constructor) { - StdArray vec1{0.,0.,0.}; - EXPECT_EQ(vec1[0],0); - EXPECT_EQ(vec1[1],0); - EXPECT_EQ(vec1[2],0); -// EigenVec3d vec2 = {0.,0.,0.}; -// EXPECT_EQ(vec2[0],0); -// EXPECT_EQ(vec2[1],0); -// EXPECT_EQ(vec2[2],0); + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + const Scalar zero(0); + const TypeParam vec1{zero, zero, zero}; + EXPECT_EQ(vec1[0],zero); + EXPECT_EQ(vec1[1],zero); + EXPECT_EQ(vec1[2],zero); } -TEST(VEC_OP_TEST, CopyConstructor) +TYPED_TEST(VEC_OP_TEST, CopyConstructor) { - StdArray vec1a = {1.,2., 3.}; - StdArray vec1b(vec1a); + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + const TypeParam vec1a = {Scalar(1), Scalar(2), Scalar(3)}; + TypeParam vec1b(vec1a); EXPECT_EQ(vec1a[0], vec1b[0]); EXPECT_EQ(vec1a[1], vec1b[1]); EXPECT_EQ(vec1a[2], vec1b[2]); -// EigenVec3d vec2a = {1.,2., 3.}; -// EigenVec3d vec2b(vec2a); -// EXPECT_EQ(vec2a[0], vec2b[0]); -// EXPECT_EQ(vec2a[1], vec2b[1]); -// EXPECT_EQ(vec2a[2], vec2b[2]); } -TEST(VEC_OP_TEST, AssignConstructor) +TYPED_TEST(VEC_OP_TEST, AssignConstructor) { - StdArray vec1a = {1.,2., 3.}; - StdArray vec1b; + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + const TypeParam vec1a = {Scalar(1), Scalar(2), Scalar(3)}; + TypeParam vec1b; vec1b = vec1a; EXPECT_EQ(vec1a[0], vec1b[0]); EXPECT_EQ(vec1a[1], vec1b[1]); EXPECT_EQ(vec1a[2], vec1b[2]); - -// EigenVec3d vec2a = {1.,2., 3.}; -// EigenVec3d vec2b; -// vec2b = vec2a; -// EXPECT_EQ(vec2a[0], vec2b[0]); -// EXPECT_EQ(vec2a[1], vec2b[1]); -// EXPECT_EQ(vec2a[2], vec2b[2]); } -TEST(VEC_OP_TEST, UnaryMinus) +TYPED_TEST(VEC_OP_TEST, UnaryMinus) { - StdArray vec1a = {1.,2., 3.}; - StdArray vec1b = -vec1a; + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + const TypeParam vec1a = {Scalar(1), Scalar(2), Scalar(3)}; + const TypeParam vec1b = -vec1a; EXPECT_EQ(vec1a[0], -vec1b[0]); EXPECT_EQ(vec1a[1], -vec1b[1]); EXPECT_EQ(vec1a[2], -vec1b[2]); - -// EigenVec3d vec2a = {1.,2., 3.}; -// EigenVec3d vec2b = -vec2a; -// EXPECT_EQ(vec2a[0], -vec2b[0]); -// EXPECT_EQ(vec2a[1], -vec2b[1]); -// EXPECT_EQ(vec2a[2], -vec2b[2]); } -TEST(VEC_OP_TEST, PlusAssign) +TYPED_TEST(VEC_OP_TEST, PlusAssign) { - { - StdArray a = {1.,2., 3.}; - StdArray b = {1.,2., 3.}; - b += a; - EXPECT_EQ(b[0], 2); - EXPECT_EQ(b[1], 4); - EXPECT_EQ(b[2], 6); - } - - { -// EigenVec3d a = {1.,2., 3.}; -// EigenVec3d b = {1.,2., 3.}; -// b += a; -// EXPECT_EQ(b[0], 2); -// EXPECT_EQ(b[1], 4); -// EXPECT_EQ(b[2], 6); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + const TypeParam a = {Scalar(1), Scalar(2), Scalar(3)}; + TypeParam b = {Scalar(7), Scalar(5), Scalar(9)}; + b += a; + EXPECT_EQ(b[0], 8); + EXPECT_EQ(b[1], 7); + EXPECT_EQ(b[2], 12); } -TEST(VEC_OP_TEST, MinusAssign) +TYPED_TEST(VEC_OP_TEST, MinusAssign) { - { - StdArray a = {-1.,-2., -3.}; - StdArray b = {1.,2., 3.}; - b -= a; - EXPECT_EQ(b[0], 2); - EXPECT_EQ(b[1], 4); - EXPECT_EQ(b[2], 6); - } - - { -// EigenVec3d a = {-1.,-2., -3.}; -// EigenVec3d b = {1.,2., 3.}; -// b -= a; -// EXPECT_EQ(b[0], 2); -// EXPECT_EQ(b[1], 4); -// EXPECT_EQ(b[2], 6); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + const TypeParam a = {Scalar(-1), Scalar(-2), Scalar(-3)}; + TypeParam b = {Scalar(7), Scalar(5), Scalar(9)}; + b -= a; + EXPECT_EQ(b[0], 8); + EXPECT_EQ(b[1], 7); + EXPECT_EQ(b[2], 12); } -TEST(VEC_OP_TEST, MultAssign) +TYPED_TEST(VEC_OP_TEST, MultAssign) { - { - StdArray a = {1.,2., 3.}; - a *= 2; - EXPECT_EQ(a[0], 2); - EXPECT_EQ(a[1], 4); - EXPECT_EQ(a[2], 6); - } - - { -// EigenVec3d a = {1.,2., 3.}; -// a *= 2; -// EXPECT_EQ(a[0], 2); -// EXPECT_EQ(a[1], 4); -// EXPECT_EQ(a[2], 6); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + TypeParam a = {Scalar(7), Scalar(5), Scalar(9)}; + a *= 2; + EXPECT_EQ(a[0], 14); + EXPECT_EQ(a[1], 10); + EXPECT_EQ(a[2], 18); } -TEST(VEC_OP_TEST, DivAssign) +TYPED_TEST(VEC_OP_TEST, DivAssign) { - { - StdArray a{2.,4., 6.}; - a /= 2; - EXPECT_EQ(a[0], 1); - EXPECT_EQ(a[1], 2); - EXPECT_EQ(a[2], 3); - } - - { -// EigenVec3d a{2.,4., 6.}; -// a /= 2; -// EXPECT_EQ(a[0], 1); -// EXPECT_EQ(a[1], 2); -// EXPECT_EQ(a[2], 3); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + TypeParam a = {Scalar(2), Scalar(4), Scalar(6)}; + a /= 2; + EXPECT_EQ(a[0], 1); + EXPECT_EQ(a[1], 2); + EXPECT_EQ(a[2], 3); } -TEST(VEC_OP_TEST, Plus) +TYPED_TEST(VEC_OP_TEST, Plus) { - { - StdArray a = {1.,2., 3.}; - StdArray b = {1.,2., 3.}; - StdArray c = a+b; - EXPECT_EQ(c[0], 2); - EXPECT_EQ(c[1], 4); - EXPECT_EQ(c[2], 6); - } - - { -// EigenVec3d a = {1.,2., 3.}; -// EigenVec3d b = {1.,2., 3.}; -// EigenVec3d c = a+b; -// EXPECT_EQ(c[0], 2); -// EXPECT_EQ(c[1], 4); -// EXPECT_EQ(c[2], 6); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + const TypeParam a = {Scalar(1), Scalar(2), Scalar(3)}; + const TypeParam b = {Scalar(7), Scalar(5), Scalar(9)}; + const TypeParam c = a + b; + EXPECT_EQ(c[0], a[0] + b[0]); + EXPECT_EQ(c[1], a[1] + b[1]); + EXPECT_EQ(c[2], a[2] + b[2]); } -TEST(VEC_OP_TEST, Minus) +TYPED_TEST(VEC_OP_TEST, Minus) { - { - StdArray a = {1.,2., 3.}; - StdArray b = {-1.,-2., -3.}; - StdArray c = a-b; - EXPECT_EQ(c[0], 2); - EXPECT_EQ(c[1], 4); - EXPECT_EQ(c[2], 6); - } - - { -// EigenVec3d a = {1.,2., 3.}; -// EigenVec3d b = {-1.,-2., -3.}; -// EigenVec3d c = a-b; -// EXPECT_EQ(c[0], 2); -// EXPECT_EQ(c[1], 4); -// EXPECT_EQ(c[2], 6); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + const TypeParam a = {Scalar(1), Scalar(2), Scalar(3)}; + const TypeParam b = {Scalar(7), Scalar(5), Scalar(9)}; + const TypeParam c = a - b; + EXPECT_EQ(c[0], a[0] - b[0]); + EXPECT_EQ(c[1], a[1] - b[1]); + EXPECT_EQ(c[2], a[2] - b[2]); } -TEST(VEC_OP_TEST, MultScalar) +TYPED_TEST(VEC_OP_TEST, MultScalar) { - { - StdArray a = {1.,2., 3.}; - StdArray c = a*2; - StdArray d = 2*a; - EXPECT_EQ(c[0], 2); - EXPECT_EQ(c[1], 4); - EXPECT_EQ(c[2], 6); - EXPECT_EQ(d[0], 2); - EXPECT_EQ(d[1], 4); - EXPECT_EQ(d[2], 6); - } - - { -// EigenVec3d a = {1.,2., 3.}; -// EigenVec3d c = a*2; -// EigenVec3d d = 2*a; -// EXPECT_EQ(c[0], 2); -// EXPECT_EQ(c[1], 4); -// EXPECT_EQ(c[2], 6); -// EXPECT_EQ(d[0], 2); -// EXPECT_EQ(d[1], 4); -// EXPECT_EQ(d[2], 6); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + TypeParam a = {Scalar(1), Scalar(2), Scalar(3)}; + const TypeParam c = a*2; + const TypeParam d = 2*a; + EXPECT_EQ(c[0], 2 * a[0]); + EXPECT_EQ(c[1], 2 * a[1]); + EXPECT_EQ(c[2], 2 * a[2]); + EXPECT_EQ(d[0], 2 * a[0]); + EXPECT_EQ(d[1], 2 * a[1]); + EXPECT_EQ(d[2], 2 * a[2]); } -TEST(VEC_OP_TEST, Norm2) +TYPED_TEST(VEC_OP_TEST, Norm2) { - StdArray vec1a = {1.,2., 3.}; - EXPECT_EQ(vec1a.squaredNorm(), 14.); + using Scalar = typename cgogn::geometry::vector_traits::Scalar; -// EigenVec3d vec2a = {1.,2., 3.}; -// EXPECT_EQ(vec2a.squaredNorm(), 14.); + const TypeParam a = {Scalar(1), Scalar(2), Scalar(3)}; + EXPECT_EQ(a.squaredNorm(), 14.); } -TEST(VEC_OP_TEST, Norm) +TYPED_TEST(VEC_OP_TEST, Norm) { - { - StdArray a = {3.,-4., 0.}; - EXPECT_EQ(a.norm(), 5.); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; - { -// EigenVec3d a = {3.,-4., 0.}; -// EXPECT_EQ(a.norm(), 5.); - } + const TypeParam a = {Scalar(3), Scalar(-4), Scalar(0)}; + EXPECT_EQ(a.norm(), 5.); } -TEST(VEC_OP_TEST, Normalize) +TYPED_TEST(VEC_OP_TEST, Normalize) { - { - StdArray a = {3.,-4., 0.}; + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + TypeParam a = {Scalar(3), Scalar(-4), Scalar(0)}; a.normalize(); - EXPECT_DOUBLE_EQ(a[0], 3./5.); - EXPECT_DOUBLE_EQ(a[1], -4./5.); - EXPECT_DOUBLE_EQ(a[2], 0.); - EXPECT_DOUBLE_EQ(a.norm(), 1.); - } - - { -// EigenVec3d a = {3.,-4., 0.}; -// a.normalize(); -// EXPECT_DOUBLE_EQ(a[0], 3./5.); -// EXPECT_DOUBLE_EQ(a[1], -4./5.); -// EXPECT_DOUBLE_EQ(a[2], 0.); -// EXPECT_DOUBLE_EQ(a.norm(), 1.); - } + EXPECT_DOUBLE_EQ(a[0], Scalar(3)/Scalar(5)); + EXPECT_DOUBLE_EQ(a[1], Scalar(-4)/Scalar(5)); + EXPECT_DOUBLE_EQ(a[2], Scalar(0)); + EXPECT_DOUBLE_EQ(a.norm(), Scalar(1)); } -TEST(VEC_OP_TEST, DotProduct) +TYPED_TEST(VEC_OP_TEST, DotProduct) { - { - StdArray a = {1.,-2., 3.}; - StdArray b = {1.,-2., 3.}; - EXPECT_EQ(a.dot(b), 14.); - EXPECT_EQ(b.dot(a), 14.); - } - - { - StdArray a = {1.,2., -3.}; - StdArray b = {1.,2., -3.}; - EXPECT_EQ(a.dot(b), 14.); - EXPECT_EQ(b.dot(a), 14.); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + TypeParam a = {Scalar(3), Scalar(-4), Scalar(10)}; + TypeParam b = {Scalar(-1), Scalar(5), Scalar(2)}; + EXPECT_EQ(a.dot(b), -3); + EXPECT_EQ(b.dot(a), -3); } -TEST(VEC_OP_TEST, CrossProduct) +TYPED_TEST(VEC_OP_TEST, CrossProduct) { - { - StdArray a = {1.,2., 3.}; - StdArray b = {3.,2., 1.}; - StdArray c = a.cross(b); + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + const TypeParam a = {Scalar(1), Scalar(2), Scalar(3)}; + const TypeParam b = {Scalar(3), Scalar(2), Scalar(1)}; + const TypeParam c = a.cross(b); EXPECT_EQ(c[0], -4.); EXPECT_EQ(c[1], 8.); EXPECT_EQ(c[2], -4.); - } - - { -// EigenVec3d a = {1.,2., 3.}; -// EigenVec3d b = {3.,2., 1.}; -// EigenVec3d c = a.cross(b); -// EXPECT_EQ(c[0], -4.); -// EXPECT_EQ(c[1], 8.); -// EXPECT_EQ(c[2], -4.); - } } -TEST(VEC_OP_TEST, Equality) +TYPED_TEST(VEC_OP_TEST, Equality) { - StdArray vec1a = {1.,2., 3.}; - StdArray vec1b = {1.,2., 3.}; - EXPECT_TRUE(vec1a == vec1b); + using Scalar = typename cgogn::geometry::vector_traits::Scalar; -// EigenVec3d vec2a = {1.,2., 3.}; -// EigenVec3d vec2b = {1.,2., 3.}; -// EXPECT_TRUE(vec2a == vec2b); + const TypeParam a = {Scalar(1), Scalar(2), Scalar(3)}; + const TypeParam b= {Scalar(1), Scalar(2), Scalar(3)}; + EXPECT_TRUE(a == b); } -TEST(VEC_OP_TEST, DivScalar) +TYPED_TEST(VEC_OP_TEST, DivScalar) { - { - StdArray a = {2. ,4., 6.}; - StdArray c = a/2; - EXPECT_EQ(c[0], 1); - EXPECT_EQ(c[1], 2); - EXPECT_EQ(c[2], 3); - } - - { -// EigenVec3d a = {2. ,4., 6.}; -// EigenVec3d c = a/2; -// EXPECT_EQ(c[0], 1); -// EXPECT_EQ(c[1], 2); -// EXPECT_EQ(c[2], 3); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + const TypeParam a = {Scalar(2), Scalar(4), Scalar(6)}; + const TypeParam c = a/2; + EXPECT_EQ(c[0], 1); + EXPECT_EQ(c[1], 2); + EXPECT_EQ(c[2], 3); } From 252018ddece3a8e85aa13046a53cf2258e5d684a Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Sat, 27 Feb 2016 15:50:01 +0100 Subject: [PATCH 204/402] using TYPED_TEST in geometry tests. Signed-off-by: Etienne Schmitt --- cgogn/geometry/algos/normal.h | 5 +- cgogn/geometry/tests/algos/algos_test.cpp | 297 +++++-------- cgogn/geometry/tests/functions/area_test.cpp | 37 +- .../geometry/tests/functions/normal_test.cpp | 65 ++- .../tests/types/bounding_box_test.cpp | 129 +++--- cgogn/geometry/tests/types/plane_3d_test.cpp | 79 ++-- cgogn/geometry/tests/types/vec_test.cpp | 397 +++++++----------- 7 files changed, 388 insertions(+), 621 deletions(-) diff --git a/cgogn/geometry/algos/normal.h b/cgogn/geometry/algos/normal.h index 453b49c3..9625b6d4 100644 --- a/cgogn/geometry/algos/normal.h +++ b/cgogn/geometry/algos/normal.h @@ -30,7 +30,7 @@ #include #include #include - +#include namespace cgogn { @@ -53,7 +53,8 @@ inline VEC3 triangle_normal(const MAP& map, Cell f, const typename template inline VEC3 newell_normal(const MAP& map, Cell f, const typename MAP::template VertexAttributeHandler& position) { - VEC3 n{0.,0.,0.}; + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + VEC3 n{Scalar(0), Scalar(0), Scalar(0)}; map.foreach_incident_vertex(f, [&] (Cell v) { const VEC3& p = position[v.dart]; diff --git a/cgogn/geometry/tests/algos/algos_test.cpp b/cgogn/geometry/tests/algos/algos_test.cpp index 7e6c0041..34c60c19 100644 --- a/cgogn/geometry/tests/algos/algos_test.cpp +++ b/cgogn/geometry/tests/algos/algos_test.cpp @@ -37,235 +37,134 @@ #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) -using StdArray = cgogn::geometry::Vec_T>; +using StdArrayf = cgogn::geometry::Vec_T>; +using StdArrayd = cgogn::geometry::Vec_T>; +using EigenVec3f = Eigen::Vector3f; using EigenVec3d = Eigen::Vector3d; +using VecTypes = testing::Types; using CMap2 = cgogn::CMap2; template using VertexAttributeHandler = CMap2::VertexAttributeHandler; - using Vertex = CMap2::Vertex; using Edge = CMap2::Edge; using Face = CMap2::Face; -TEST(Algos_TEST, TriangleArea) +template +class Algos_TEST : public testing::Test { - { - CMap2 map; - cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); - VertexAttributeHandler vertex_position = map.get_attribute("position"); - const double area = cgogn::geometry::triangle_area(map, *map.begin(), vertex_position); - const double cf_area = cgogn::geometry::convex_face_area(map, *map.begin(), vertex_position); - EXPECT_DOUBLE_EQ(area, 12.5); - EXPECT_DOUBLE_EQ(cf_area, 12.5); - } - { -// CMap2 map; -// cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); -// VertexAttributeHandler vertex_position = map.get_attribute("position"); -// const double area = cgogn::geometry::triangle_area(map, *map.begin(), vertex_position); -// const double cf_area = cgogn::geometry::convex_face_area(map, *map.begin(), vertex_position); -// EXPECT_DOUBLE_EQ(area, 12.5); -// EXPECT_DOUBLE_EQ(cf_area, 12.5); - } -} +protected : + CMap2 map2_; +}; -TEST(Algos_TEST, QuadArea) -{ - { - CMap2 map; - cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); - VertexAttributeHandler vertex_position = map.get_attribute("position"); - const double area = cgogn::geometry::convex_face_area(map, *map.begin(), vertex_position); - EXPECT_DOUBLE_EQ(area, 10); - } - { -// CMap2 map; -// cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); -// VertexAttributeHandler vertex_position = map.get_attribute("position"); -// const double area = cgogn::geometry::convex_face_area(map, *map.begin(), vertex_position); -// EXPECT_DOUBLE_EQ(area, 10); - } -} +TYPED_TEST_CASE(Algos_TEST, VecTypes ); -TEST(Algos_TEST, TriangleCentroid) +TYPED_TEST(Algos_TEST, TriangleArea) { - { - CMap2 map; - cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); - VertexAttributeHandler vertex_position = map.get_attribute("position"); - const StdArray centroid = cgogn::geometry::centroid(map, CMap2::Face(*map.begin()), vertex_position); - EXPECT_DOUBLE_EQ(centroid[0], 5.0/3.0); - EXPECT_DOUBLE_EQ(centroid[1], 5.0/3.0); - EXPECT_DOUBLE_EQ(centroid[2], 0); - } - - { -// CMap2 map; -// cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); -// VertexAttributeHandler vertex_position = map.get_attribute("position"); -// const EigenVec3d centroid = cgogn::geometry::centroid(map, CMap2::Face(*map.begin()), vertex_position); -// EXPECT_DOUBLE_EQ(centroid[0], 5.0/3.0); -// EXPECT_DOUBLE_EQ(centroid[1], 5.0/3.0); -// EXPECT_DOUBLE_EQ(centroid[2], 0); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + cgogn::io::import_surface(this->map2_, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); + VertexAttributeHandler vertex_position = this->map2_.template get_attribute("position"); + const Scalar area = cgogn::geometry::triangle_area(this->map2_, *this->map2_.begin(), vertex_position); + const Scalar cf_area = cgogn::geometry::convex_face_area(this->map2_, *this->map2_.begin(), vertex_position); + EXPECT_DOUBLE_EQ(area, Scalar(12.5f)); + EXPECT_DOUBLE_EQ(cf_area, Scalar(12.5f)); } -TEST(Algos_TEST, QuadCentroid) +TYPED_TEST(Algos_TEST, QuadArea) { - { - CMap2 map; - cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); - VertexAttributeHandler vertex_position = map.get_attribute("position"); - const StdArray centroid = cgogn::geometry::centroid(map, CMap2::Face(*map.begin()), vertex_position); - EXPECT_DOUBLE_EQ(centroid[0], 2.5); - EXPECT_DOUBLE_EQ(centroid[1], 1); - EXPECT_DOUBLE_EQ(centroid[2], 0); - } - - { -// CMap2 map; -// cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); -// VertexAttributeHandler vertex_position = map.get_attribute("position"); -// const EigenVec3d centroid = cgogn::geometry::centroid(map, CMap2::Face(*map.begin()), vertex_position); -// EXPECT_DOUBLE_EQ(centroid[0], 2.5); -// EXPECT_DOUBLE_EQ(centroid[1], 1); -// EXPECT_DOUBLE_EQ(centroid[2], 0); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + cgogn::io::import_surface(this->map2_, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); + VertexAttributeHandler vertex_position = this->map2_.template get_attribute("position"); + const Scalar area = cgogn::geometry::convex_face_area(this->map2_, *this->map2_.begin(), vertex_position); + EXPECT_DOUBLE_EQ(area, Scalar(10)); } -TEST(Algos_TEST, TriangleNormal) +TYPED_TEST(Algos_TEST, TriangleCentroid) { - { - CMap2 map; - cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); - VertexAttributeHandler vertex_position = map.get_attribute("position"); - const StdArray& n1 = cgogn::geometry::triangle_normal(map, CMap2::Face(*map.begin()), vertex_position); - const StdArray& n2 = cgogn::geometry::face_normal(map, CMap2::Face(*map.begin()), vertex_position); - EXPECT_TRUE(cgogn::almost_equal_relative(n1[0], n2[0])); - EXPECT_TRUE(cgogn::almost_equal_relative(n1[1], n2[1])); - EXPECT_TRUE(cgogn::almost_equal_relative(n1[2], n2[2])); + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + cgogn::io::import_surface(this->map2_, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); + VertexAttributeHandler vertex_position = this->map2_.template get_attribute("position"); + const TypeParam centroid = cgogn::geometry::centroid(this->map2_, CMap2::Face(*this->map2_.begin()), vertex_position); + EXPECT_DOUBLE_EQ(centroid[0], Scalar(5)/Scalar(3)); + EXPECT_DOUBLE_EQ(centroid[1], Scalar(5)/Scalar(3)); + EXPECT_DOUBLE_EQ(centroid[2], Scalar(0)); +} - const StdArray& cross = n1.cross(StdArray(0.,0.,1.)); - EXPECT_TRUE(cgogn::almost_equal_relative(cross[0], 0.)); - EXPECT_TRUE(cgogn::almost_equal_relative(cross[1], 0.)); - EXPECT_TRUE(cgogn::almost_equal_relative(cross[2], 0.)); - } - { -// CMap2 map; -// cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); -// VertexAttributeHandler vertex_position = map.get_attribute("position"); -// const EigenVec3d& n1 = cgogn::geometry::triangle_normal(map, CMap2::Face(*map.begin()), vertex_position); -// const EigenVec3d& n2 = cgogn::geometry::face_normal(map, CMap2::Face(*map.begin()), vertex_position); -// EXPECT_TRUE(cgogn::almost_equal_relative(n1[0], n2[0])); -// EXPECT_TRUE(cgogn::almost_equal_relative(n1[1], n2[1])); -// EXPECT_TRUE(cgogn::almost_equal_relative(n1[2], n2[2])); +TYPED_TEST(Algos_TEST, QuadCentroid) +{ + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + cgogn::io::import_surface(this->map2_, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); + VertexAttributeHandler vertex_position = this->map2_.template get_attribute("position"); + const TypeParam centroid = cgogn::geometry::centroid(this->map2_, CMap2::Face(*this->map2_.begin()), vertex_position); + EXPECT_DOUBLE_EQ(centroid[0], Scalar(2.5f)); + EXPECT_DOUBLE_EQ(centroid[1], Scalar(1)); + EXPECT_DOUBLE_EQ(centroid[2], Scalar(0)); +} -// const EigenVec3d& cross = n1.cross(EigenVec3d(0,0,1)); -// EXPECT_TRUE(cgogn::almost_equal_relative(cross[0], 0.)); -// EXPECT_TRUE(cgogn::almost_equal_relative(cross[1], 0.)); -// EXPECT_TRUE(cgogn::almost_equal_relative(cross[2], 0.)); - } +TYPED_TEST(Algos_TEST, TriangleNormal) +{ + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + cgogn::io::import_surface(this->map2_, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); + VertexAttributeHandler vertex_position = this->map2_.template get_attribute("position"); + const TypeParam& n1 = cgogn::geometry::triangle_normal(this->map2_, CMap2::Face(*this->map2_.begin()), vertex_position); + const TypeParam& n2 = cgogn::geometry::face_normal(this->map2_, CMap2::Face(*this->map2_.begin()), vertex_position); + EXPECT_TRUE(cgogn::almost_equal_relative(n1[0], n2[0])); + EXPECT_TRUE(cgogn::almost_equal_relative(n1[1], n2[1])); + EXPECT_TRUE(cgogn::almost_equal_relative(n1[2], n2[2])); + + const TypeParam& cross = n1.cross(TypeParam(Scalar(0), Scalar(0), Scalar(1))); + EXPECT_TRUE(cgogn::almost_equal_relative(cross[0], Scalar(0))); + EXPECT_TRUE(cgogn::almost_equal_relative(cross[1], Scalar(0))); + EXPECT_TRUE(cgogn::almost_equal_relative(cross[2], Scalar(0))); } -TEST(Algos_TEST, QuadNormal) +TYPED_TEST(Algos_TEST, QuadNormal) { - { - CMap2 map; - cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); - VertexAttributeHandler vertex_position = map.get_attribute("position"); - const StdArray& n1 = cgogn::geometry::face_normal(map, CMap2::Face(*map.begin()), vertex_position); - const StdArray& cross = n1.cross(StdArray(0.,0.,1.)); - EXPECT_TRUE(cgogn::almost_equal_relative(cross[0], 0.)); - EXPECT_TRUE(cgogn::almost_equal_relative(cross[1], 0.)); - EXPECT_TRUE(cgogn::almost_equal_relative(cross[2], 0.)); - } - { -// CMap2 map; -// cgogn::io::import_surface(map, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); -// VertexAttributeHandler vertex_position = map.get_attribute("position"); -// const EigenVec3d& n1 = cgogn::geometry::triangle_normal(map, CMap2::Face(*map.begin()), vertex_position); -// const EigenVec3d& cross = n1.cross(EigenVec3d(0,0,1)); -// EXPECT_TRUE(cgogn::almost_equal_relative(cross[0], 0.)); -// EXPECT_TRUE(cgogn::almost_equal_relative(cross[1], 0.)); -// EXPECT_TRUE(cgogn::almost_equal_relative(cross[2], 0.)); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + cgogn::io::import_surface(this->map2_, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); + VertexAttributeHandler vertex_position = this->map2_.template get_attribute("position"); + const TypeParam& n1 = cgogn::geometry::face_normal(this->map2_, CMap2::Face(*this->map2_.begin()), vertex_position); + const TypeParam& cross = n1.cross(TypeParam(Scalar(0), Scalar(0), Scalar(1))); + EXPECT_TRUE(cgogn::almost_equal_relative(cross[0], Scalar(0))); + EXPECT_TRUE(cgogn::almost_equal_relative(cross[1], Scalar(0))); + EXPECT_TRUE(cgogn::almost_equal_relative(cross[2], Scalar(0))); } -TEST(Algos_TEST, EarTriangulation) +TYPED_TEST(Algos_TEST, EarTriangulation) { - // with array + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + VertexAttributeHandler vertex_position = this->map2_.template add_attribute("position"); + + Face f = this->map2_.add_face(5); + cgogn::Dart d = f.dart; + + vertex_position[Vertex(d)] = TypeParam(Scalar(0), Scalar(0), Scalar(0)); + d = this->map2_.phi1(d); + vertex_position[Vertex(d)] = TypeParam(Scalar(10), Scalar(0), Scalar(0)); + d = this->map2_.phi1(d); + vertex_position[Vertex(d)] = TypeParam(Scalar(10), Scalar(10), Scalar(0)); + d = this->map2_.phi1(d); + vertex_position[Vertex(d)] = TypeParam(Scalar(5), Scalar(5), Scalar(0)); + d = this->map2_.phi1(d); + vertex_position[Vertex(d)] = TypeParam(Scalar(0), Scalar(10), Scalar(0)); + + std::vector indices; + cgogn::geometry::compute_ear_triangulation(this->map2_,f,vertex_position,indices); + EXPECT_TRUE(indices.size() == 9); + + Scalar area = 0; + for (size_t i=0; i vertex_position = map.add_attribute("position"); - - Face f = map.add_face(5); - cgogn::Dart d = f.dart; - - vertex_position[Vertex(d)] = StdArray(0.0,0.0,0.0); - d = map.phi1(d); - vertex_position[Vertex(d)] = StdArray(10.0,0.0,0.0); - d = map.phi1(d); - vertex_position[Vertex(d)] = StdArray(10.0,10.0,0.0); - d = map.phi1(d); - vertex_position[Vertex(d)] = StdArray(5.0,5.0,0.0); - d = map.phi1(d); - vertex_position[Vertex(d)] = StdArray(0.0,10.0,0.0); - - std::vector indices; - cgogn::geometry::compute_ear_triangulation(map,f,vertex_position,indices); - EXPECT_TRUE(indices.size() == 9); - - double area = 0.0; - for (size_t i=0; i(map,f,vertex_position); - EXPECT_TRUE(map.nb_cells()==4); - EXPECT_TRUE(map.nb_cells()==7); + const TypeParam& A = vertex_position[indices[i]]; + const TypeParam& B = vertex_position[indices[i+1]]; + const TypeParam& C = vertex_position[indices[i+2]]; + area += cgogn::geometry::triangle_area(A,B,C); } - // with Eigen - { - CMap2 map; - VertexAttributeHandler vertex_position = map.add_attribute("position"); + EXPECT_DOUBLE_EQ(area,75.0); - Face f = map.add_face(5); - cgogn::Dart d = f.dart; - - vertex_position[CMap2::Vertex(d)] = EigenVec3d(0,0,0); - d = map.phi1(d); - vertex_position[CMap2::Vertex(d)] = EigenVec3d(10,0,0); - d = map.phi1(d); - vertex_position[CMap2::Vertex(d)] = EigenVec3d(10,10,0); - d = map.phi1(d); - vertex_position[CMap2::Vertex(d)] = EigenVec3d(5,5,0); - d = map.phi1(d); - vertex_position[CMap2::Vertex(d)] = EigenVec3d(0,10,0); - - std::vector indices; - cgogn::geometry::compute_ear_triangulation(map,f,vertex_position,indices); - EXPECT_TRUE(indices.size() == 9); - - double area = 0.0; - for (size_t i=0; i(map,f,vertex_position); - EXPECT_TRUE(map.nb_cells()==4); - EXPECT_TRUE(map.nb_cells()==7); - } + cgogn::geometry::apply_ear_triangulation(this->map2_,f,vertex_position); + EXPECT_TRUE(this->map2_.template nb_cells()==4); + EXPECT_TRUE(this->map2_.template nb_cells()==7); } diff --git a/cgogn/geometry/tests/functions/area_test.cpp b/cgogn/geometry/tests/functions/area_test.cpp index 8591000e..b40c10ae 100644 --- a/cgogn/geometry/tests/functions/area_test.cpp +++ b/cgogn/geometry/tests/functions/area_test.cpp @@ -23,25 +23,30 @@ #include #include +#include #include + #include -#include -using StdArray = cgogn::geometry::Vec_T>; -//using EigenVec3d = Eigen::Vector3d; +using StdArrayf = cgogn::geometry::Vec_T>; +using StdArrayd = cgogn::geometry::Vec_T>; +using EigenVec3f = Eigen::Vector3f; +using EigenVec3d = Eigen::Vector3d; +using VecTypes = testing::Types; + +template +class Area_TEST : public testing::Test +{ +}; + + +TYPED_TEST_CASE(Area_TEST, VecTypes ); -TEST(Area_TEST, TriangleArea) +TYPED_TEST(Area_TEST, TriangleArea) { - { - StdArray p0(0.,0.,0.); - StdArray p1(2.,0.,0.); - StdArray p2(0.,2.,0.); - EXPECT_DOUBLE_EQ(cgogn::geometry::triangle_area(p0,p1,p2), 2.0); - } - { -// EigenVec3d p0(0,0,0); -// EigenVec3d p1(2,0,0); -// EigenVec3d p2(0,2,0); -// EXPECT_DOUBLE_EQ(cgogn::geometry::triangle_area(p0,p1,p2), 2.0); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + TypeParam p0(Scalar(0), Scalar(0), Scalar(0)); + TypeParam p1(Scalar(2), Scalar(0), Scalar(0)); + TypeParam p2(Scalar(0), Scalar(2), Scalar(0)); + EXPECT_DOUBLE_EQ(cgogn::geometry::triangle_area(p0,p1,p2), Scalar(2)); } diff --git a/cgogn/geometry/tests/functions/normal_test.cpp b/cgogn/geometry/tests/functions/normal_test.cpp index 1fa1b70b..a8c7545c 100644 --- a/cgogn/geometry/tests/functions/normal_test.cpp +++ b/cgogn/geometry/tests/functions/normal_test.cpp @@ -25,41 +25,40 @@ #include #include #include +#include + #include -#include -using StdArray = cgogn::geometry::Vec_T>; -//using EigenVec3d = Eigen::Vector3d; +using StdArrayf = cgogn::geometry::Vec_T>; +using StdArrayd = cgogn::geometry::Vec_T>; +using EigenVec3f = Eigen::Vector3f; +using EigenVec3d = Eigen::Vector3d; +using VecTypes = testing::Types; + +template +class Normal_TEST : public testing::Test {}; + +TYPED_TEST_CASE(Normal_TEST, VecTypes ); + -TEST(Normal_TEST, TriangleNormal) +TYPED_TEST(Normal_TEST, TriangleNormal) { - { - StdArray p0(1.,3.,-5.); - StdArray p1(7.,-4.,0.1); - StdArray p2(-15.,-2.,15.); - StdArray n = cgogn::geometry::triangle_normal(p0,p1,p2); - cgogn::almost_equal_relative(n.dot(p1-p0), 0.); -// EXPECT_TRUE(cgogn::almost_equal_relative(n.dot(p1-p0),0.)); // is false ! - EXPECT_TRUE(cgogn::almost_equal_absolute(n.dot(p1-p0), 0., 1e-8)); - EXPECT_TRUE(cgogn::almost_equal_relative(n.dot(p2-p0), 0.)); - EXPECT_TRUE(cgogn::almost_equal_relative(n.dot(p2-p1), 0.)); -// EXPECT_DOUBLE_EQ(n.dot(p1-p0), 0.); // is false ! - EXPECT_NEAR(n.dot(p1-p0), 0., 1e-8); - EXPECT_DOUBLE_EQ(n.dot(p2-p0), 0.); - EXPECT_DOUBLE_EQ(n.dot(p2-p1), 0.); - } - { -// EigenVec3d p0(1,3,-5); -// EigenVec3d p1(7,-4,0.1); -// EigenVec3d p2(-15,-2,15); -// EigenVec3d n = cgogn::geometry::triangle_normal(p0,p1,p2); -//// EXPECT_TRUE(cgogn::almost_equal_relative(n.dot(p1-p0),0.)); // is false ! -// EXPECT_TRUE(cgogn::almost_equal_absolute(n.dot(p1-p0), 0., 1e-8)); -// EXPECT_TRUE(cgogn::almost_equal_relative(n.dot(p2-p0), 0.)); -// EXPECT_TRUE(cgogn::almost_equal_relative(n.dot(p2-p1), 0.)); -//// EXPECT_DOUBLE_EQ(n.dot(p1-p0),0); // is false ! -// EXPECT_NEAR(n.dot(p1-p0), 0., 1e-8); -// EXPECT_DOUBLE_EQ(n.dot(p2-p0), 0.); -// EXPECT_DOUBLE_EQ(n.dot(p2-p1), 0.); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + const Scalar tolerence = std::is_same::value ? Scalar(1e-8) : Scalar(1e-4f); + TypeParam p0(Scalar(1), Scalar(3), Scalar(-5)); + TypeParam p1(Scalar(7), Scalar(-4), Scalar(0.1f)); + TypeParam p2(Scalar(-15), Scalar(-2), Scalar(15));; + + TypeParam n = cgogn::geometry::triangle_normal(p0,p1,p2); + + cgogn::almost_equal_relative(n.dot(p1-p0), Scalar(0)); + // EXPECT_TRUE(cgogn::almost_equal_relative(n.dot(p1-p0),0.)); // is false ! + EXPECT_TRUE(cgogn::almost_equal_absolute(n.dot(p1-p0), Scalar(0), tolerence)); + EXPECT_TRUE(cgogn::almost_equal_relative(n.dot(p2-p0), Scalar(0))); + EXPECT_TRUE(cgogn::almost_equal_relative(n.dot(p2-p1), Scalar(0))); + // EXPECT_DOUBLE_EQ(n.dot(p1-p0), 0.); // is false ! + EXPECT_NEAR(n.dot(p1-p0), Scalar(0), tolerence); + EXPECT_DOUBLE_EQ(n.dot(p2-p0), Scalar(0)); + EXPECT_DOUBLE_EQ(n.dot(p2-p1), Scalar(0)); } diff --git a/cgogn/geometry/tests/types/bounding_box_test.cpp b/cgogn/geometry/tests/types/bounding_box_test.cpp index 70c49a90..be930782 100644 --- a/cgogn/geometry/tests/types/bounding_box_test.cpp +++ b/cgogn/geometry/tests/types/bounding_box_test.cpp @@ -21,100 +21,75 @@ * * *******************************************************************************/ +#include #include +#include + #include -#include -#include -using StdArray = cgogn::geometry::Vec_T>; -//using EigenVec3d = Eigen::Vector3d; -using BoundingBox_Array = cgogn::geometry::BoundingBox; -//using BoundingBox_Eigen = cgogn::geometry::BoundingBox; +using StdArrayf = cgogn::geometry::Vec_T>; +using StdArrayd = cgogn::geometry::Vec_T>; +using EigenVec3f = Eigen::Vector3f; +using EigenVec3d = Eigen::Vector3d; +using VecTypes = testing::Types; + +template +class BoundingBox_TEST : public testing::Test +{ +protected : + cgogn::geometry::BoundingBox bb_; +}; + + +TYPED_TEST_CASE(BoundingBox_TEST, VecTypes ); + TEST(BoundingBox_TEST, NameOfType) { - EXPECT_EQ(cgogn::name_of_type(BoundingBox_Array()), "cgogn::geometry::BoundingBox>>"); -// EXPECT_EQ(cgogn::name_of_type(BoundingBox_Eigen()), "cgogn::geometry::BoundingBox>"); + EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::BoundingBox()), "cgogn::geometry::BoundingBox>>"); + EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::BoundingBox()), "cgogn::geometry::BoundingBox>"); + EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::BoundingBox()), "cgogn::geometry::BoundingBox>>"); + EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::BoundingBox()), "cgogn::geometry::BoundingBox>"); } -TEST(BoundingBox_TEST, Basics) +TYPED_TEST(BoundingBox_TEST, Basics) { - { - BoundingBox_Array bb; - bb.add_point(StdArray({0.5,0.4,0.3})); - bb.add_point(StdArray({-1.,-2.,-3.})); - bb.add_point(StdArray({1.,2.,3.})); - - EXPECT_EQ(bb.min(), StdArray({-1.,-2.,-3.})); - EXPECT_EQ(bb.max(), StdArray({1.,2.,3.})); - EXPECT_EQ(bb.max_size(), 6); - EXPECT_EQ(bb.min_size(), 2); - EXPECT_TRUE(cgogn::almost_equal_relative(bb.diag_size(), std::sqrt(2.0*2+4*4+6*6))); - - std::cout << bb.center()[0] << "," << bb.center()[1] << "," << bb.center()[2] << std::endl; - EXPECT_EQ(bb.center(), StdArray({0.,0.,0.})); - } - { -// BoundingBox_Eigen bb; -// bb.add_point(EigenVec3d(0.5,0.4,0.3)); -// bb.add_point(EigenVec3d(-1,2,-3)); -// bb.add_point(EigenVec3d(1,-2,3)); - -// EXPECT_EQ(bb.min(), EigenVec3d(-1,-2,-3)); -// EXPECT_EQ(bb.max(), EigenVec3d(1,2,3)); -// EXPECT_EQ(bb.max_size(), 6); -// EXPECT_EQ(bb.min_size(), 2); -// EXPECT_TRUE(cgogn::almost_equal_relative(bb.diag_size(), std::sqrt(2.0*2+4*4+6*6))); -// EXPECT_EQ(bb.center(), EigenVec3d(0,0,0)); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + this->bb_.add_point(TypeParam({Scalar(0.5f), Scalar(0.4f), Scalar(0.3f)})); + this->bb_.add_point(TypeParam({Scalar(-1), Scalar(-2), Scalar(-3)})); + this->bb_.add_point(TypeParam({Scalar(1), Scalar(2), Scalar(3)})); + + EXPECT_EQ(this->bb_.min(), TypeParam({Scalar(-1), Scalar(-2), Scalar(-3)})); + EXPECT_EQ(this->bb_.max(), TypeParam({Scalar(1), Scalar(2), Scalar(3)})); + EXPECT_EQ(this->bb_.max_size(), Scalar(6)); + EXPECT_EQ(this->bb_.min_size(), Scalar(2)); + EXPECT_TRUE(cgogn::almost_equal_relative(this->bb_.diag_size(), std::sqrt(Scalar(2*2+4*4+6*6)))); + EXPECT_EQ(this->bb_.center(), TypeParam({Scalar(0), Scalar(0), Scalar(0)})); } -TEST(BoundingBox_TEST, testing) +TYPED_TEST(BoundingBox_TEST, testing) { - { - BoundingBox_Array bb; - bb.add_point(StdArray({0.5,0.4,0.3})); - bb.add_point(StdArray({-1.,-2.,-3.})); - bb.add_point(StdArray({1.,2.,3.})); - - EXPECT_TRUE(bb.contains(StdArray({1.,1.,1.}))); - - BoundingBox_Array bb2; - bb2.add_point(StdArray({0.,0.,0.})); - bb2.add_point(StdArray({4.,5.,2.})); - - EXPECT_TRUE(bb.intersects(bb2)); - - BoundingBox_Array bb3; - bb3.add_point(StdArray({0.,0.,0.})); - bb3.add_point(StdArray({1.,1.,1.})); - - EXPECT_TRUE(bb.contains(bb3)); + using Scalar = typename cgogn::geometry::vector_traits::Scalar; - EXPECT_TRUE(bb.ray_intersect(StdArray({-9.,-9.,-9.}), StdArray({1.,1.,1.}))); - EXPECT_FALSE(bb.ray_intersect(StdArray({-9.,-9.,-9.}), StdArray({1.,-1.,0.}))); - } - { -// BoundingBox_Eigen bb; -// bb.add_point(EigenVec3d(0.5,0.4,0.3)); -// bb.add_point(EigenVec3d(-1,2,-3)); -// bb.add_point(EigenVec3d(1,-2,3)); + this->bb_.add_point(TypeParam({Scalar(0.5f), Scalar(0.4f), Scalar(0.3f)})); + this->bb_.add_point(TypeParam({Scalar(-1), Scalar(-2), Scalar(-3)})); + this->bb_.add_point(TypeParam({Scalar(1), Scalar(2), Scalar(3)})); -// EXPECT_TRUE(bb.contains(EigenVec3d(1,1,1))); + EXPECT_TRUE(this->bb_.contains(TypeParam({Scalar(1), Scalar(1), Scalar(1)}))); -// BoundingBox_Eigen bb2; -// bb2.add_point(EigenVec3d(0,0,0)); -// bb2.add_point(EigenVec3d(4,5,2)); + cgogn::geometry::BoundingBox bb2; + bb2.add_point(TypeParam({Scalar(0), Scalar(0), Scalar(0)})); + bb2.add_point(TypeParam({Scalar(4), Scalar(5), Scalar(2)})); -// EXPECT_TRUE(bb.intersects(bb2)); + EXPECT_TRUE(this->bb_.intersects(bb2)); -// BoundingBox_Eigen bb3; -// bb3.add_point(EigenVec3d(0,0,0)); -// bb3.add_point(EigenVec3d(1,1,1)); + cgogn::geometry::BoundingBox bb3; + bb3.add_point(TypeParam({Scalar(0), Scalar(0), Scalar(0)})); + bb3.add_point(TypeParam({Scalar(1), Scalar(1), Scalar(1)})); -// EXPECT_TRUE(bb.contains(bb3)); + EXPECT_TRUE(this->bb_.contains(bb3)); -// EXPECT_TRUE(bb.ray_intersect(EigenVec3d(-9,-9,-9), EigenVec3d(1,1,1))); -// EXPECT_FALSE(bb.ray_intersect(EigenVec3d(-9,-9,-9), EigenVec3d(1,-1,0))); - } + EXPECT_TRUE(this->bb_.ray_intersect(TypeParam({Scalar(-9), Scalar(-9), Scalar(-9)}), TypeParam({Scalar(1), Scalar(1), Scalar(1)}))); + EXPECT_FALSE(this->bb_.ray_intersect(TypeParam({Scalar(-9), Scalar(-9), Scalar(-9)}), TypeParam({Scalar(1), Scalar(-1), Scalar(0)}))); } diff --git a/cgogn/geometry/tests/types/plane_3d_test.cpp b/cgogn/geometry/tests/types/plane_3d_test.cpp index 8867d4cd..b9234c98 100644 --- a/cgogn/geometry/tests/types/plane_3d_test.cpp +++ b/cgogn/geometry/tests/types/plane_3d_test.cpp @@ -22,58 +22,51 @@ *******************************************************************************/ #include +#include + #include -#include -using StdArray = cgogn::geometry::Vec_T>; -//using EigenVec3d = Eigen::Vector3d; -using Plane3D_Array = cgogn::geometry::Plane3D; -//using Plane3D_Eigen = cgogn::geometry::Plane3D; +using StdArrayf = cgogn::geometry::Vec_T>; +using StdArrayd = cgogn::geometry::Vec_T>; +using EigenVec3f = Eigen::Vector3f; +using EigenVec3d = Eigen::Vector3d; +using VecTypes = testing::Types; + + +template +class Plane3D_TEST : public testing::Test {}; + +TYPED_TEST_CASE(Plane3D_TEST, VecTypes ); TEST(Plane3D_TEST, NameOfType) { - EXPECT_EQ(cgogn::name_of_type(Plane3D_Array(StdArray(),0.)), "cgogn::geometry::Plane3D>>"); -// EXPECT_EQ(cgogn::name_of_type(Plane3D_Eigen(EigenVec3d(),0.)), "cgogn::geometry::Plane3D>"); + EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::Plane3D(StdArrayf(),0)), "cgogn::geometry::Plane3D>>"); + EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::Plane3D(EigenVec3f(),0)), "cgogn::geometry::Plane3D>"); + EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::Plane3D(StdArrayd(),0)), "cgogn::geometry::Plane3D>>"); + EXPECT_EQ(cgogn::name_of_type(cgogn::geometry::Plane3D(EigenVec3d(),0)), "cgogn::geometry::Plane3D>"); } -TEST(Plane3D_TEST, Project) +TYPED_TEST(Plane3D_TEST, Project) { - { - Plane3D_Array plane(StdArray{4.,0.,0.}, StdArray{0.,0.,0.}); - StdArray p{5.,8.,12.}; - plane.project(p); - EXPECT_EQ(p[0], 0.); - EXPECT_EQ(p[1], 8.); - EXPECT_EQ(p[2], 12.); - } - { -// Plane3D_Eigen plane(EigenVec3d{4,0,0}, EigenVec3d{0,0,0}); -// EigenVec3d p{5,8,12}; -// plane.project(p); -// EXPECT_EQ(p[0], 0.); -// EXPECT_EQ(p[1], 8.); -// EXPECT_EQ(p[2], 12.); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + cgogn::geometry::Plane3D plane(TypeParam{Scalar(4), Scalar(0), Scalar(0)}, TypeParam{Scalar(0), Scalar(0), Scalar(0)}); + TypeParam p{Scalar(5), Scalar(8), Scalar(12)}; + plane.project(p); + EXPECT_EQ(p[0], Scalar(0)); + EXPECT_EQ(p[1], Scalar(8)); + EXPECT_EQ(p[2], Scalar(12)); } -TEST(Plane3D_TEST, Orient) +TYPED_TEST(Plane3D_TEST, Orient) { - { - Plane3D_Array plane(StdArray{0.,0.,15.}, StdArray{0.,0.,0.}); - StdArray p1{546854.,864.,12.}; - StdArray p2{-5.,886486.,-12.}; - StdArray p3{44552.,7.,0.}; - EXPECT_EQ(plane.orient(p1), cgogn::geometry::Orientation3D::OVER); - EXPECT_EQ(plane.orient(p2), cgogn::geometry::Orientation3D::UNDER); - EXPECT_EQ(plane.orient(p3), cgogn::geometry::Orientation3D::ON); - } - { -// EigenVec3d p1{546854,864,12}; -// EigenVec3d p2{-5,886486,-12}; -// EigenVec3d p3{44552,7,0}; -// EXPECT_EQ(plane.orient(p1), cgogn::geometry::Orientation3D::OVER); -// EXPECT_EQ(plane.orient(p2), cgogn::geometry::Orientation3D::UNDER); -// Plane3D_Eigen plane(EigenVec3d{0,0,15}, EigenVec3d{0,0,0}); -// EXPECT_EQ(plane.orient(p3), cgogn::geometry::Orientation3D::ON); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + cgogn::geometry::Plane3D plane(TypeParam{Scalar(0), Scalar(0), Scalar(15)}, TypeParam{Scalar(0), Scalar(0), Scalar(0)}); + TypeParam p1{Scalar(546854), Scalar(864), Scalar(12)}; + TypeParam p2{Scalar(-5), Scalar(886486), Scalar(-12)}; + TypeParam p3{Scalar(44552), Scalar(7), Scalar(0)}; + EXPECT_EQ(plane.orient(p1), cgogn::geometry::Orientation3D::OVER); + EXPECT_EQ(plane.orient(p2), cgogn::geometry::Orientation3D::UNDER); + EXPECT_EQ(plane.orient(p3), cgogn::geometry::Orientation3D::ON); } diff --git a/cgogn/geometry/tests/types/vec_test.cpp b/cgogn/geometry/tests/types/vec_test.cpp index e3cc6e83..a61de2e3 100644 --- a/cgogn/geometry/tests/types/vec_test.cpp +++ b/cgogn/geometry/tests/types/vec_test.cpp @@ -23,332 +23,227 @@ #include #include +#include #include -using StdArray = cgogn::geometry::Vec_T>; -//using EigenVec3d = Eigen::Vector3d; +using StdArrayf = cgogn::geometry::Vec_T>; +using StdArrayd = cgogn::geometry::Vec_T>; +using EigenVec3f = Eigen::Vector3f; +using EigenVec3d = Eigen::Vector3d; +using VecTypes = testing::Types; + +template +class VEC_OP_TEST : public testing::Test +{ +}; + +TYPED_TEST_CASE(VEC_OP_TEST, VecTypes ); TEST(VEC_OP_TEST, CGOGN_Typename) { - EXPECT_EQ(cgogn::name_of_type(StdArray()),"cgogn::geometry::Vec_T>"); -// EXPECT_EQ(cgogn::name_of_type(EigenVec3d()), "Eigen::Matrix"); + EXPECT_EQ(cgogn::name_of_type(StdArrayf()),"cgogn::geometry::Vec_T>"); + EXPECT_EQ(cgogn::name_of_type(EigenVec3f()), "Eigen::Matrix"); + EXPECT_EQ(cgogn::name_of_type(StdArrayd()),"cgogn::geometry::Vec_T>"); + EXPECT_EQ(cgogn::name_of_type(EigenVec3d()), "Eigen::Matrix"); } -TEST(VEC_OP_TEST, Constructor) +TYPED_TEST(VEC_OP_TEST, Constructor) { - StdArray vec1{0.,0.,0.}; - EXPECT_EQ(vec1[0],0); - EXPECT_EQ(vec1[1],0); - EXPECT_EQ(vec1[2],0); -// EigenVec3d vec2 = {0.,0.,0.}; -// EXPECT_EQ(vec2[0],0); -// EXPECT_EQ(vec2[1],0); -// EXPECT_EQ(vec2[2],0); + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + const Scalar zero(0); + const TypeParam vec1{zero, zero, zero}; + EXPECT_EQ(vec1[0],zero); + EXPECT_EQ(vec1[1],zero); + EXPECT_EQ(vec1[2],zero); } -TEST(VEC_OP_TEST, CopyConstructor) +TYPED_TEST(VEC_OP_TEST, CopyConstructor) { - StdArray vec1a = {1.,2., 3.}; - StdArray vec1b(vec1a); + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + const TypeParam vec1a = {Scalar(1), Scalar(2), Scalar(3)}; + TypeParam vec1b(vec1a); EXPECT_EQ(vec1a[0], vec1b[0]); EXPECT_EQ(vec1a[1], vec1b[1]); EXPECT_EQ(vec1a[2], vec1b[2]); -// EigenVec3d vec2a = {1.,2., 3.}; -// EigenVec3d vec2b(vec2a); -// EXPECT_EQ(vec2a[0], vec2b[0]); -// EXPECT_EQ(vec2a[1], vec2b[1]); -// EXPECT_EQ(vec2a[2], vec2b[2]); } -TEST(VEC_OP_TEST, AssignConstructor) +TYPED_TEST(VEC_OP_TEST, AssignConstructor) { - StdArray vec1a = {1.,2., 3.}; - StdArray vec1b; + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + const TypeParam vec1a = {Scalar(1), Scalar(2), Scalar(3)}; + TypeParam vec1b; vec1b = vec1a; EXPECT_EQ(vec1a[0], vec1b[0]); EXPECT_EQ(vec1a[1], vec1b[1]); EXPECT_EQ(vec1a[2], vec1b[2]); - -// EigenVec3d vec2a = {1.,2., 3.}; -// EigenVec3d vec2b; -// vec2b = vec2a; -// EXPECT_EQ(vec2a[0], vec2b[0]); -// EXPECT_EQ(vec2a[1], vec2b[1]); -// EXPECT_EQ(vec2a[2], vec2b[2]); } -TEST(VEC_OP_TEST, UnaryMinus) +TYPED_TEST(VEC_OP_TEST, UnaryMinus) { - StdArray vec1a = {1.,2., 3.}; - StdArray vec1b = -vec1a; + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + const TypeParam vec1a = {Scalar(1), Scalar(2), Scalar(3)}; + const TypeParam vec1b = -vec1a; EXPECT_EQ(vec1a[0], -vec1b[0]); EXPECT_EQ(vec1a[1], -vec1b[1]); EXPECT_EQ(vec1a[2], -vec1b[2]); - -// EigenVec3d vec2a = {1.,2., 3.}; -// EigenVec3d vec2b = -vec2a; -// EXPECT_EQ(vec2a[0], -vec2b[0]); -// EXPECT_EQ(vec2a[1], -vec2b[1]); -// EXPECT_EQ(vec2a[2], -vec2b[2]); } -TEST(VEC_OP_TEST, PlusAssign) +TYPED_TEST(VEC_OP_TEST, PlusAssign) { - { - StdArray a = {1.,2., 3.}; - StdArray b = {1.,2., 3.}; - b += a; - EXPECT_EQ(b[0], 2); - EXPECT_EQ(b[1], 4); - EXPECT_EQ(b[2], 6); - } - - { -// EigenVec3d a = {1.,2., 3.}; -// EigenVec3d b = {1.,2., 3.}; -// b += a; -// EXPECT_EQ(b[0], 2); -// EXPECT_EQ(b[1], 4); -// EXPECT_EQ(b[2], 6); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + const TypeParam a = {Scalar(1), Scalar(2), Scalar(3)}; + TypeParam b = {Scalar(7), Scalar(5), Scalar(9)}; + b += a; + EXPECT_EQ(b[0], 8); + EXPECT_EQ(b[1], 7); + EXPECT_EQ(b[2], 12); } -TEST(VEC_OP_TEST, MinusAssign) +TYPED_TEST(VEC_OP_TEST, MinusAssign) { - { - StdArray a = {-1.,-2., -3.}; - StdArray b = {1.,2., 3.}; - b -= a; - EXPECT_EQ(b[0], 2); - EXPECT_EQ(b[1], 4); - EXPECT_EQ(b[2], 6); - } - - { -// EigenVec3d a = {-1.,-2., -3.}; -// EigenVec3d b = {1.,2., 3.}; -// b -= a; -// EXPECT_EQ(b[0], 2); -// EXPECT_EQ(b[1], 4); -// EXPECT_EQ(b[2], 6); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + const TypeParam a = {Scalar(-1), Scalar(-2), Scalar(-3)}; + TypeParam b = {Scalar(7), Scalar(5), Scalar(9)}; + b -= a; + EXPECT_EQ(b[0], 8); + EXPECT_EQ(b[1], 7); + EXPECT_EQ(b[2], 12); } -TEST(VEC_OP_TEST, MultAssign) +TYPED_TEST(VEC_OP_TEST, MultAssign) { - { - StdArray a = {1.,2., 3.}; - a *= 2; - EXPECT_EQ(a[0], 2); - EXPECT_EQ(a[1], 4); - EXPECT_EQ(a[2], 6); - } - - { -// EigenVec3d a = {1.,2., 3.}; -// a *= 2; -// EXPECT_EQ(a[0], 2); -// EXPECT_EQ(a[1], 4); -// EXPECT_EQ(a[2], 6); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + TypeParam a = {Scalar(7), Scalar(5), Scalar(9)}; + a *= 2; + EXPECT_EQ(a[0], 14); + EXPECT_EQ(a[1], 10); + EXPECT_EQ(a[2], 18); } -TEST(VEC_OP_TEST, DivAssign) +TYPED_TEST(VEC_OP_TEST, DivAssign) { - { - StdArray a{2.,4., 6.}; - a /= 2; - EXPECT_EQ(a[0], 1); - EXPECT_EQ(a[1], 2); - EXPECT_EQ(a[2], 3); - } - - { -// EigenVec3d a{2.,4., 6.}; -// a /= 2; -// EXPECT_EQ(a[0], 1); -// EXPECT_EQ(a[1], 2); -// EXPECT_EQ(a[2], 3); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + TypeParam a = {Scalar(2), Scalar(4), Scalar(6)}; + a /= 2; + EXPECT_EQ(a[0], 1); + EXPECT_EQ(a[1], 2); + EXPECT_EQ(a[2], 3); } -TEST(VEC_OP_TEST, Plus) +TYPED_TEST(VEC_OP_TEST, Plus) { - { - StdArray a = {1.,2., 3.}; - StdArray b = {1.,2., 3.}; - StdArray c = a+b; - EXPECT_EQ(c[0], 2); - EXPECT_EQ(c[1], 4); - EXPECT_EQ(c[2], 6); - } - - { -// EigenVec3d a = {1.,2., 3.}; -// EigenVec3d b = {1.,2., 3.}; -// EigenVec3d c = a+b; -// EXPECT_EQ(c[0], 2); -// EXPECT_EQ(c[1], 4); -// EXPECT_EQ(c[2], 6); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + const TypeParam a = {Scalar(1), Scalar(2), Scalar(3)}; + const TypeParam b = {Scalar(7), Scalar(5), Scalar(9)}; + const TypeParam c = a + b; + EXPECT_EQ(c[0], a[0] + b[0]); + EXPECT_EQ(c[1], a[1] + b[1]); + EXPECT_EQ(c[2], a[2] + b[2]); } -TEST(VEC_OP_TEST, Minus) +TYPED_TEST(VEC_OP_TEST, Minus) { - { - StdArray a = {1.,2., 3.}; - StdArray b = {-1.,-2., -3.}; - StdArray c = a-b; - EXPECT_EQ(c[0], 2); - EXPECT_EQ(c[1], 4); - EXPECT_EQ(c[2], 6); - } - - { -// EigenVec3d a = {1.,2., 3.}; -// EigenVec3d b = {-1.,-2., -3.}; -// EigenVec3d c = a-b; -// EXPECT_EQ(c[0], 2); -// EXPECT_EQ(c[1], 4); -// EXPECT_EQ(c[2], 6); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + const TypeParam a = {Scalar(1), Scalar(2), Scalar(3)}; + const TypeParam b = {Scalar(7), Scalar(5), Scalar(9)}; + const TypeParam c = a - b; + EXPECT_EQ(c[0], a[0] - b[0]); + EXPECT_EQ(c[1], a[1] - b[1]); + EXPECT_EQ(c[2], a[2] - b[2]); } -TEST(VEC_OP_TEST, MultScalar) +TYPED_TEST(VEC_OP_TEST, MultScalar) { - { - StdArray a = {1.,2., 3.}; - StdArray c = a*2; - StdArray d = 2*a; - EXPECT_EQ(c[0], 2); - EXPECT_EQ(c[1], 4); - EXPECT_EQ(c[2], 6); - EXPECT_EQ(d[0], 2); - EXPECT_EQ(d[1], 4); - EXPECT_EQ(d[2], 6); - } - - { -// EigenVec3d a = {1.,2., 3.}; -// EigenVec3d c = a*2; -// EigenVec3d d = 2*a; -// EXPECT_EQ(c[0], 2); -// EXPECT_EQ(c[1], 4); -// EXPECT_EQ(c[2], 6); -// EXPECT_EQ(d[0], 2); -// EXPECT_EQ(d[1], 4); -// EXPECT_EQ(d[2], 6); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + TypeParam a = {Scalar(1), Scalar(2), Scalar(3)}; + const TypeParam c = a*2; + const TypeParam d = 2*a; + EXPECT_EQ(c[0], 2 * a[0]); + EXPECT_EQ(c[1], 2 * a[1]); + EXPECT_EQ(c[2], 2 * a[2]); + EXPECT_EQ(d[0], 2 * a[0]); + EXPECT_EQ(d[1], 2 * a[1]); + EXPECT_EQ(d[2], 2 * a[2]); } -TEST(VEC_OP_TEST, Norm2) +TYPED_TEST(VEC_OP_TEST, Norm2) { - StdArray vec1a = {1.,2., 3.}; - EXPECT_EQ(vec1a.squaredNorm(), 14.); + using Scalar = typename cgogn::geometry::vector_traits::Scalar; -// EigenVec3d vec2a = {1.,2., 3.}; -// EXPECT_EQ(vec2a.squaredNorm(), 14.); + const TypeParam a = {Scalar(1), Scalar(2), Scalar(3)}; + EXPECT_EQ(a.squaredNorm(), 14.); } -TEST(VEC_OP_TEST, Norm) +TYPED_TEST(VEC_OP_TEST, Norm) { - { - StdArray a = {3.,-4., 0.}; - EXPECT_EQ(a.norm(), 5.); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; - { -// EigenVec3d a = {3.,-4., 0.}; -// EXPECT_EQ(a.norm(), 5.); - } + const TypeParam a = {Scalar(3), Scalar(-4), Scalar(0)}; + EXPECT_EQ(a.norm(), 5.); } -TEST(VEC_OP_TEST, Normalize) +TYPED_TEST(VEC_OP_TEST, Normalize) { - { - StdArray a = {3.,-4., 0.}; + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + TypeParam a = {Scalar(3), Scalar(-4), Scalar(0)}; a.normalize(); - EXPECT_DOUBLE_EQ(a[0], 3./5.); - EXPECT_DOUBLE_EQ(a[1], -4./5.); - EXPECT_DOUBLE_EQ(a[2], 0.); - EXPECT_DOUBLE_EQ(a.norm(), 1.); - } - - { -// EigenVec3d a = {3.,-4., 0.}; -// a.normalize(); -// EXPECT_DOUBLE_EQ(a[0], 3./5.); -// EXPECT_DOUBLE_EQ(a[1], -4./5.); -// EXPECT_DOUBLE_EQ(a[2], 0.); -// EXPECT_DOUBLE_EQ(a.norm(), 1.); - } + EXPECT_DOUBLE_EQ(a[0], Scalar(3)/Scalar(5)); + EXPECT_DOUBLE_EQ(a[1], Scalar(-4)/Scalar(5)); + EXPECT_DOUBLE_EQ(a[2], Scalar(0)); + EXPECT_DOUBLE_EQ(a.norm(), Scalar(1)); } -TEST(VEC_OP_TEST, DotProduct) +TYPED_TEST(VEC_OP_TEST, DotProduct) { - { - StdArray a = {1.,-2., 3.}; - StdArray b = {1.,-2., 3.}; - EXPECT_EQ(a.dot(b), 14.); - EXPECT_EQ(b.dot(a), 14.); - } - - { - StdArray a = {1.,2., -3.}; - StdArray b = {1.,2., -3.}; - EXPECT_EQ(a.dot(b), 14.); - EXPECT_EQ(b.dot(a), 14.); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + TypeParam a = {Scalar(3), Scalar(-4), Scalar(10)}; + TypeParam b = {Scalar(-1), Scalar(5), Scalar(2)}; + EXPECT_EQ(a.dot(b), -3); + EXPECT_EQ(b.dot(a), -3); } -TEST(VEC_OP_TEST, CrossProduct) +TYPED_TEST(VEC_OP_TEST, CrossProduct) { - { - StdArray a = {1.,2., 3.}; - StdArray b = {3.,2., 1.}; - StdArray c = a.cross(b); + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + const TypeParam a = {Scalar(1), Scalar(2), Scalar(3)}; + const TypeParam b = {Scalar(3), Scalar(2), Scalar(1)}; + const TypeParam c = a.cross(b); EXPECT_EQ(c[0], -4.); EXPECT_EQ(c[1], 8.); EXPECT_EQ(c[2], -4.); - } - - { -// EigenVec3d a = {1.,2., 3.}; -// EigenVec3d b = {3.,2., 1.}; -// EigenVec3d c = a.cross(b); -// EXPECT_EQ(c[0], -4.); -// EXPECT_EQ(c[1], 8.); -// EXPECT_EQ(c[2], -4.); - } } -TEST(VEC_OP_TEST, Equality) +TYPED_TEST(VEC_OP_TEST, Equality) { - StdArray vec1a = {1.,2., 3.}; - StdArray vec1b = {1.,2., 3.}; - EXPECT_TRUE(vec1a == vec1b); + using Scalar = typename cgogn::geometry::vector_traits::Scalar; -// EigenVec3d vec2a = {1.,2., 3.}; -// EigenVec3d vec2b = {1.,2., 3.}; -// EXPECT_TRUE(vec2a == vec2b); + const TypeParam a = {Scalar(1), Scalar(2), Scalar(3)}; + const TypeParam b= {Scalar(1), Scalar(2), Scalar(3)}; + EXPECT_TRUE(a == b); } -TEST(VEC_OP_TEST, DivScalar) +TYPED_TEST(VEC_OP_TEST, DivScalar) { - { - StdArray a = {2. ,4., 6.}; - StdArray c = a/2; - EXPECT_EQ(c[0], 1); - EXPECT_EQ(c[1], 2); - EXPECT_EQ(c[2], 3); - } - - { -// EigenVec3d a = {2. ,4., 6.}; -// EigenVec3d c = a/2; -// EXPECT_EQ(c[0], 1); -// EXPECT_EQ(c[1], 2); -// EXPECT_EQ(c[2], 3); - } + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + + const TypeParam a = {Scalar(2), Scalar(4), Scalar(6)}; + const TypeParam c = a/2; + EXPECT_EQ(c[0], 1); + EXPECT_EQ(c[1], 2); + EXPECT_EQ(c[2], 3); } From 62b4fc493d8ed702d4e41479168e0fcf6d4dfcda Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Sat, 27 Feb 2016 16:05:19 +0100 Subject: [PATCH 205/402] updated eigen to 3.2.8 Signed-off-by: Etienne Schmitt --- thirdparty/eigen-3.2.7/Eigen/CholmodSupport | 2 +- thirdparty/eigen-3.2.7/Eigen/SPQRSupport | 2 +- thirdparty/eigen-3.2.7/Eigen/UmfPackSupport | 2 +- .../Eigen/src/Core/CwiseUnaryView.h | 2 +- .../Eigen/src/Core/GeneralProduct.h | 11 +- .../eigen-3.2.7/Eigen/src/Core/MapBase.h | 4 + .../Eigen/src/Core/MathFunctions.h | 6 +- .../Eigen/src/Core/SolveTriangular.h | 8 +- .../eigen-3.2.7/Eigen/src/Core/Visitor.h | 7 +- .../Eigen/src/Core/arch/SSE/PacketMath.h | 44 +-- .../src/Core/products/GeneralMatrixMatrix.h | 8 +- .../Core/products/TriangularSolverMatrix.h | 4 +- .../eigen-3.2.7/Eigen/src/Core/util/Macros.h | 287 +++++++++++++++++- .../eigen-3.2.7/Eigen/src/Core/util/Memory.h | 2 + .../Eigen/src/Core/util/StaticAssert.h | 2 +- .../Eigen/src/Eigenvalues/ComplexSchur_MKL.h | 1 - .../Eigen/src/Eigenvalues/RealSchur_MKL.h | 4 - .../Eigen/src/Geometry/AngleAxis.h | 7 + .../Eigen/src/Geometry/ParametrizedLine.h | 2 +- .../Eigen/src/Geometry/Transform.h | 49 ++- .../Eigen/src/Geometry/Translation.h | 2 +- .../ConjugateGradient.h | 2 + .../eigen-3.2.7/Eigen/src/LU/FullPivLU.h | 2 +- .../Eigen/src/OrderingMethods/Amd.h | 2 +- .../Eigen/src/OrderingMethods/Eigen_Colamd.h | 31 +- .../Eigen/src/QR/ColPivHouseholderQR_MKL.h | 1 - .../eigen-3.2.7/Eigen/src/SVD/JacobiSVD.h | 2 +- .../eigen-3.2.7/Eigen/src/SVD/JacobiSVD_MKL.h | 4 +- .../Eigen/src/SparseCore/SparseBlock.h | 6 +- .../src/SparseCore/SparseCwiseBinaryOp.h | 5 +- .../Eigen/src/SparseCore/SparseView.h | 6 +- .../Eigen/src/StlSupport/StdDeque.h | 18 +- .../Eigen/src/StlSupport/StdList.h | 18 +- 33 files changed, 399 insertions(+), 154 deletions(-) diff --git a/thirdparty/eigen-3.2.7/Eigen/CholmodSupport b/thirdparty/eigen-3.2.7/Eigen/CholmodSupport index 745b884e..88c29a64 100644 --- a/thirdparty/eigen-3.2.7/Eigen/CholmodSupport +++ b/thirdparty/eigen-3.2.7/Eigen/CholmodSupport @@ -12,7 +12,7 @@ extern "C" { /** \ingroup Support_modules * \defgroup CholmodSupport_Module CholmodSupport module * - * This module provides an interface to the Cholmod library which is part of the suitesparse package. + * This module provides an interface to the Cholmod library which is part of the suitesparse package. * It provides the two following main factorization classes: * - class CholmodSupernodalLLT: a supernodal LLT Cholesky factorization. * - class CholmodDecomposiiton: a general L(D)LT Cholesky factorization with automatic or explicit runtime selection of the underlying factorization method (supernodal or simplicial). diff --git a/thirdparty/eigen-3.2.7/Eigen/SPQRSupport b/thirdparty/eigen-3.2.7/Eigen/SPQRSupport index 77016442..7f1eb477 100644 --- a/thirdparty/eigen-3.2.7/Eigen/SPQRSupport +++ b/thirdparty/eigen-3.2.7/Eigen/SPQRSupport @@ -10,7 +10,7 @@ /** \ingroup Support_modules * \defgroup SPQRSupport_Module SuiteSparseQR module * - * This module provides an interface to the SPQR library, which is part of the suitesparse package. + * This module provides an interface to the SPQR library, which is part of the suitesparse package. * * \code * #include diff --git a/thirdparty/eigen-3.2.7/Eigen/UmfPackSupport b/thirdparty/eigen-3.2.7/Eigen/UmfPackSupport index 984f64a8..7b1b6606 100644 --- a/thirdparty/eigen-3.2.7/Eigen/UmfPackSupport +++ b/thirdparty/eigen-3.2.7/Eigen/UmfPackSupport @@ -12,7 +12,7 @@ extern "C" { /** \ingroup Support_modules * \defgroup UmfPackSupport_Module UmfPackSupport module * - * This module provides an interface to the UmfPack library which is part of the suitesparse package. + * This module provides an interface to the UmfPack library which is part of the suitesparse package. * It provides the following factorization class: * - class UmfPackLU: a multifrontal sequential LU factorization. * diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/CwiseUnaryView.h b/thirdparty/eigen-3.2.7/Eigen/src/Core/CwiseUnaryView.h index b2638d32..f3b2ffeb 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/Core/CwiseUnaryView.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/Core/CwiseUnaryView.h @@ -38,7 +38,7 @@ struct traits > typedef typename remove_all::type _MatrixTypeNested; enum { Flags = (traits<_MatrixTypeNested>::Flags & (HereditaryBits | LvalueBit | LinearAccessBit | DirectAccessBit)), - CoeffReadCost = traits<_MatrixTypeNested>::CoeffReadCost + functor_traits::Cost, + CoeffReadCost = EIGEN_ADD_COST(traits<_MatrixTypeNested>::CoeffReadCost, functor_traits::Cost), MatrixTypeInnerStride = inner_stride_at_compile_time::ret, // need to cast the sizeof's from size_t to int explicitly, otherwise: // "error: no integral type can represent all of the enumerator values diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/GeneralProduct.h b/thirdparty/eigen-3.2.7/Eigen/src/Core/GeneralProduct.h index 0eae5299..29ac522d 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/Core/GeneralProduct.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/Core/GeneralProduct.h @@ -425,15 +425,18 @@ template<> struct gemv_selector ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs()) * RhsBlasTraits::extractScalarFactor(prod.rhs()); + // make sure Dest is a compile-time vector type (bug 1166) + typedef typename conditional::type ActualDest; + enum { // FIXME find a way to allow an inner stride on the result if packet_traits::size==1 // on, the other hand it is good for the cache to pack the vector anyways... - EvalToDestAtCompileTime = Dest::InnerStrideAtCompileTime==1, + EvalToDestAtCompileTime = (ActualDest::InnerStrideAtCompileTime==1), ComplexByReal = (NumTraits::IsComplex) && (!NumTraits::IsComplex), - MightCannotUseDest = (Dest::InnerStrideAtCompileTime!=1) || ComplexByReal + MightCannotUseDest = (ActualDest::InnerStrideAtCompileTime!=1) || ComplexByReal }; - gemv_static_vector_if static_dest; + gemv_static_vector_if static_dest; bool alphaIsCompatible = (!ComplexByReal) || (numext::imag(actualAlpha)==RealScalar(0)); bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible; @@ -522,7 +525,7 @@ template<> struct gemv_selector actualLhs.rows(), actualLhs.cols(), actualLhs.data(), actualLhs.outerStride(), actualRhsPtr, 1, - dest.data(), dest.innerStride(), + dest.data(), dest.col(0).innerStride(), //NOTE if dest is not a vector at compile-time, then dest.innerStride() might be wrong. (bug 1166) actualAlpha); } }; diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/MapBase.h b/thirdparty/eigen-3.2.7/Eigen/src/Core/MapBase.h index a9828f7f..81efc4a6 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/Core/MapBase.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/Core/MapBase.h @@ -149,6 +149,10 @@ template class MapBase checkSanity(); } + #ifdef EIGEN_MAPBASE_PLUGIN + #include EIGEN_MAPBASE_PLUGIN + #endif + protected: void checkSanity() const diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/MathFunctions.h b/thirdparty/eigen-3.2.7/Eigen/src/Core/MathFunctions.h index adf2f9c5..4e17ecd4 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/Core/MathFunctions.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/Core/MathFunctions.h @@ -707,21 +707,21 @@ struct scalar_fuzzy_impl : scalar_fuzzy_default_impl:: template inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, - typename NumTraits::Real precision = NumTraits::dummy_precision()) + const typename NumTraits::Real &precision = NumTraits::dummy_precision()) { return scalar_fuzzy_impl::template isMuchSmallerThan(x, y, precision); } template inline bool isApprox(const Scalar& x, const Scalar& y, - typename NumTraits::Real precision = NumTraits::dummy_precision()) + const typename NumTraits::Real &precision = NumTraits::dummy_precision()) { return scalar_fuzzy_impl::isApprox(x, y, precision); } template inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, - typename NumTraits::Real precision = NumTraits::dummy_precision()) + const typename NumTraits::Real &precision = NumTraits::dummy_precision()) { return scalar_fuzzy_impl::isApproxOrLessThan(x, y, precision); } diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/SolveTriangular.h b/thirdparty/eigen-3.2.7/Eigen/src/Core/SolveTriangular.h index ef17f288..83565ddd 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/Core/SolveTriangular.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/Core/SolveTriangular.h @@ -116,17 +116,17 @@ template struct triangular_solver_unroller { enum { IsLower = ((Mode&Lower)==Lower), - I = IsLower ? Index : Size - Index - 1, - S = IsLower ? 0 : I+1 + RowIndex = IsLower ? Index : Size - Index - 1, + S = IsLower ? 0 : RowIndex+1 }; static void run(const Lhs& lhs, Rhs& rhs) { if (Index>0) - rhs.coeffRef(I) -= lhs.row(I).template segment(S).transpose() + rhs.coeffRef(RowIndex) -= lhs.row(RowIndex).template segment(S).transpose() .cwiseProduct(rhs.template segment(S)).sum(); if(!(Mode & UnitDiag)) - rhs.coeffRef(I) /= lhs.coeff(I,I); + rhs.coeffRef(RowIndex) /= lhs.coeff(RowIndex,RowIndex); triangular_solver_unroller::run(lhs,rhs); } diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/Visitor.h b/thirdparty/eigen-3.2.7/Eigen/src/Core/Visitor.h index 64867b7a..dd94eb8f 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/Core/Visitor.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/Core/Visitor.h @@ -76,14 +76,17 @@ template template void DenseBase::visit(Visitor& visitor) const { + typedef typename internal::remove_all::type ThisNested; + typename Derived::Nested thisNested(derived()); + enum { unroll = SizeAtCompileTime != Dynamic && CoeffReadCost != Dynamic && (SizeAtCompileTime == 1 || internal::functor_traits::Cost != Dynamic) && SizeAtCompileTime * CoeffReadCost + (SizeAtCompileTime-1) * internal::functor_traits::Cost <= EIGEN_UNROLLING_LIMIT }; - return internal::visitor_impl::run(derived(), visitor); + >::run(thisNested, visitor); } namespace internal { diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/arch/SSE/PacketMath.h b/thirdparty/eigen-3.2.7/Eigen/src/Core/arch/SSE/PacketMath.h index fc8ae50f..bef898b1 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/Core/arch/SSE/PacketMath.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/Core/arch/SSE/PacketMath.h @@ -235,63 +235,27 @@ template<> EIGEN_STRONG_INLINE Packet4i pload(const int* from) { E return _mm_loadu_ps(from); #endif } - template<> EIGEN_STRONG_INLINE Packet2d ploadu(const double* from) { EIGEN_DEBUG_UNALIGNED_LOAD return _mm_loadu_pd(from); } - template<> EIGEN_STRONG_INLINE Packet4i ploadu(const int* from) { EIGEN_DEBUG_UNALIGNED_LOAD return _mm_loadu_si128(reinterpret_cast(from)); } #else -// Fast unaligned loads. Note that here we cannot directly use intrinsics: this would -// require pointer casting to incompatible pointer types and leads to invalid code -// because of the strict aliasing rule. The "dummy" stuff are required to enforce -// a correct instruction dependency. -// TODO: do the same for MSVC (ICC is compatible) // NOTE: with the code below, MSVC's compiler crashes! -#if defined(__GNUC__) && defined(__i386__) - // bug 195: gcc/i386 emits weird x87 fldl/fstpl instructions for _mm_load_sd - #define EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS 1 -#elif defined(__clang__) - // bug 201: Segfaults in __mm_loadh_pd with clang 2.8 - #define EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS 1 -#else - #define EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS 0 -#endif - template<> EIGEN_STRONG_INLINE Packet4f ploadu(const float* from) { EIGEN_DEBUG_UNALIGNED_LOAD -#if EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS return _mm_loadu_ps(from); -#else - __m128d res; - res = _mm_load_sd((const double*)(from)) ; - res = _mm_loadh_pd(res, (const double*)(from+2)) ; - return _mm_castpd_ps(res); -#endif } +#endif + template<> EIGEN_STRONG_INLINE Packet2d ploadu(const double* from) { EIGEN_DEBUG_UNALIGNED_LOAD -#if EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS return _mm_loadu_pd(from); -#else - __m128d res; - res = _mm_load_sd(from) ; - res = _mm_loadh_pd(res,from+1); - return res; -#endif } template<> EIGEN_STRONG_INLINE Packet4i ploadu(const int* from) { EIGEN_DEBUG_UNALIGNED_LOAD -#if EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS - return _mm_loadu_si128(reinterpret_cast(from)); -#else - __m128d res; - res = _mm_load_sd((const double*)(from)) ; - res = _mm_loadh_pd(res, (const double*)(from+2)) ; - return _mm_castpd_si128(res); -#endif + return _mm_loadu_si128(reinterpret_cast(from)); } -#endif + template<> EIGEN_STRONG_INLINE Packet4f ploaddup(const float* from) { diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/products/GeneralMatrixMatrix.h b/thirdparty/eigen-3.2.7/Eigen/src/Core/products/GeneralMatrixMatrix.h index 3f5ffcf5..cfd2f009 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/Core/products/GeneralMatrixMatrix.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/Core/products/GeneralMatrixMatrix.h @@ -140,8 +140,10 @@ static void run(Index rows, Index cols, Index depth, // Release all the sub blocks B'_j of B' for the current thread, // i.e., we simply decrement the number of users by 1 for(Index j=0; j GeneralProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs) { +#if !(defined(EIGEN_NO_STATIC_ASSERT) && defined(EIGEN_NO_DEBUG)) typedef internal::scalar_product_op BinOp; EIGEN_CHECK_BINARY_COMPATIBILIY(BinOp,LhsScalar,RhsScalar); +#endif } template void scaleAndAddTo(Dest& dst, const Scalar& alpha) const { eigen_assert(dst.rows()==m_lhs.rows() && dst.cols()==m_rhs.cols()); + if(m_lhs.cols()==0 || m_lhs.rows()==0 || m_rhs.cols()==0) + return; typename internal::add_const_on_value_type::type lhs = LhsBlasTraits::extract(m_lhs); typename internal::add_const_on_value_type::type rhs = RhsBlasTraits::extract(m_rhs); diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/products/TriangularSolverMatrix.h b/thirdparty/eigen-3.2.7/Eigen/src/Core/products/TriangularSolverMatrix.h index 04240ab5..03a23abc 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/Core/products/TriangularSolverMatrix.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/Core/products/TriangularSolverMatrix.h @@ -115,8 +115,9 @@ EIGEN_DONT_INLINE void triangular_solve_matrixx || (EIGEN_WORLD_VERSION>=x && \ (EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \ EIGEN_MINOR_VERSION>=z)))) + + +// Compiler identification, EIGEN_COMP_* + +/// \internal EIGEN_COMP_GNUC set to 1 for all compilers compatible with GCC #ifdef __GNUC__ + #define EIGEN_COMP_GNUC 1 +#else + #define EIGEN_COMP_GNUC 0 +#endif + +/// \internal EIGEN_COMP_CLANG set to 1 if the compiler is clang (alias for __clang__) +#if defined(__clang__) + #define EIGEN_COMP_CLANG 1 +#else + #define EIGEN_COMP_CLANG 0 +#endif + + +/// \internal EIGEN_COMP_LLVM set to 1 if the compiler backend is llvm +#if defined(__llvm__) + #define EIGEN_COMP_LLVM 1 +#else + #define EIGEN_COMP_LLVM 0 +#endif + +/// \internal EIGEN_COMP_ICC set to __INTEL_COMPILER if the compiler is Intel compiler, 0 otherwise +#if defined(__INTEL_COMPILER) + #define EIGEN_COMP_ICC __INTEL_COMPILER +#else + #define EIGEN_COMP_ICC 0 +#endif + +/// \internal EIGEN_COMP_MINGW set to 1 if the compiler is mingw +#if defined(__MINGW32__) + #define EIGEN_COMP_MINGW 1 +#else + #define EIGEN_COMP_MINGW 0 +#endif + +/// \internal EIGEN_COMP_SUNCC set to 1 if the compiler is Solaris Studio +#if defined(__SUNPRO_CC) + #define EIGEN_COMP_SUNCC 1 +#else + #define EIGEN_COMP_SUNCC 0 +#endif + +/// \internal EIGEN_COMP_MSVC set to _MSC_VER if the compiler is Microsoft Visual C++, 0 otherwise. +#if defined(_MSC_VER) + #define EIGEN_COMP_MSVC _MSC_VER +#else + #define EIGEN_COMP_MSVC 0 +#endif + +/// \internal EIGEN_COMP_MSVC_STRICT set to 1 if the compiler is really Microsoft Visual C++ and not ,e.g., ICC +#if EIGEN_COMP_MSVC && !(EIGEN_COMP_ICC) + #define EIGEN_COMP_MSVC_STRICT _MSC_VER +#else + #define EIGEN_COMP_MSVC_STRICT 0 +#endif + +/// \internal EIGEN_COMP_IBM set to 1 if the compiler is IBM XL C++ +#if defined(__IBMCPP__) || defined(__xlc__) + #define EIGEN_COMP_IBM 1 +#else + #define EIGEN_COMP_IBM 0 +#endif + +/// \internal EIGEN_COMP_PGI set to 1 if the compiler is Portland Group Compiler +#if defined(__PGI) + #define EIGEN_COMP_PGI 1 +#else + #define EIGEN_COMP_PGI 0 +#endif + +/// \internal EIGEN_COMP_ARM set to 1 if the compiler is ARM Compiler +#if defined(__CC_ARM) || defined(__ARMCC_VERSION) + #define EIGEN_COMP_ARM 1 +#else + #define EIGEN_COMP_ARM 0 +#endif + + +/// \internal EIGEN_GNUC_STRICT set to 1 if the compiler is really GCC and not a compatible compiler (e.g., ICC, clang, mingw, etc.) +#if EIGEN_COMP_GNUC && !(EIGEN_COMP_CLANG || EIGEN_COMP_ICC || EIGEN_COMP_MINGW || EIGEN_COMP_PGI || EIGEN_COMP_IBM || EIGEN_COMP_ARM ) + #define EIGEN_COMP_GNUC_STRICT 1 +#else + #define EIGEN_COMP_GNUC_STRICT 0 +#endif + + +#if EIGEN_COMP_GNUC #define EIGEN_GNUC_AT_LEAST(x,y) ((__GNUC__==x && __GNUC_MINOR__>=y) || __GNUC__>x) + #define EIGEN_GNUC_AT_MOST(x,y) ((__GNUC__==x && __GNUC_MINOR__<=y) || __GNUC__= 201103L) || \ (defined(_MSC_VER) && _MSC_VER >= 1600)) #define EIGEN_HAVE_RVALUE_REFERENCES #endif diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/util/Memory.h b/thirdparty/eigen-3.2.7/Eigen/src/Core/util/Memory.h index b9af5cf8..bc1ea69e 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/Core/util/Memory.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/Core/util/Memory.h @@ -630,6 +630,8 @@ template class aligned_stack_memory_handler } \ void operator delete(void * ptr) throw() { Eigen::internal::conditional_aligned_free(ptr); } \ void operator delete[](void * ptr) throw() { Eigen::internal::conditional_aligned_free(ptr); } \ + void operator delete(void * ptr, std::size_t /* sz */) throw() { Eigen::internal::conditional_aligned_free(ptr); } \ + void operator delete[](void * ptr, std::size_t /* sz */) throw() { Eigen::internal::conditional_aligned_free(ptr); } \ /* in-place new and delete. since (at least afaik) there is no actual */ \ /* memory allocated we can safely let the default implementation handle */ \ /* this particular case. */ \ diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/util/StaticAssert.h b/thirdparty/eigen-3.2.7/Eigen/src/Core/util/StaticAssert.h index bac5d9fe..e53d2b87 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/Core/util/StaticAssert.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/Core/util/StaticAssert.h @@ -26,7 +26,7 @@ #ifndef EIGEN_NO_STATIC_ASSERT - #if defined(__GXX_EXPERIMENTAL_CXX0X__) || (defined(_MSC_VER) && (_MSC_VER >= 1600)) + #if __has_feature(cxx_static_assert) || (defined(__cplusplus) && __cplusplus >= 201103L) || (EIGEN_COMP_MSVC >= 1600) // if native static_assert is enabled, let's use it #define EIGEN_STATIC_ASSERT(X,MSG) static_assert(X,#MSG); diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/ComplexSchur_MKL.h b/thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/ComplexSchur_MKL.h index 91496ae5..27aed923 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/ComplexSchur_MKL.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/ComplexSchur_MKL.h @@ -45,7 +45,6 @@ ComplexSchur >& \ ComplexSchur >::compute(const Matrix& matrix, bool computeU) \ { \ typedef Matrix MatrixType; \ - typedef MatrixType::Scalar Scalar; \ typedef MatrixType::RealScalar RealScalar; \ typedef std::complex ComplexScalar; \ \ diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/RealSchur_MKL.h b/thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/RealSchur_MKL.h index ad973646..c3089b46 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/RealSchur_MKL.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/RealSchur_MKL.h @@ -44,10 +44,6 @@ template<> inline \ RealSchur >& \ RealSchur >::compute(const Matrix& matrix, bool computeU) \ { \ - typedef Matrix MatrixType; \ - typedef MatrixType::Scalar Scalar; \ - typedef MatrixType::RealScalar RealScalar; \ -\ eigen_assert(matrix.cols() == matrix.rows()); \ \ lapack_int n = matrix.cols(), sdim, info; \ diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Geometry/AngleAxis.h b/thirdparty/eigen-3.2.7/Eigen/src/Geometry/AngleAxis.h index bbf6a7ed..a8d3cdcf 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/Geometry/AngleAxis.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/Geometry/AngleAxis.h @@ -83,10 +83,17 @@ class AngleAxis : public RotationBase,3> template inline explicit AngleAxis(const MatrixBase& m) { *this = m; } + /** \returns the value of the rotation angle in radian */ Scalar angle() const { return m_angle; } + /** \returns a read-write reference to the stored angle in radian */ Scalar& angle() { return m_angle; } + /** \returns the rotation axis */ const Vector3& axis() const { return m_axis; } + /** \returns a read-write reference to the stored rotation axis. + * + * \warning The rotation axis must remain a \b unit vector. + */ Vector3& axis() { return m_axis; } /** Concatenates two rotations */ diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Geometry/ParametrizedLine.h b/thirdparty/eigen-3.2.7/Eigen/src/Geometry/ParametrizedLine.h index 77fa228e..cf3252df 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/Geometry/ParametrizedLine.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/Geometry/ParametrizedLine.h @@ -129,7 +129,7 @@ class ParametrizedLine * determined by \a prec. * * \sa MatrixBase::isApprox() */ - bool isApprox(const ParametrizedLine& other, typename NumTraits::Real prec = NumTraits::dummy_precision()) const + bool isApprox(const ParametrizedLine& other, const typename NumTraits::Real& prec = NumTraits::dummy_precision()) const { return m_origin.isApprox(other.m_origin, prec) && m_direction.isApprox(other.m_direction, prec); } protected: diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Geometry/Transform.h b/thirdparty/eigen-3.2.7/Eigen/src/Geometry/Transform.h index e786e535..0186f3b8 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/Geometry/Transform.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/Geometry/Transform.h @@ -102,15 +102,15 @@ template struct transform_make_affine; * * However, unlike a plain matrix, the Transform class provides many features * simplifying both its assembly and usage. In particular, it can be composed - * with any other transformations (Transform,Translation,RotationBase,Matrix) + * with any other transformations (Transform,Translation,RotationBase,DiagonalMatrix) * and can be directly used to transform implicit homogeneous vectors. All these * operations are handled via the operator*. For the composition of transformations, * its principle consists to first convert the right/left hand sides of the product * to a compatible (Dim+1)^2 matrix and then perform a pure matrix product. * Of course, internally, operator* tries to perform the minimal number of operations * according to the nature of each terms. Likewise, when applying the transform - * to non homogeneous vectors, the latters are automatically promoted to homogeneous - * one before doing the matrix product. The convertions to homogeneous representations + * to points, the latters are automatically promoted to homogeneous vectors + * before doing the matrix product. The conventions to homogeneous representations * are performed as follow: * * \b Translation t (Dim)x(1): @@ -124,7 +124,7 @@ template struct transform_make_affine; * R & 0\\ * 0\,...\,0 & 1 * \end{array} \right) \f$ - * + * + * \b Scaling \b DiagonalMatrix S (Dim)x(Dim): + * \f$ \left( \begin{array}{cc} + * S & 0\\ + * 0\,...\,0 & 1 + * \end{array} \right) \f$ * - * \b Column \b vector v (Dim)x(1): + * \b Column \b point v (Dim)x(1): * \f$ \left( \begin{array}{c} * v\\ * 1 * \end{array} \right) \f$ * - * \b Set \b of \b column \b vectors V1...Vn (Dim)x(n): + * \b Set \b of \b column \b points V1...Vn (Dim)x(n): * \f$ \left( \begin{array}{ccc} * v_1 & ... & v_n\\ * 1 & ... & 1 @@ -384,26 +390,39 @@ class Transform /** \returns a writable expression of the translation vector of the transformation */ inline TranslationPart translation() { return TranslationPart(m_matrix,0,Dim); } - /** \returns an expression of the product between the transform \c *this and a matrix expression \a other + /** \returns an expression of the product between the transform \c *this and a matrix expression \a other. * - * The right hand side \a other might be either: - * \li a vector of size Dim, + * The right-hand-side \a other can be either: * \li an homogeneous vector of size Dim+1, - * \li a set of vectors of size Dim x Dynamic, - * \li a set of homogeneous vectors of size Dim+1 x Dynamic, - * \li a linear transformation matrix of size Dim x Dim, - * \li an affine transformation matrix of size Dim x Dim+1, + * \li a set of homogeneous vectors of size Dim+1 x N, * \li a transformation matrix of size Dim+1 x Dim+1. + * + * Moreover, if \c *this represents an affine transformation (i.e., Mode!=Projective), then \a other can also be: + * \li a point of size Dim (computes: \code this->linear() * other + this->translation()\endcode), + * \li a set of N points as a Dim x N matrix (computes: \code (this->linear() * other).colwise() + this->translation()\endcode), + * + * In all cases, the return type is a matrix or vector of same sizes as the right-hand-side \a other. + * + * If you want to interpret \a other as a linear or affine transformation, then first convert it to a Transform<> type, + * or do your own cooking. + * + * Finally, if you want to apply Affine transformations to vectors, then explicitly apply the linear part only: + * \code + * Affine3f A; + * Vector3f v1, v2; + * v2 = A.linear() * v1; + * \endcode + * */ // note: this function is defined here because some compilers cannot find the respective declaration template - EIGEN_STRONG_INLINE const typename internal::transform_right_product_impl::ResultType + EIGEN_STRONG_INLINE const typename OtherDerived::PlainObject operator * (const EigenBase &other) const { return internal::transform_right_product_impl::run(*this,other.derived()); } /** \returns the product expression of a transformation matrix \a a times a transform \a b * - * The left hand side \a other might be either: + * The left hand side \a other can be either: * \li a linear transformation matrix of size Dim x Dim, * \li an affine transformation matrix of size Dim x Dim+1, * \li a general transformation matrix of size Dim+1 x Dim+1. diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Geometry/Translation.h b/thirdparty/eigen-3.2.7/Eigen/src/Geometry/Translation.h index 7fda179c..2e779868 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/Geometry/Translation.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/Geometry/Translation.h @@ -162,7 +162,7 @@ class Translation * determined by \a prec. * * \sa MatrixBase::isApprox() */ - bool isApprox(const Translation& other, typename NumTraits::Real prec = NumTraits::dummy_precision()) const + bool isApprox(const Translation& other, const typename NumTraits::Real& prec = NumTraits::dummy_precision()) const { return m_coeffs.isApprox(other.m_coeffs, prec); } }; diff --git a/thirdparty/eigen-3.2.7/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h b/thirdparty/eigen-3.2.7/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h index 1a7e569c..7dd4010c 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h @@ -139,6 +139,8 @@ struct traits > * By default the iterations start with x=0 as an initial guess of the solution. * One can control the start using the solveWithGuess() method. * + * ConjugateGradient can also be used in a matrix-free context, see the following \link MatrixfreeSolverExample example \endlink. + * * \sa class SimplicialCholesky, DiagonalPreconditioner, IdentityPreconditioner */ template< typename _MatrixType, int _UpLo, typename _Preconditioner> diff --git a/thirdparty/eigen-3.2.7/Eigen/src/LU/FullPivLU.h b/thirdparty/eigen-3.2.7/Eigen/src/LU/FullPivLU.h index 26bc7144..e3847046 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/LU/FullPivLU.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/LU/FullPivLU.h @@ -688,7 +688,7 @@ struct solve_retval, Rhs> */ const Index rows = dec().rows(), cols = dec().cols(), - nonzero_pivots = dec().nonzeroPivots(); + nonzero_pivots = dec().rank(); eigen_assert(rhs().rows() == rows); const Index smalldim = (std::min)(rows, cols); diff --git a/thirdparty/eigen-3.2.7/Eigen/src/OrderingMethods/Amd.h b/thirdparty/eigen-3.2.7/Eigen/src/OrderingMethods/Amd.h index 70550b8a..658b954c 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/OrderingMethods/Amd.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/OrderingMethods/Amd.h @@ -8,7 +8,7 @@ NOTE: this routine has been adapted from the CSparse library: Copyright (c) 2006, Timothy A. Davis. -http://www.cise.ufl.edu/research/sparse/CSparse +http://www.suitesparse.com CSparse is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public diff --git a/thirdparty/eigen-3.2.7/Eigen/src/OrderingMethods/Eigen_Colamd.h b/thirdparty/eigen-3.2.7/Eigen/src/OrderingMethods/Eigen_Colamd.h index 44548f66..359fd441 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/OrderingMethods/Eigen_Colamd.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/OrderingMethods/Eigen_Colamd.h @@ -41,12 +41,8 @@ // // The colamd/symamd library is available at // -// http://www.cise.ufl.edu/research/sparse/colamd/ +// http://www.suitesparse.com -// This is the http://www.cise.ufl.edu/research/sparse/colamd/colamd.h -// file. It is required by the colamd.c, colamdmex.c, and symamdmex.c -// files, and by any C code that calls the routines whose prototypes are -// listed below, or that uses the colamd/symamd definitions listed below. #ifndef EIGEN_COLAMD_H #define EIGEN_COLAMD_H @@ -102,9 +98,6 @@ namespace internal { /* === Definitions ========================================================== */ /* ========================================================================== */ -#define COLAMD_MAX(a,b) (((a) > (b)) ? (a) : (b)) -#define COLAMD_MIN(a,b) (((a) < (b)) ? (a) : (b)) - #define ONES_COMPLEMENT(r) (-(r)-1) /* -------------------------------------------------------------------------- */ @@ -516,7 +509,7 @@ static Index init_rows_cols /* returns true if OK, or false otherwise */ Col [col].start = p [col] ; Col [col].length = p [col+1] - p [col] ; - if (Col [col].length < 0) + if ((Col [col].length) < 0) // extra parentheses to work-around gcc bug 10200 { /* column pointers must be non-decreasing */ stats [COLAMD_STATUS] = COLAMD_ERROR_col_length_negative ; @@ -739,8 +732,8 @@ static void init_scoring /* === Extract knobs ==================================================== */ - dense_row_count = COLAMD_MAX (0, COLAMD_MIN (knobs [COLAMD_DENSE_ROW] * n_col, n_col)) ; - dense_col_count = COLAMD_MAX (0, COLAMD_MIN (knobs [COLAMD_DENSE_COL] * n_row, n_row)) ; + dense_row_count = std::max(0, (std::min)(Index(knobs [COLAMD_DENSE_ROW] * n_col), n_col)) ; + dense_col_count = std::max(0, (std::min)(Index(knobs [COLAMD_DENSE_COL] * n_row), n_row)) ; COLAMD_DEBUG1 (("colamd: densecount: %d %d\n", dense_row_count, dense_col_count)) ; max_deg = 0 ; n_col2 = n_col ; @@ -804,7 +797,7 @@ static void init_scoring else { /* keep track of max degree of remaining rows */ - max_deg = COLAMD_MAX (max_deg, deg) ; + max_deg = (std::max)(max_deg, deg) ; } } COLAMD_DEBUG1 (("colamd: Dense and null rows killed: %d\n", n_row - n_row2)) ; @@ -842,7 +835,7 @@ static void init_scoring /* add row's external degree */ score += Row [row].shared1.degree - 1 ; /* guard against integer overflow */ - score = COLAMD_MIN (score, n_col) ; + score = (std::min)(score, n_col) ; } /* determine pruned column length */ col_length = (Index) (new_cp - &A [Col [c].start]) ; @@ -914,7 +907,7 @@ static void init_scoring head [score] = c ; /* see if this score is less than current min */ - min_score = COLAMD_MIN (min_score, score) ; + min_score = (std::min)(min_score, score) ; } @@ -1040,7 +1033,7 @@ static Index find_ordering /* return the number of garbage collections */ /* === Garbage_collection, if necessary ============================= */ - needed_memory = COLAMD_MIN (pivot_col_score, n_col - k) ; + needed_memory = (std::min)(pivot_col_score, n_col - k) ; if (pfree + needed_memory >= Alen) { pfree = Eigen::internal::garbage_collection (n_row, n_col, Row, Col, A, &A [pfree]) ; @@ -1099,7 +1092,7 @@ static Index find_ordering /* return the number of garbage collections */ /* clear tag on pivot column */ Col [pivot_col].shared1.thickness = pivot_col_thickness ; - max_deg = COLAMD_MAX (max_deg, pivot_row_degree) ; + max_deg = (std::max)(max_deg, pivot_row_degree) ; /* === Kill all rows used to construct pivot row ==================== */ @@ -1273,7 +1266,7 @@ static Index find_ordering /* return the number of garbage collections */ /* add set difference */ cur_score += row_mark - tag_mark ; /* integer overflow... */ - cur_score = COLAMD_MIN (cur_score, n_col) ; + cur_score = (std::min)(cur_score, n_col) ; } /* recompute the column's length */ @@ -1386,7 +1379,7 @@ static Index find_ordering /* return the number of garbage collections */ cur_score -= Col [col].shared1.thickness ; /* make sure score is less or equal than the max score */ - cur_score = COLAMD_MIN (cur_score, max_score) ; + cur_score = (std::min)(cur_score, max_score) ; COLAMD_ASSERT (cur_score >= 0) ; /* store updated score */ @@ -1409,7 +1402,7 @@ static Index find_ordering /* return the number of garbage collections */ head [cur_score] = col ; /* see if this score is less than current min */ - min_score = COLAMD_MIN (min_score, cur_score) ; + min_score = (std::min)(min_score, cur_score) ; } diff --git a/thirdparty/eigen-3.2.7/Eigen/src/QR/ColPivHouseholderQR_MKL.h b/thirdparty/eigen-3.2.7/Eigen/src/QR/ColPivHouseholderQR_MKL.h index b5b19832..7b6ba0a5 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/QR/ColPivHouseholderQR_MKL.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/QR/ColPivHouseholderQR_MKL.h @@ -49,7 +49,6 @@ ColPivHouseholderQR MatrixType; \ - typedef MatrixType::Scalar Scalar; \ typedef MatrixType::RealScalar RealScalar; \ Index rows = matrix.rows();\ Index cols = matrix.cols();\ diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SVD/JacobiSVD.h b/thirdparty/eigen-3.2.7/Eigen/src/SVD/JacobiSVD.h index 1b297741..89ace381 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/SVD/JacobiSVD.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/SVD/JacobiSVD.h @@ -816,7 +816,7 @@ void JacobiSVD::allocate(Index rows, Index cols, u if(m_cols>m_rows) m_qr_precond_morecols.allocate(*this); if(m_rows>m_cols) m_qr_precond_morerows.allocate(*this); - if(m_cols!=m_cols) m_scaledMatrix.resize(rows,cols); + if(m_rows!=m_cols) m_scaledMatrix.resize(rows,cols); } template diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SVD/JacobiSVD_MKL.h b/thirdparty/eigen-3.2.7/Eigen/src/SVD/JacobiSVD_MKL.h index decda754..14e461c4 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/SVD/JacobiSVD_MKL.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/SVD/JacobiSVD_MKL.h @@ -45,8 +45,8 @@ JacobiSVD, ColPiv JacobiSVD, ColPivHouseholderQRPreconditioner>::compute(const Matrix& matrix, unsigned int computationOptions) \ { \ typedef Matrix MatrixType; \ - typedef MatrixType::Scalar Scalar; \ - typedef MatrixType::RealScalar RealScalar; \ + /*typedef MatrixType::Scalar Scalar;*/ \ + /*typedef MatrixType::RealScalar RealScalar;*/ \ allocate(matrix.rows(), matrix.cols(), computationOptions); \ \ /*const RealScalar precision = RealScalar(2) * NumTraits::epsilon();*/ \ diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseBlock.h b/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseBlock.h index 0c90bafb..4f498350 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseBlock.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseBlock.h @@ -364,10 +364,11 @@ class BlockImpl,BlockRows,BlockCol protected: + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl) + typename SparseMatrixType::Nested m_matrix; Index m_outerStart; const internal::variable_if_dynamic m_outerSize; - }; //---------- @@ -528,7 +529,8 @@ class BlockImpl const internal::variable_if_dynamic m_startCol; const internal::variable_if_dynamic m_blockRows; const internal::variable_if_dynamic m_blockCols; - + private: + Index nonZeros() const; }; } // end namespace Eigen diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseCwiseBinaryOp.h b/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseCwiseBinaryOp.h index 4ca91283..54627375 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseCwiseBinaryOp.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseCwiseBinaryOp.h @@ -55,10 +55,9 @@ class CwiseBinaryOpImpl EIGEN_SPARSE_PUBLIC_INTERFACE(Derived) CwiseBinaryOpImpl() { - typedef typename internal::traits::StorageKind LhsStorageKind; - typedef typename internal::traits::StorageKind RhsStorageKind; EIGEN_STATIC_ASSERT(( - (!internal::is_same::value) + (!internal::is_same::StorageKind, + typename internal::traits::StorageKind>::value) || ((Lhs::Flags&RowMajorBit) == (Rhs::Flags&RowMajorBit))), THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH); } diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseView.h b/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseView.h index fd845046..2820b39b 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseView.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseView.h @@ -35,9 +35,9 @@ class SparseView : public SparseMatrixBase > public: EIGEN_SPARSE_PUBLIC_INTERFACE(SparseView) - SparseView(const MatrixType& mat, const Scalar& m_reference = Scalar(0), - typename NumTraits::Real m_epsilon = NumTraits::dummy_precision()) : - m_matrix(mat), m_reference(m_reference), m_epsilon(m_epsilon) {} + explicit SparseView(const MatrixType& mat, const Scalar& reference = Scalar(0), + const RealScalar &epsilon = NumTraits::dummy_precision()) + : m_matrix(mat), m_reference(reference), m_epsilon(epsilon) {} class InnerIterator; diff --git a/thirdparty/eigen-3.2.7/Eigen/src/StlSupport/StdDeque.h b/thirdparty/eigen-3.2.7/Eigen/src/StlSupport/StdDeque.h index aaf66330..69a46b2b 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/StlSupport/StdDeque.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/StlSupport/StdDeque.h @@ -13,32 +13,24 @@ #include "details.h" -// Define the explicit instantiation (e.g. necessary for the Intel compiler) -#if defined(__INTEL_COMPILER) || defined(__GNUC__) - #define EIGEN_EXPLICIT_STL_DEQUE_INSTANTIATION(...) template class std::deque<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> >; -#else - #define EIGEN_EXPLICIT_STL_DEQUE_INSTANTIATION(...) -#endif - /** * This section contains a convenience MACRO which allows an easy specialization of * std::deque such that for data types with alignment issues the correct allocator * is used automatically. */ #define EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(...) \ -EIGEN_EXPLICIT_STL_DEQUE_INSTANTIATION(__VA_ARGS__) \ namespace std \ { \ - template \ - class deque<__VA_ARGS__, _Ay> \ + template<> \ + class deque<__VA_ARGS__, std::allocator<__VA_ARGS__> > \ : public deque<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> > \ { \ typedef deque<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> > deque_base; \ public: \ typedef __VA_ARGS__ value_type; \ - typedef typename deque_base::allocator_type allocator_type; \ - typedef typename deque_base::size_type size_type; \ - typedef typename deque_base::iterator iterator; \ + typedef deque_base::allocator_type allocator_type; \ + typedef deque_base::size_type size_type; \ + typedef deque_base::iterator iterator; \ explicit deque(const allocator_type& a = allocator_type()) : deque_base(a) {} \ template \ deque(InputIterator first, InputIterator last, const allocator_type& a = allocator_type()) : deque_base(first, last, a) {} \ diff --git a/thirdparty/eigen-3.2.7/Eigen/src/StlSupport/StdList.h b/thirdparty/eigen-3.2.7/Eigen/src/StlSupport/StdList.h index 3c742430..050c2373 100644 --- a/thirdparty/eigen-3.2.7/Eigen/src/StlSupport/StdList.h +++ b/thirdparty/eigen-3.2.7/Eigen/src/StlSupport/StdList.h @@ -12,32 +12,24 @@ #include "details.h" -// Define the explicit instantiation (e.g. necessary for the Intel compiler) -#if defined(__INTEL_COMPILER) || defined(__GNUC__) - #define EIGEN_EXPLICIT_STL_LIST_INSTANTIATION(...) template class std::list<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> >; -#else - #define EIGEN_EXPLICIT_STL_LIST_INSTANTIATION(...) -#endif - /** * This section contains a convenience MACRO which allows an easy specialization of * std::list such that for data types with alignment issues the correct allocator * is used automatically. */ #define EIGEN_DEFINE_STL_LIST_SPECIALIZATION(...) \ -EIGEN_EXPLICIT_STL_LIST_INSTANTIATION(__VA_ARGS__) \ namespace std \ { \ - template \ - class list<__VA_ARGS__, _Ay> \ + template<> \ + class list<__VA_ARGS__, std::allocator<__VA_ARGS__> > \ : public list<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> > \ { \ typedef list<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> > list_base; \ public: \ typedef __VA_ARGS__ value_type; \ - typedef typename list_base::allocator_type allocator_type; \ - typedef typename list_base::size_type size_type; \ - typedef typename list_base::iterator iterator; \ + typedef list_base::allocator_type allocator_type; \ + typedef list_base::size_type size_type; \ + typedef list_base::iterator iterator; \ explicit list(const allocator_type& a = allocator_type()) : list_base(a) {} \ template \ list(InputIterator first, InputIterator last, const allocator_type& a = allocator_type()) : list_base(first, last, a) {} \ From d11d8023892746c6b1a3bd80c9c8de32e188da80 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Sat, 27 Feb 2016 16:08:02 +0100 Subject: [PATCH 206/402] eigen3.2.7/ --> eigen3.2.8/ Signed-off-by: Etienne Schmitt --- thirdparty/CMakeLists.txt | 2 +- thirdparty/{eigen-3.2.7 => eigen-3.2.8}/CMakeLists.txt | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/Array | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/Cholesky | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/CholmodSupport | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/Core | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/Dense | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/Eigen | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/Eigen2Support | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/Eigenvalues | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/Geometry | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/Householder | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/IterativeLinearSolvers | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/Jacobi | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/LU | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/LeastSquares | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/MetisSupport | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/OrderingMethods | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/PaStiXSupport | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/PardisoSupport | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/QR | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/QtAlignedMalloc | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/SPQRSupport | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/SVD | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/Sparse | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/SparseCholesky | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/SparseCore | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/SparseLU | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/SparseQR | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/StdDeque | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/StdList | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/StdVector | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/SuperLUSupport | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/UmfPackSupport | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Cholesky/LDLT.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Cholesky/LLT.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Cholesky/LLT_MKL.h | 0 .../Eigen/src/CholmodSupport/CholmodSupport.h | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Array.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/ArrayBase.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/ArrayWrapper.h | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Assign.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Assign_MKL.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/BandMatrix.h | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Block.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/BooleanRedux.h | 0 .../Eigen/src/Core/CommaInitializer.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/CoreIterators.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/CwiseBinaryOp.h | 0 .../Eigen/src/Core/CwiseNullaryOp.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/CwiseUnaryOp.h | 0 .../Eigen/src/Core/CwiseUnaryView.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/DenseBase.h | 0 .../Eigen/src/Core/DenseCoeffsBase.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/DenseStorage.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Diagonal.h | 0 .../Eigen/src/Core/DiagonalMatrix.h | 0 .../Eigen/src/Core/DiagonalProduct.h | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Dot.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/EigenBase.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Flagged.h | 0 .../Eigen/src/Core/ForceAlignedAccess.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Functors.h | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Fuzzy.h | 0 .../Eigen/src/Core/GeneralProduct.h | 0 .../Eigen/src/Core/GenericPacketMath.h | 0 .../Eigen/src/Core/GlobalFunctions.h | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/IO.h | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Map.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/MapBase.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/MathFunctions.h | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Matrix.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/MatrixBase.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/NestByValue.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/NoAlias.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/NumTraits.h | 0 .../Eigen/src/Core/PermutationMatrix.h | 0 .../Eigen/src/Core/PlainObjectBase.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/ProductBase.h | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Random.h | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Redux.h | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Ref.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Replicate.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/ReturnByValue.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Reverse.h | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Select.h | 0 .../Eigen/src/Core/SelfAdjointView.h | 0 .../Eigen/src/Core/SelfCwiseBinaryOp.h | 0 .../Eigen/src/Core/SolveTriangular.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/StableNorm.h | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Stride.h | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Swap.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Transpose.h | 0 .../Eigen/src/Core/Transpositions.h | 0 .../Eigen/src/Core/TriangularMatrix.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/VectorBlock.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/VectorwiseOp.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Visitor.h | 0 .../Eigen/src/Core/arch/AltiVec/Complex.h | 0 .../Eigen/src/Core/arch/AltiVec/PacketMath.h | 0 .../Eigen/src/Core/arch/Default/Settings.h | 0 .../Eigen/src/Core/arch/NEON/Complex.h | 0 .../Eigen/src/Core/arch/NEON/PacketMath.h | 0 .../Eigen/src/Core/arch/SSE/Complex.h | 0 .../Eigen/src/Core/arch/SSE/MathFunctions.h | 0 .../Eigen/src/Core/arch/SSE/PacketMath.h | 0 .../Eigen/src/Core/products/CoeffBasedProduct.h | 0 .../Eigen/src/Core/products/GeneralBlockPanelKernel.h | 0 .../Eigen/src/Core/products/GeneralMatrixMatrix.h | 0 .../Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h | 0 .../Eigen/src/Core/products/GeneralMatrixMatrixTriangular_MKL.h | 0 .../Eigen/src/Core/products/GeneralMatrixMatrix_MKL.h | 0 .../Eigen/src/Core/products/GeneralMatrixVector.h | 0 .../Eigen/src/Core/products/GeneralMatrixVector_MKL.h | 0 .../Eigen/src/Core/products/Parallelizer.h | 0 .../Eigen/src/Core/products/SelfadjointMatrixMatrix.h | 0 .../Eigen/src/Core/products/SelfadjointMatrixMatrix_MKL.h | 0 .../Eigen/src/Core/products/SelfadjointMatrixVector.h | 0 .../Eigen/src/Core/products/SelfadjointMatrixVector_MKL.h | 0 .../Eigen/src/Core/products/SelfadjointProduct.h | 0 .../Eigen/src/Core/products/SelfadjointRank2Update.h | 0 .../Eigen/src/Core/products/TriangularMatrixMatrix.h | 0 .../Eigen/src/Core/products/TriangularMatrixMatrix_MKL.h | 0 .../Eigen/src/Core/products/TriangularMatrixVector.h | 0 .../Eigen/src/Core/products/TriangularMatrixVector_MKL.h | 0 .../Eigen/src/Core/products/TriangularSolverMatrix.h | 0 .../Eigen/src/Core/products/TriangularSolverMatrix_MKL.h | 0 .../Eigen/src/Core/products/TriangularSolverVector.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/util/BlasUtil.h | 0 .../Eigen/src/Core/util/Constants.h | 0 .../Eigen/src/Core/util/DisableStupidWarnings.h | 0 .../Eigen/src/Core/util/ForwardDeclarations.h | 0 .../Eigen/src/Core/util/MKL_support.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/util/Macros.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/util/Memory.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/util/Meta.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/util/NonMPL2.h | 0 .../Eigen/src/Core/util/ReenableStupidWarnings.h | 0 .../Eigen/src/Core/util/StaticAssert.h | 0 .../Eigen/src/Core/util/XprHelper.h | 0 .../Eigen/src/Eigen2Support/Block.h | 0 .../Eigen/src/Eigen2Support/Cwise.h | 0 .../Eigen/src/Eigen2Support/CwiseOperators.h | 0 .../Eigen/src/Eigen2Support/Geometry/AlignedBox.h | 0 .../Eigen/src/Eigen2Support/Geometry/All.h | 0 .../Eigen/src/Eigen2Support/Geometry/AngleAxis.h | 0 .../Eigen/src/Eigen2Support/Geometry/Hyperplane.h | 0 .../Eigen/src/Eigen2Support/Geometry/ParametrizedLine.h | 0 .../Eigen/src/Eigen2Support/Geometry/Quaternion.h | 0 .../Eigen/src/Eigen2Support/Geometry/Rotation2D.h | 0 .../Eigen/src/Eigen2Support/Geometry/RotationBase.h | 0 .../Eigen/src/Eigen2Support/Geometry/Scaling.h | 0 .../Eigen/src/Eigen2Support/Geometry/Transform.h | 0 .../Eigen/src/Eigen2Support/Geometry/Translation.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/LU.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/Lazy.h | 0 .../Eigen/src/Eigen2Support/LeastSquares.h | 0 .../Eigen/src/Eigen2Support/Macros.h | 0 .../Eigen/src/Eigen2Support/MathFunctions.h | 0 .../Eigen/src/Eigen2Support/Memory.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/Meta.h | 0 .../Eigen/src/Eigen2Support/Minor.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/QR.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/SVD.h | 0 .../Eigen/src/Eigen2Support/TriangularSolver.h | 0 .../Eigen/src/Eigen2Support/VectorBlock.h | 0 .../Eigen/src/Eigenvalues/ComplexEigenSolver.h | 0 .../Eigen/src/Eigenvalues/ComplexSchur.h | 0 .../Eigen/src/Eigenvalues/ComplexSchur_MKL.h | 0 .../Eigen/src/Eigenvalues/EigenSolver.h | 0 .../Eigen/src/Eigenvalues/GeneralizedEigenSolver.h | 0 .../Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h | 0 .../Eigen/src/Eigenvalues/HessenbergDecomposition.h | 0 .../Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigenvalues/RealQZ.h | 0 .../Eigen/src/Eigenvalues/RealSchur.h | 0 .../Eigen/src/Eigenvalues/RealSchur_MKL.h | 0 .../Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h | 0 .../Eigen/src/Eigenvalues/SelfAdjointEigenSolver_MKL.h | 0 .../Eigen/src/Eigenvalues/Tridiagonalization.h | 0 .../Eigen/src/Geometry/AlignedBox.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Geometry/AngleAxis.h | 0 .../Eigen/src/Geometry/EulerAngles.h | 0 .../Eigen/src/Geometry/Homogeneous.h | 0 .../Eigen/src/Geometry/Hyperplane.h | 0 .../Eigen/src/Geometry/OrthoMethods.h | 0 .../Eigen/src/Geometry/ParametrizedLine.h | 0 .../Eigen/src/Geometry/Quaternion.h | 0 .../Eigen/src/Geometry/Rotation2D.h | 0 .../Eigen/src/Geometry/RotationBase.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Geometry/Scaling.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Geometry/Transform.h | 0 .../Eigen/src/Geometry/Translation.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Geometry/Umeyama.h | 0 .../Eigen/src/Geometry/arch/Geometry_SSE.h | 0 .../Eigen/src/Householder/BlockHouseholder.h | 0 .../Eigen/src/Householder/Householder.h | 0 .../Eigen/src/Householder/HouseholderSequence.h | 0 .../Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h | 0 .../Eigen/src/IterativeLinearSolvers/BiCGSTAB.h | 0 .../Eigen/src/IterativeLinearSolvers/ConjugateGradient.h | 0 .../Eigen/src/IterativeLinearSolvers/IncompleteLUT.h | 0 .../Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Jacobi/Jacobi.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/LU/Determinant.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/LU/FullPivLU.h | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/LU/Inverse.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/LU/PartialPivLU.h | 0 .../Eigen/src/LU/PartialPivLU_MKL.h | 0 .../Eigen/src/LU/arch/Inverse_SSE.h | 0 .../Eigen/src/MetisSupport/MetisSupport.h | 0 .../Eigen/src/OrderingMethods/Amd.h | 0 .../Eigen/src/OrderingMethods/Eigen_Colamd.h | 0 .../Eigen/src/OrderingMethods/Ordering.h | 0 .../Eigen/src/PaStiXSupport/PaStiXSupport.h | 0 .../Eigen/src/PardisoSupport/PardisoSupport.h | 0 .../Eigen/src/QR/ColPivHouseholderQR.h | 0 .../Eigen/src/QR/ColPivHouseholderQR_MKL.h | 0 .../Eigen/src/QR/FullPivHouseholderQR.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/QR/HouseholderQR.h | 0 .../Eigen/src/QR/HouseholderQR_MKL.h | 0 .../Eigen/src/SPQRSupport/SuiteSparseQRSupport.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SVD/JacobiSVD.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SVD/JacobiSVD_MKL.h | 0 .../Eigen/src/SVD/UpperBidiagonalization.h | 0 .../Eigen/src/SparseCholesky/SimplicialCholesky.h | 0 .../Eigen/src/SparseCholesky/SimplicialCholesky_impl.h | 0 .../Eigen/src/SparseCore/AmbiVector.h | 0 .../Eigen/src/SparseCore/CompressedStorage.h | 0 .../Eigen/src/SparseCore/ConservativeSparseSparseProduct.h | 0 .../Eigen/src/SparseCore/MappedSparseMatrix.h | 0 .../Eigen/src/SparseCore/SparseBlock.h | 0 .../Eigen/src/SparseCore/SparseColEtree.h | 0 .../Eigen/src/SparseCore/SparseCwiseBinaryOp.h | 0 .../Eigen/src/SparseCore/SparseCwiseUnaryOp.h | 0 .../Eigen/src/SparseCore/SparseDenseProduct.h | 0 .../Eigen/src/SparseCore/SparseDiagonalProduct.h | 0 .../Eigen/src/SparseCore/SparseDot.h | 0 .../Eigen/src/SparseCore/SparseFuzzy.h | 0 .../Eigen/src/SparseCore/SparseMatrix.h | 0 .../Eigen/src/SparseCore/SparseMatrixBase.h | 0 .../Eigen/src/SparseCore/SparsePermutation.h | 0 .../Eigen/src/SparseCore/SparseProduct.h | 0 .../Eigen/src/SparseCore/SparseRedux.h | 0 .../Eigen/src/SparseCore/SparseSelfAdjointView.h | 0 .../Eigen/src/SparseCore/SparseSparseProductWithPruning.h | 0 .../Eigen/src/SparseCore/SparseTranspose.h | 0 .../Eigen/src/SparseCore/SparseTriangularView.h | 0 .../Eigen/src/SparseCore/SparseUtil.h | 0 .../Eigen/src/SparseCore/SparseVector.h | 0 .../Eigen/src/SparseCore/SparseView.h | 0 .../Eigen/src/SparseCore/TriangularSolver.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseLU/SparseLU.h | 0 .../Eigen/src/SparseLU/SparseLUImpl.h | 0 .../Eigen/src/SparseLU/SparseLU_Memory.h | 0 .../Eigen/src/SparseLU/SparseLU_Structs.h | 0 .../Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h | 0 .../Eigen/src/SparseLU/SparseLU_Utils.h | 0 .../Eigen/src/SparseLU/SparseLU_column_bmod.h | 0 .../Eigen/src/SparseLU/SparseLU_column_dfs.h | 0 .../Eigen/src/SparseLU/SparseLU_copy_to_ucol.h | 0 .../Eigen/src/SparseLU/SparseLU_gemm_kernel.h | 0 .../Eigen/src/SparseLU/SparseLU_heap_relax_snode.h | 0 .../Eigen/src/SparseLU/SparseLU_kernel_bmod.h | 0 .../Eigen/src/SparseLU/SparseLU_panel_bmod.h | 0 .../Eigen/src/SparseLU/SparseLU_panel_dfs.h | 0 .../Eigen/src/SparseLU/SparseLU_pivotL.h | 0 .../Eigen/src/SparseLU/SparseLU_pruneL.h | 0 .../Eigen/src/SparseLU/SparseLU_relax_snode.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseQR/SparseQR.h | 0 .../Eigen/src/StlSupport/StdDeque.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/StlSupport/StdList.h | 0 .../Eigen/src/StlSupport/StdVector.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/StlSupport/details.h | 0 .../Eigen/src/SuperLUSupport/SuperLUSupport.h | 0 .../Eigen/src/UmfPackSupport/UmfPackSupport.h | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/misc/Image.h | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/misc/Kernel.h | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/misc/Solve.h | 0 .../{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/misc/SparseSolve.h | 0 thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/misc/blas.h | 0 .../Eigen/src/plugins/ArrayCwiseBinaryOps.h | 0 .../Eigen/src/plugins/ArrayCwiseUnaryOps.h | 0 .../Eigen/src/plugins/BlockMethods.h | 0 .../Eigen/src/plugins/CommonCwiseBinaryOps.h | 0 .../Eigen/src/plugins/CommonCwiseUnaryOps.h | 0 .../Eigen/src/plugins/MatrixCwiseBinaryOps.h | 0 .../Eigen/src/plugins/MatrixCwiseUnaryOps.h | 0 288 files changed, 1 insertion(+), 1 deletion(-) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/CMakeLists.txt (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/Array (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/Cholesky (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/CholmodSupport (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/Core (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/Dense (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/Eigen (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/Eigen2Support (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/Eigenvalues (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/Geometry (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/Householder (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/IterativeLinearSolvers (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/Jacobi (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/LU (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/LeastSquares (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/MetisSupport (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/OrderingMethods (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/PaStiXSupport (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/PardisoSupport (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/QR (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/QtAlignedMalloc (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/SPQRSupport (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/SVD (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/Sparse (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/SparseCholesky (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/SparseCore (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/SparseLU (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/SparseQR (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/StdDeque (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/StdList (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/StdVector (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/SuperLUSupport (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/UmfPackSupport (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Cholesky/LDLT.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Cholesky/LLT.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Cholesky/LLT_MKL.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/CholmodSupport/CholmodSupport.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Array.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/ArrayBase.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/ArrayWrapper.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Assign.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Assign_MKL.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/BandMatrix.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Block.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/BooleanRedux.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/CommaInitializer.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/CoreIterators.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/CwiseBinaryOp.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/CwiseNullaryOp.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/CwiseUnaryOp.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/CwiseUnaryView.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/DenseBase.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/DenseCoeffsBase.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/DenseStorage.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Diagonal.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/DiagonalMatrix.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/DiagonalProduct.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Dot.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/EigenBase.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Flagged.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/ForceAlignedAccess.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Functors.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Fuzzy.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/GeneralProduct.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/GenericPacketMath.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/GlobalFunctions.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/IO.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Map.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/MapBase.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/MathFunctions.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Matrix.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/MatrixBase.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/NestByValue.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/NoAlias.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/NumTraits.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/PermutationMatrix.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/PlainObjectBase.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/ProductBase.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Random.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Redux.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Ref.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Replicate.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/ReturnByValue.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Reverse.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Select.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/SelfAdjointView.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/SelfCwiseBinaryOp.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/SolveTriangular.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/StableNorm.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Stride.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Swap.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Transpose.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Transpositions.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/TriangularMatrix.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/VectorBlock.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/VectorwiseOp.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/Visitor.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/arch/AltiVec/Complex.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/arch/AltiVec/PacketMath.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/arch/Default/Settings.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/arch/NEON/Complex.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/arch/NEON/PacketMath.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/arch/SSE/Complex.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/arch/SSE/MathFunctions.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/arch/SSE/PacketMath.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/products/CoeffBasedProduct.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/products/GeneralBlockPanelKernel.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/products/GeneralMatrixMatrix.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_MKL.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/products/GeneralMatrixMatrix_MKL.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/products/GeneralMatrixVector.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/products/GeneralMatrixVector_MKL.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/products/Parallelizer.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/products/SelfadjointMatrixMatrix.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/products/SelfadjointMatrixMatrix_MKL.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/products/SelfadjointMatrixVector.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/products/SelfadjointMatrixVector_MKL.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/products/SelfadjointProduct.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/products/SelfadjointRank2Update.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/products/TriangularMatrixMatrix.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/products/TriangularMatrixMatrix_MKL.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/products/TriangularMatrixVector.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/products/TriangularMatrixVector_MKL.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/products/TriangularSolverMatrix.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/products/TriangularSolverMatrix_MKL.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/products/TriangularSolverVector.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/util/BlasUtil.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/util/Constants.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/util/DisableStupidWarnings.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/util/ForwardDeclarations.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/util/MKL_support.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/util/Macros.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/util/Memory.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/util/Meta.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/util/NonMPL2.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/util/ReenableStupidWarnings.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/util/StaticAssert.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Core/util/XprHelper.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/Block.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/Cwise.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/CwiseOperators.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/Geometry/AlignedBox.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/Geometry/All.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/Geometry/AngleAxis.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/Geometry/Hyperplane.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/Geometry/ParametrizedLine.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/Geometry/Quaternion.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/Geometry/Rotation2D.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/Geometry/RotationBase.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/Geometry/Scaling.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/Geometry/Transform.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/Geometry/Translation.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/LU.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/Lazy.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/LeastSquares.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/Macros.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/MathFunctions.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/Memory.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/Meta.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/Minor.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/QR.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/SVD.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/TriangularSolver.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigen2Support/VectorBlock.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigenvalues/ComplexEigenSolver.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigenvalues/ComplexSchur.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigenvalues/ComplexSchur_MKL.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigenvalues/EigenSolver.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigenvalues/HessenbergDecomposition.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigenvalues/RealQZ.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigenvalues/RealSchur.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigenvalues/RealSchur_MKL.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_MKL.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Eigenvalues/Tridiagonalization.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Geometry/AlignedBox.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Geometry/AngleAxis.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Geometry/EulerAngles.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Geometry/Homogeneous.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Geometry/Hyperplane.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Geometry/OrthoMethods.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Geometry/ParametrizedLine.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Geometry/Quaternion.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Geometry/Rotation2D.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Geometry/RotationBase.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Geometry/Scaling.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Geometry/Transform.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Geometry/Translation.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Geometry/Umeyama.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Geometry/arch/Geometry_SSE.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Householder/BlockHouseholder.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Householder/Householder.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Householder/HouseholderSequence.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/Jacobi/Jacobi.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/LU/Determinant.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/LU/FullPivLU.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/LU/Inverse.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/LU/PartialPivLU.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/LU/PartialPivLU_MKL.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/LU/arch/Inverse_SSE.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/MetisSupport/MetisSupport.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/OrderingMethods/Amd.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/OrderingMethods/Eigen_Colamd.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/OrderingMethods/Ordering.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/PaStiXSupport/PaStiXSupport.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/PardisoSupport/PardisoSupport.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/QR/ColPivHouseholderQR.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/QR/ColPivHouseholderQR_MKL.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/QR/FullPivHouseholderQR.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/QR/HouseholderQR.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/QR/HouseholderQR_MKL.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SVD/JacobiSVD.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SVD/JacobiSVD_MKL.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SVD/UpperBidiagonalization.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseCholesky/SimplicialCholesky.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseCore/AmbiVector.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseCore/CompressedStorage.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseCore/MappedSparseMatrix.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseCore/SparseBlock.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseCore/SparseColEtree.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseCore/SparseCwiseBinaryOp.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseCore/SparseCwiseUnaryOp.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseCore/SparseDenseProduct.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseCore/SparseDiagonalProduct.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseCore/SparseDot.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseCore/SparseFuzzy.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseCore/SparseMatrix.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseCore/SparseMatrixBase.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseCore/SparsePermutation.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseCore/SparseProduct.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseCore/SparseRedux.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseCore/SparseSelfAdjointView.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseCore/SparseSparseProductWithPruning.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseCore/SparseTranspose.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseCore/SparseTriangularView.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseCore/SparseUtil.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseCore/SparseVector.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseCore/SparseView.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseCore/TriangularSolver.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseLU/SparseLU.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseLU/SparseLUImpl.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseLU/SparseLU_Memory.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseLU/SparseLU_Structs.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseLU/SparseLU_Utils.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseLU/SparseLU_column_bmod.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseLU/SparseLU_column_dfs.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseLU/SparseLU_copy_to_ucol.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseLU/SparseLU_gemm_kernel.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseLU/SparseLU_heap_relax_snode.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseLU/SparseLU_kernel_bmod.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseLU/SparseLU_panel_bmod.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseLU/SparseLU_panel_dfs.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseLU/SparseLU_pivotL.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseLU/SparseLU_pruneL.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseLU/SparseLU_relax_snode.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SparseQR/SparseQR.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/StlSupport/StdDeque.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/StlSupport/StdList.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/StlSupport/StdVector.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/StlSupport/details.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/SuperLUSupport/SuperLUSupport.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/UmfPackSupport/UmfPackSupport.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/misc/Image.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/misc/Kernel.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/misc/Solve.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/misc/SparseSolve.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/misc/blas.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/plugins/ArrayCwiseBinaryOps.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/plugins/ArrayCwiseUnaryOps.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/plugins/BlockMethods.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/plugins/CommonCwiseBinaryOps.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/plugins/CommonCwiseUnaryOps.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/plugins/MatrixCwiseBinaryOps.h (100%) rename thirdparty/{eigen-3.2.7 => eigen-3.2.8}/Eigen/src/plugins/MatrixCwiseUnaryOps.h (100%) diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index 55c6adac..c4a92db5 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -1,5 +1,5 @@ if(CGOGN_PROVIDE_EIGEN) - add_subdirectory(eigen-3.2.7) + add_subdirectory(eigen-3.2.8) endif(CGOGN_PROVIDE_EIGEN) if(CGOGN_PROVIDE_TINYXML2) diff --git a/thirdparty/eigen-3.2.7/CMakeLists.txt b/thirdparty/eigen-3.2.8/CMakeLists.txt similarity index 100% rename from thirdparty/eigen-3.2.7/CMakeLists.txt rename to thirdparty/eigen-3.2.8/CMakeLists.txt diff --git a/thirdparty/eigen-3.2.7/Eigen/Array b/thirdparty/eigen-3.2.8/Eigen/Array similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/Array rename to thirdparty/eigen-3.2.8/Eigen/Array diff --git a/thirdparty/eigen-3.2.7/Eigen/Cholesky b/thirdparty/eigen-3.2.8/Eigen/Cholesky similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/Cholesky rename to thirdparty/eigen-3.2.8/Eigen/Cholesky diff --git a/thirdparty/eigen-3.2.7/Eigen/CholmodSupport b/thirdparty/eigen-3.2.8/Eigen/CholmodSupport similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/CholmodSupport rename to thirdparty/eigen-3.2.8/Eigen/CholmodSupport diff --git a/thirdparty/eigen-3.2.7/Eigen/Core b/thirdparty/eigen-3.2.8/Eigen/Core similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/Core rename to thirdparty/eigen-3.2.8/Eigen/Core diff --git a/thirdparty/eigen-3.2.7/Eigen/Dense b/thirdparty/eigen-3.2.8/Eigen/Dense similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/Dense rename to thirdparty/eigen-3.2.8/Eigen/Dense diff --git a/thirdparty/eigen-3.2.7/Eigen/Eigen b/thirdparty/eigen-3.2.8/Eigen/Eigen similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/Eigen rename to thirdparty/eigen-3.2.8/Eigen/Eigen diff --git a/thirdparty/eigen-3.2.7/Eigen/Eigen2Support b/thirdparty/eigen-3.2.8/Eigen/Eigen2Support similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/Eigen2Support rename to thirdparty/eigen-3.2.8/Eigen/Eigen2Support diff --git a/thirdparty/eigen-3.2.7/Eigen/Eigenvalues b/thirdparty/eigen-3.2.8/Eigen/Eigenvalues similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/Eigenvalues rename to thirdparty/eigen-3.2.8/Eigen/Eigenvalues diff --git a/thirdparty/eigen-3.2.7/Eigen/Geometry b/thirdparty/eigen-3.2.8/Eigen/Geometry similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/Geometry rename to thirdparty/eigen-3.2.8/Eigen/Geometry diff --git a/thirdparty/eigen-3.2.7/Eigen/Householder b/thirdparty/eigen-3.2.8/Eigen/Householder similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/Householder rename to thirdparty/eigen-3.2.8/Eigen/Householder diff --git a/thirdparty/eigen-3.2.7/Eigen/IterativeLinearSolvers b/thirdparty/eigen-3.2.8/Eigen/IterativeLinearSolvers similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/IterativeLinearSolvers rename to thirdparty/eigen-3.2.8/Eigen/IterativeLinearSolvers diff --git a/thirdparty/eigen-3.2.7/Eigen/Jacobi b/thirdparty/eigen-3.2.8/Eigen/Jacobi similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/Jacobi rename to thirdparty/eigen-3.2.8/Eigen/Jacobi diff --git a/thirdparty/eigen-3.2.7/Eigen/LU b/thirdparty/eigen-3.2.8/Eigen/LU similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/LU rename to thirdparty/eigen-3.2.8/Eigen/LU diff --git a/thirdparty/eigen-3.2.7/Eigen/LeastSquares b/thirdparty/eigen-3.2.8/Eigen/LeastSquares similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/LeastSquares rename to thirdparty/eigen-3.2.8/Eigen/LeastSquares diff --git a/thirdparty/eigen-3.2.7/Eigen/MetisSupport b/thirdparty/eigen-3.2.8/Eigen/MetisSupport similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/MetisSupport rename to thirdparty/eigen-3.2.8/Eigen/MetisSupport diff --git a/thirdparty/eigen-3.2.7/Eigen/OrderingMethods b/thirdparty/eigen-3.2.8/Eigen/OrderingMethods similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/OrderingMethods rename to thirdparty/eigen-3.2.8/Eigen/OrderingMethods diff --git a/thirdparty/eigen-3.2.7/Eigen/PaStiXSupport b/thirdparty/eigen-3.2.8/Eigen/PaStiXSupport similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/PaStiXSupport rename to thirdparty/eigen-3.2.8/Eigen/PaStiXSupport diff --git a/thirdparty/eigen-3.2.7/Eigen/PardisoSupport b/thirdparty/eigen-3.2.8/Eigen/PardisoSupport similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/PardisoSupport rename to thirdparty/eigen-3.2.8/Eigen/PardisoSupport diff --git a/thirdparty/eigen-3.2.7/Eigen/QR b/thirdparty/eigen-3.2.8/Eigen/QR similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/QR rename to thirdparty/eigen-3.2.8/Eigen/QR diff --git a/thirdparty/eigen-3.2.7/Eigen/QtAlignedMalloc b/thirdparty/eigen-3.2.8/Eigen/QtAlignedMalloc similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/QtAlignedMalloc rename to thirdparty/eigen-3.2.8/Eigen/QtAlignedMalloc diff --git a/thirdparty/eigen-3.2.7/Eigen/SPQRSupport b/thirdparty/eigen-3.2.8/Eigen/SPQRSupport similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/SPQRSupport rename to thirdparty/eigen-3.2.8/Eigen/SPQRSupport diff --git a/thirdparty/eigen-3.2.7/Eigen/SVD b/thirdparty/eigen-3.2.8/Eigen/SVD similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/SVD rename to thirdparty/eigen-3.2.8/Eigen/SVD diff --git a/thirdparty/eigen-3.2.7/Eigen/Sparse b/thirdparty/eigen-3.2.8/Eigen/Sparse similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/Sparse rename to thirdparty/eigen-3.2.8/Eigen/Sparse diff --git a/thirdparty/eigen-3.2.7/Eigen/SparseCholesky b/thirdparty/eigen-3.2.8/Eigen/SparseCholesky similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/SparseCholesky rename to thirdparty/eigen-3.2.8/Eigen/SparseCholesky diff --git a/thirdparty/eigen-3.2.7/Eigen/SparseCore b/thirdparty/eigen-3.2.8/Eigen/SparseCore similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/SparseCore rename to thirdparty/eigen-3.2.8/Eigen/SparseCore diff --git a/thirdparty/eigen-3.2.7/Eigen/SparseLU b/thirdparty/eigen-3.2.8/Eigen/SparseLU similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/SparseLU rename to thirdparty/eigen-3.2.8/Eigen/SparseLU diff --git a/thirdparty/eigen-3.2.7/Eigen/SparseQR b/thirdparty/eigen-3.2.8/Eigen/SparseQR similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/SparseQR rename to thirdparty/eigen-3.2.8/Eigen/SparseQR diff --git a/thirdparty/eigen-3.2.7/Eigen/StdDeque b/thirdparty/eigen-3.2.8/Eigen/StdDeque similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/StdDeque rename to thirdparty/eigen-3.2.8/Eigen/StdDeque diff --git a/thirdparty/eigen-3.2.7/Eigen/StdList b/thirdparty/eigen-3.2.8/Eigen/StdList similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/StdList rename to thirdparty/eigen-3.2.8/Eigen/StdList diff --git a/thirdparty/eigen-3.2.7/Eigen/StdVector b/thirdparty/eigen-3.2.8/Eigen/StdVector similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/StdVector rename to thirdparty/eigen-3.2.8/Eigen/StdVector diff --git a/thirdparty/eigen-3.2.7/Eigen/SuperLUSupport b/thirdparty/eigen-3.2.8/Eigen/SuperLUSupport similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/SuperLUSupport rename to thirdparty/eigen-3.2.8/Eigen/SuperLUSupport diff --git a/thirdparty/eigen-3.2.7/Eigen/UmfPackSupport b/thirdparty/eigen-3.2.8/Eigen/UmfPackSupport similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/UmfPackSupport rename to thirdparty/eigen-3.2.8/Eigen/UmfPackSupport diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Cholesky/LDLT.h b/thirdparty/eigen-3.2.8/Eigen/src/Cholesky/LDLT.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Cholesky/LDLT.h rename to thirdparty/eigen-3.2.8/Eigen/src/Cholesky/LDLT.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Cholesky/LLT.h b/thirdparty/eigen-3.2.8/Eigen/src/Cholesky/LLT.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Cholesky/LLT.h rename to thirdparty/eigen-3.2.8/Eigen/src/Cholesky/LLT.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Cholesky/LLT_MKL.h b/thirdparty/eigen-3.2.8/Eigen/src/Cholesky/LLT_MKL.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Cholesky/LLT_MKL.h rename to thirdparty/eigen-3.2.8/Eigen/src/Cholesky/LLT_MKL.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/CholmodSupport/CholmodSupport.h b/thirdparty/eigen-3.2.8/Eigen/src/CholmodSupport/CholmodSupport.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/CholmodSupport/CholmodSupport.h rename to thirdparty/eigen-3.2.8/Eigen/src/CholmodSupport/CholmodSupport.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/Array.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/Array.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/Array.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/Array.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/ArrayBase.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/ArrayBase.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/ArrayBase.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/ArrayBase.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/ArrayWrapper.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/ArrayWrapper.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/ArrayWrapper.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/ArrayWrapper.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/Assign.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/Assign.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/Assign.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/Assign.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/Assign_MKL.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/Assign_MKL.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/Assign_MKL.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/Assign_MKL.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/BandMatrix.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/BandMatrix.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/BandMatrix.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/BandMatrix.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/Block.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/Block.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/Block.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/Block.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/BooleanRedux.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/BooleanRedux.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/BooleanRedux.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/BooleanRedux.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/CommaInitializer.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/CommaInitializer.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/CommaInitializer.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/CommaInitializer.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/CoreIterators.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/CoreIterators.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/CoreIterators.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/CoreIterators.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/CwiseBinaryOp.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/CwiseBinaryOp.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/CwiseBinaryOp.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/CwiseBinaryOp.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/CwiseNullaryOp.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/CwiseNullaryOp.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/CwiseNullaryOp.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/CwiseNullaryOp.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/CwiseUnaryOp.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/CwiseUnaryOp.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/CwiseUnaryOp.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/CwiseUnaryOp.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/CwiseUnaryView.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/CwiseUnaryView.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/CwiseUnaryView.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/CwiseUnaryView.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/DenseBase.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/DenseBase.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/DenseBase.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/DenseBase.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/DenseCoeffsBase.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/DenseCoeffsBase.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/DenseCoeffsBase.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/DenseCoeffsBase.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/DenseStorage.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/DenseStorage.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/DenseStorage.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/DenseStorage.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/Diagonal.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/Diagonal.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/Diagonal.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/Diagonal.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/DiagonalMatrix.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/DiagonalMatrix.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/DiagonalMatrix.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/DiagonalMatrix.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/DiagonalProduct.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/DiagonalProduct.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/DiagonalProduct.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/DiagonalProduct.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/Dot.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/Dot.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/Dot.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/Dot.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/EigenBase.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/EigenBase.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/EigenBase.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/EigenBase.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/Flagged.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/Flagged.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/Flagged.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/Flagged.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/ForceAlignedAccess.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/ForceAlignedAccess.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/ForceAlignedAccess.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/ForceAlignedAccess.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/Functors.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/Functors.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/Functors.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/Functors.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/Fuzzy.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/Fuzzy.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/Fuzzy.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/Fuzzy.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/GeneralProduct.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/GeneralProduct.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/GeneralProduct.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/GeneralProduct.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/GenericPacketMath.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/GenericPacketMath.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/GenericPacketMath.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/GenericPacketMath.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/GlobalFunctions.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/GlobalFunctions.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/GlobalFunctions.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/GlobalFunctions.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/IO.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/IO.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/IO.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/IO.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/Map.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/Map.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/Map.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/Map.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/MapBase.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/MapBase.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/MapBase.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/MapBase.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/MathFunctions.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/MathFunctions.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/MathFunctions.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/MathFunctions.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/Matrix.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/Matrix.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/Matrix.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/Matrix.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/MatrixBase.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/MatrixBase.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/MatrixBase.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/MatrixBase.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/NestByValue.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/NestByValue.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/NestByValue.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/NestByValue.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/NoAlias.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/NoAlias.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/NoAlias.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/NoAlias.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/NumTraits.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/NumTraits.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/NumTraits.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/NumTraits.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/PermutationMatrix.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/PermutationMatrix.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/PermutationMatrix.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/PermutationMatrix.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/PlainObjectBase.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/PlainObjectBase.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/PlainObjectBase.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/PlainObjectBase.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/ProductBase.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/ProductBase.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/ProductBase.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/ProductBase.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/Random.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/Random.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/Random.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/Random.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/Redux.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/Redux.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/Redux.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/Redux.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/Ref.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/Ref.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/Ref.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/Ref.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/Replicate.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/Replicate.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/Replicate.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/Replicate.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/ReturnByValue.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/ReturnByValue.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/ReturnByValue.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/ReturnByValue.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/Reverse.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/Reverse.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/Reverse.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/Reverse.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/Select.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/Select.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/Select.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/Select.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/SelfAdjointView.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/SelfAdjointView.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/SelfAdjointView.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/SelfAdjointView.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/SelfCwiseBinaryOp.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/SelfCwiseBinaryOp.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/SelfCwiseBinaryOp.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/SelfCwiseBinaryOp.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/SolveTriangular.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/SolveTriangular.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/SolveTriangular.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/SolveTriangular.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/StableNorm.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/StableNorm.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/StableNorm.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/StableNorm.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/Stride.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/Stride.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/Stride.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/Stride.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/Swap.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/Swap.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/Swap.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/Swap.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/Transpose.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/Transpose.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/Transpose.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/Transpose.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/Transpositions.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/Transpositions.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/Transpositions.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/Transpositions.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/TriangularMatrix.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/TriangularMatrix.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/TriangularMatrix.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/TriangularMatrix.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/VectorBlock.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/VectorBlock.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/VectorBlock.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/VectorBlock.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/VectorwiseOp.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/VectorwiseOp.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/VectorwiseOp.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/VectorwiseOp.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/Visitor.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/Visitor.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/Visitor.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/Visitor.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/arch/AltiVec/Complex.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/arch/AltiVec/Complex.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/arch/AltiVec/Complex.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/arch/AltiVec/Complex.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/arch/AltiVec/PacketMath.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/arch/AltiVec/PacketMath.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/arch/AltiVec/PacketMath.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/arch/AltiVec/PacketMath.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/arch/Default/Settings.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/arch/Default/Settings.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/arch/Default/Settings.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/arch/Default/Settings.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/arch/NEON/Complex.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/arch/NEON/Complex.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/arch/NEON/Complex.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/arch/NEON/Complex.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/arch/NEON/PacketMath.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/arch/NEON/PacketMath.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/arch/NEON/PacketMath.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/arch/NEON/PacketMath.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/arch/SSE/Complex.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/arch/SSE/Complex.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/arch/SSE/Complex.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/arch/SSE/Complex.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/arch/SSE/MathFunctions.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/arch/SSE/MathFunctions.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/arch/SSE/MathFunctions.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/arch/SSE/MathFunctions.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/arch/SSE/PacketMath.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/arch/SSE/PacketMath.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/arch/SSE/PacketMath.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/arch/SSE/PacketMath.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/products/CoeffBasedProduct.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/products/CoeffBasedProduct.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/products/CoeffBasedProduct.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/products/CoeffBasedProduct.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/products/GeneralBlockPanelKernel.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/products/GeneralBlockPanelKernel.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/products/GeneralBlockPanelKernel.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/products/GeneralBlockPanelKernel.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/products/GeneralMatrixMatrix.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/products/GeneralMatrixMatrix.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/products/GeneralMatrixMatrix.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/products/GeneralMatrixMatrix.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_MKL.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_MKL.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_MKL.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_MKL.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/products/GeneralMatrixMatrix_MKL.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/products/GeneralMatrixMatrix_MKL.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/products/GeneralMatrixMatrix_MKL.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/products/GeneralMatrixMatrix_MKL.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/products/GeneralMatrixVector.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/products/GeneralMatrixVector.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/products/GeneralMatrixVector.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/products/GeneralMatrixVector.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/products/GeneralMatrixVector_MKL.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/products/GeneralMatrixVector_MKL.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/products/GeneralMatrixVector_MKL.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/products/GeneralMatrixVector_MKL.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/products/Parallelizer.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/products/Parallelizer.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/products/Parallelizer.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/products/Parallelizer.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/products/SelfadjointMatrixMatrix.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/products/SelfadjointMatrixMatrix.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/products/SelfadjointMatrixMatrix.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/products/SelfadjointMatrixMatrix.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/products/SelfadjointMatrixMatrix_MKL.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/products/SelfadjointMatrixMatrix_MKL.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/products/SelfadjointMatrixMatrix_MKL.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/products/SelfadjointMatrixMatrix_MKL.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/products/SelfadjointMatrixVector.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/products/SelfadjointMatrixVector.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/products/SelfadjointMatrixVector.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/products/SelfadjointMatrixVector.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/products/SelfadjointMatrixVector_MKL.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/products/SelfadjointMatrixVector_MKL.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/products/SelfadjointMatrixVector_MKL.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/products/SelfadjointMatrixVector_MKL.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/products/SelfadjointProduct.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/products/SelfadjointProduct.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/products/SelfadjointProduct.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/products/SelfadjointProduct.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/products/SelfadjointRank2Update.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/products/SelfadjointRank2Update.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/products/SelfadjointRank2Update.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/products/SelfadjointRank2Update.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/products/TriangularMatrixMatrix.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/products/TriangularMatrixMatrix.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/products/TriangularMatrixMatrix.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/products/TriangularMatrixMatrix.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/products/TriangularMatrixMatrix_MKL.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/products/TriangularMatrixMatrix_MKL.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/products/TriangularMatrixMatrix_MKL.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/products/TriangularMatrixMatrix_MKL.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/products/TriangularMatrixVector.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/products/TriangularMatrixVector.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/products/TriangularMatrixVector.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/products/TriangularMatrixVector.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/products/TriangularMatrixVector_MKL.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/products/TriangularMatrixVector_MKL.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/products/TriangularMatrixVector_MKL.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/products/TriangularMatrixVector_MKL.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/products/TriangularSolverMatrix.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/products/TriangularSolverMatrix.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/products/TriangularSolverMatrix.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/products/TriangularSolverMatrix.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/products/TriangularSolverMatrix_MKL.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/products/TriangularSolverMatrix_MKL.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/products/TriangularSolverMatrix_MKL.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/products/TriangularSolverMatrix_MKL.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/products/TriangularSolverVector.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/products/TriangularSolverVector.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/products/TriangularSolverVector.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/products/TriangularSolverVector.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/util/BlasUtil.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/util/BlasUtil.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/util/BlasUtil.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/util/BlasUtil.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/util/Constants.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/util/Constants.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/util/Constants.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/util/Constants.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/util/DisableStupidWarnings.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/util/DisableStupidWarnings.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/util/DisableStupidWarnings.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/util/DisableStupidWarnings.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/util/ForwardDeclarations.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/util/ForwardDeclarations.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/util/ForwardDeclarations.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/util/ForwardDeclarations.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/util/MKL_support.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/util/MKL_support.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/util/MKL_support.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/util/MKL_support.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/util/Macros.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/util/Macros.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/util/Macros.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/util/Macros.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/util/Memory.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/util/Memory.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/util/Memory.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/util/Memory.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/util/Meta.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/util/Meta.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/util/Meta.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/util/Meta.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/util/NonMPL2.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/util/NonMPL2.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/util/NonMPL2.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/util/NonMPL2.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/util/ReenableStupidWarnings.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/util/ReenableStupidWarnings.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/util/ReenableStupidWarnings.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/util/ReenableStupidWarnings.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/util/StaticAssert.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/util/StaticAssert.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/util/StaticAssert.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/util/StaticAssert.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Core/util/XprHelper.h b/thirdparty/eigen-3.2.8/Eigen/src/Core/util/XprHelper.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Core/util/XprHelper.h rename to thirdparty/eigen-3.2.8/Eigen/src/Core/util/XprHelper.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Block.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Block.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Block.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Block.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Cwise.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Cwise.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Cwise.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Cwise.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/CwiseOperators.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/CwiseOperators.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/CwiseOperators.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/CwiseOperators.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Geometry/AlignedBox.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Geometry/AlignedBox.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Geometry/AlignedBox.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Geometry/AlignedBox.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Geometry/All.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Geometry/All.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Geometry/All.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Geometry/All.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Geometry/AngleAxis.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Geometry/AngleAxis.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Geometry/AngleAxis.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Geometry/AngleAxis.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Geometry/Hyperplane.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Geometry/Hyperplane.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Geometry/Hyperplane.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Geometry/Hyperplane.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Geometry/ParametrizedLine.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Geometry/ParametrizedLine.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Geometry/ParametrizedLine.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Geometry/ParametrizedLine.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Geometry/Quaternion.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Geometry/Quaternion.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Geometry/Quaternion.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Geometry/Quaternion.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Geometry/Rotation2D.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Geometry/Rotation2D.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Geometry/Rotation2D.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Geometry/Rotation2D.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Geometry/RotationBase.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Geometry/RotationBase.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Geometry/RotationBase.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Geometry/RotationBase.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Geometry/Scaling.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Geometry/Scaling.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Geometry/Scaling.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Geometry/Scaling.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Geometry/Transform.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Geometry/Transform.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Geometry/Transform.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Geometry/Transform.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Geometry/Translation.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Geometry/Translation.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Geometry/Translation.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Geometry/Translation.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/LU.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/LU.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/LU.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/LU.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Lazy.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Lazy.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Lazy.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Lazy.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/LeastSquares.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/LeastSquares.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/LeastSquares.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/LeastSquares.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Macros.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Macros.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Macros.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Macros.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/MathFunctions.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/MathFunctions.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/MathFunctions.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/MathFunctions.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Memory.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Memory.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Memory.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Memory.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Meta.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Meta.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Meta.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Meta.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Minor.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Minor.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/Minor.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/Minor.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/QR.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/QR.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/QR.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/QR.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/SVD.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/SVD.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/SVD.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/SVD.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/TriangularSolver.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/TriangularSolver.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/TriangularSolver.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/TriangularSolver.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/VectorBlock.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/VectorBlock.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigen2Support/VectorBlock.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigen2Support/VectorBlock.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/ComplexEigenSolver.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/ComplexEigenSolver.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/ComplexEigenSolver.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/ComplexEigenSolver.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/ComplexSchur.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/ComplexSchur.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/ComplexSchur.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/ComplexSchur.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/ComplexSchur_MKL.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/ComplexSchur_MKL.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/ComplexSchur_MKL.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/ComplexSchur_MKL.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/EigenSolver.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/EigenSolver.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/EigenSolver.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/EigenSolver.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/HessenbergDecomposition.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/HessenbergDecomposition.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/HessenbergDecomposition.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/HessenbergDecomposition.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/RealQZ.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/RealQZ.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/RealQZ.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/RealQZ.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/RealSchur.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/RealSchur.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/RealSchur.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/RealSchur.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/RealSchur_MKL.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/RealSchur_MKL.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/RealSchur_MKL.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/RealSchur_MKL.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_MKL.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_MKL.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_MKL.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_MKL.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/Tridiagonalization.h b/thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/Tridiagonalization.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Eigenvalues/Tridiagonalization.h rename to thirdparty/eigen-3.2.8/Eigen/src/Eigenvalues/Tridiagonalization.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Geometry/AlignedBox.h b/thirdparty/eigen-3.2.8/Eigen/src/Geometry/AlignedBox.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Geometry/AlignedBox.h rename to thirdparty/eigen-3.2.8/Eigen/src/Geometry/AlignedBox.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Geometry/AngleAxis.h b/thirdparty/eigen-3.2.8/Eigen/src/Geometry/AngleAxis.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Geometry/AngleAxis.h rename to thirdparty/eigen-3.2.8/Eigen/src/Geometry/AngleAxis.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Geometry/EulerAngles.h b/thirdparty/eigen-3.2.8/Eigen/src/Geometry/EulerAngles.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Geometry/EulerAngles.h rename to thirdparty/eigen-3.2.8/Eigen/src/Geometry/EulerAngles.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Geometry/Homogeneous.h b/thirdparty/eigen-3.2.8/Eigen/src/Geometry/Homogeneous.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Geometry/Homogeneous.h rename to thirdparty/eigen-3.2.8/Eigen/src/Geometry/Homogeneous.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Geometry/Hyperplane.h b/thirdparty/eigen-3.2.8/Eigen/src/Geometry/Hyperplane.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Geometry/Hyperplane.h rename to thirdparty/eigen-3.2.8/Eigen/src/Geometry/Hyperplane.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Geometry/OrthoMethods.h b/thirdparty/eigen-3.2.8/Eigen/src/Geometry/OrthoMethods.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Geometry/OrthoMethods.h rename to thirdparty/eigen-3.2.8/Eigen/src/Geometry/OrthoMethods.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Geometry/ParametrizedLine.h b/thirdparty/eigen-3.2.8/Eigen/src/Geometry/ParametrizedLine.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Geometry/ParametrizedLine.h rename to thirdparty/eigen-3.2.8/Eigen/src/Geometry/ParametrizedLine.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Geometry/Quaternion.h b/thirdparty/eigen-3.2.8/Eigen/src/Geometry/Quaternion.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Geometry/Quaternion.h rename to thirdparty/eigen-3.2.8/Eigen/src/Geometry/Quaternion.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Geometry/Rotation2D.h b/thirdparty/eigen-3.2.8/Eigen/src/Geometry/Rotation2D.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Geometry/Rotation2D.h rename to thirdparty/eigen-3.2.8/Eigen/src/Geometry/Rotation2D.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Geometry/RotationBase.h b/thirdparty/eigen-3.2.8/Eigen/src/Geometry/RotationBase.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Geometry/RotationBase.h rename to thirdparty/eigen-3.2.8/Eigen/src/Geometry/RotationBase.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Geometry/Scaling.h b/thirdparty/eigen-3.2.8/Eigen/src/Geometry/Scaling.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Geometry/Scaling.h rename to thirdparty/eigen-3.2.8/Eigen/src/Geometry/Scaling.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Geometry/Transform.h b/thirdparty/eigen-3.2.8/Eigen/src/Geometry/Transform.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Geometry/Transform.h rename to thirdparty/eigen-3.2.8/Eigen/src/Geometry/Transform.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Geometry/Translation.h b/thirdparty/eigen-3.2.8/Eigen/src/Geometry/Translation.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Geometry/Translation.h rename to thirdparty/eigen-3.2.8/Eigen/src/Geometry/Translation.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Geometry/Umeyama.h b/thirdparty/eigen-3.2.8/Eigen/src/Geometry/Umeyama.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Geometry/Umeyama.h rename to thirdparty/eigen-3.2.8/Eigen/src/Geometry/Umeyama.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Geometry/arch/Geometry_SSE.h b/thirdparty/eigen-3.2.8/Eigen/src/Geometry/arch/Geometry_SSE.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Geometry/arch/Geometry_SSE.h rename to thirdparty/eigen-3.2.8/Eigen/src/Geometry/arch/Geometry_SSE.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Householder/BlockHouseholder.h b/thirdparty/eigen-3.2.8/Eigen/src/Householder/BlockHouseholder.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Householder/BlockHouseholder.h rename to thirdparty/eigen-3.2.8/Eigen/src/Householder/BlockHouseholder.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Householder/Householder.h b/thirdparty/eigen-3.2.8/Eigen/src/Householder/Householder.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Householder/Householder.h rename to thirdparty/eigen-3.2.8/Eigen/src/Householder/Householder.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Householder/HouseholderSequence.h b/thirdparty/eigen-3.2.8/Eigen/src/Householder/HouseholderSequence.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Householder/HouseholderSequence.h rename to thirdparty/eigen-3.2.8/Eigen/src/Householder/HouseholderSequence.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h b/thirdparty/eigen-3.2.8/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h rename to thirdparty/eigen-3.2.8/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h b/thirdparty/eigen-3.2.8/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h rename to thirdparty/eigen-3.2.8/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h b/thirdparty/eigen-3.2.8/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h rename to thirdparty/eigen-3.2.8/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h b/thirdparty/eigen-3.2.8/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h rename to thirdparty/eigen-3.2.8/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h b/thirdparty/eigen-3.2.8/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h rename to thirdparty/eigen-3.2.8/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/Jacobi/Jacobi.h b/thirdparty/eigen-3.2.8/Eigen/src/Jacobi/Jacobi.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/Jacobi/Jacobi.h rename to thirdparty/eigen-3.2.8/Eigen/src/Jacobi/Jacobi.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/LU/Determinant.h b/thirdparty/eigen-3.2.8/Eigen/src/LU/Determinant.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/LU/Determinant.h rename to thirdparty/eigen-3.2.8/Eigen/src/LU/Determinant.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/LU/FullPivLU.h b/thirdparty/eigen-3.2.8/Eigen/src/LU/FullPivLU.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/LU/FullPivLU.h rename to thirdparty/eigen-3.2.8/Eigen/src/LU/FullPivLU.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/LU/Inverse.h b/thirdparty/eigen-3.2.8/Eigen/src/LU/Inverse.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/LU/Inverse.h rename to thirdparty/eigen-3.2.8/Eigen/src/LU/Inverse.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/LU/PartialPivLU.h b/thirdparty/eigen-3.2.8/Eigen/src/LU/PartialPivLU.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/LU/PartialPivLU.h rename to thirdparty/eigen-3.2.8/Eigen/src/LU/PartialPivLU.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/LU/PartialPivLU_MKL.h b/thirdparty/eigen-3.2.8/Eigen/src/LU/PartialPivLU_MKL.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/LU/PartialPivLU_MKL.h rename to thirdparty/eigen-3.2.8/Eigen/src/LU/PartialPivLU_MKL.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/LU/arch/Inverse_SSE.h b/thirdparty/eigen-3.2.8/Eigen/src/LU/arch/Inverse_SSE.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/LU/arch/Inverse_SSE.h rename to thirdparty/eigen-3.2.8/Eigen/src/LU/arch/Inverse_SSE.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/MetisSupport/MetisSupport.h b/thirdparty/eigen-3.2.8/Eigen/src/MetisSupport/MetisSupport.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/MetisSupport/MetisSupport.h rename to thirdparty/eigen-3.2.8/Eigen/src/MetisSupport/MetisSupport.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/OrderingMethods/Amd.h b/thirdparty/eigen-3.2.8/Eigen/src/OrderingMethods/Amd.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/OrderingMethods/Amd.h rename to thirdparty/eigen-3.2.8/Eigen/src/OrderingMethods/Amd.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/OrderingMethods/Eigen_Colamd.h b/thirdparty/eigen-3.2.8/Eigen/src/OrderingMethods/Eigen_Colamd.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/OrderingMethods/Eigen_Colamd.h rename to thirdparty/eigen-3.2.8/Eigen/src/OrderingMethods/Eigen_Colamd.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/OrderingMethods/Ordering.h b/thirdparty/eigen-3.2.8/Eigen/src/OrderingMethods/Ordering.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/OrderingMethods/Ordering.h rename to thirdparty/eigen-3.2.8/Eigen/src/OrderingMethods/Ordering.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/PaStiXSupport/PaStiXSupport.h b/thirdparty/eigen-3.2.8/Eigen/src/PaStiXSupport/PaStiXSupport.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/PaStiXSupport/PaStiXSupport.h rename to thirdparty/eigen-3.2.8/Eigen/src/PaStiXSupport/PaStiXSupport.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/PardisoSupport/PardisoSupport.h b/thirdparty/eigen-3.2.8/Eigen/src/PardisoSupport/PardisoSupport.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/PardisoSupport/PardisoSupport.h rename to thirdparty/eigen-3.2.8/Eigen/src/PardisoSupport/PardisoSupport.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/QR/ColPivHouseholderQR.h b/thirdparty/eigen-3.2.8/Eigen/src/QR/ColPivHouseholderQR.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/QR/ColPivHouseholderQR.h rename to thirdparty/eigen-3.2.8/Eigen/src/QR/ColPivHouseholderQR.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/QR/ColPivHouseholderQR_MKL.h b/thirdparty/eigen-3.2.8/Eigen/src/QR/ColPivHouseholderQR_MKL.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/QR/ColPivHouseholderQR_MKL.h rename to thirdparty/eigen-3.2.8/Eigen/src/QR/ColPivHouseholderQR_MKL.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/QR/FullPivHouseholderQR.h b/thirdparty/eigen-3.2.8/Eigen/src/QR/FullPivHouseholderQR.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/QR/FullPivHouseholderQR.h rename to thirdparty/eigen-3.2.8/Eigen/src/QR/FullPivHouseholderQR.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/QR/HouseholderQR.h b/thirdparty/eigen-3.2.8/Eigen/src/QR/HouseholderQR.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/QR/HouseholderQR.h rename to thirdparty/eigen-3.2.8/Eigen/src/QR/HouseholderQR.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/QR/HouseholderQR_MKL.h b/thirdparty/eigen-3.2.8/Eigen/src/QR/HouseholderQR_MKL.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/QR/HouseholderQR_MKL.h rename to thirdparty/eigen-3.2.8/Eigen/src/QR/HouseholderQR_MKL.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h b/thirdparty/eigen-3.2.8/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h rename to thirdparty/eigen-3.2.8/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SVD/JacobiSVD.h b/thirdparty/eigen-3.2.8/Eigen/src/SVD/JacobiSVD.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SVD/JacobiSVD.h rename to thirdparty/eigen-3.2.8/Eigen/src/SVD/JacobiSVD.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SVD/JacobiSVD_MKL.h b/thirdparty/eigen-3.2.8/Eigen/src/SVD/JacobiSVD_MKL.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SVD/JacobiSVD_MKL.h rename to thirdparty/eigen-3.2.8/Eigen/src/SVD/JacobiSVD_MKL.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SVD/UpperBidiagonalization.h b/thirdparty/eigen-3.2.8/Eigen/src/SVD/UpperBidiagonalization.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SVD/UpperBidiagonalization.h rename to thirdparty/eigen-3.2.8/Eigen/src/SVD/UpperBidiagonalization.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCholesky/SimplicialCholesky.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseCholesky/SimplicialCholesky.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseCholesky/SimplicialCholesky.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseCholesky/SimplicialCholesky.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/AmbiVector.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseCore/AmbiVector.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseCore/AmbiVector.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseCore/AmbiVector.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/CompressedStorage.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseCore/CompressedStorage.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseCore/CompressedStorage.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseCore/CompressedStorage.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/MappedSparseMatrix.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseCore/MappedSparseMatrix.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseCore/MappedSparseMatrix.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseCore/MappedSparseMatrix.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseBlock.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseBlock.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseBlock.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseBlock.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseColEtree.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseColEtree.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseColEtree.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseColEtree.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseCwiseBinaryOp.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseCwiseBinaryOp.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseCwiseBinaryOp.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseCwiseBinaryOp.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseCwiseUnaryOp.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseCwiseUnaryOp.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseCwiseUnaryOp.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseCwiseUnaryOp.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseDenseProduct.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseDenseProduct.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseDenseProduct.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseDenseProduct.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseDiagonalProduct.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseDiagonalProduct.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseDiagonalProduct.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseDiagonalProduct.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseDot.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseDot.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseDot.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseDot.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseFuzzy.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseFuzzy.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseFuzzy.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseFuzzy.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseMatrix.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseMatrix.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseMatrix.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseMatrix.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseMatrixBase.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseMatrixBase.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseMatrixBase.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseMatrixBase.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparsePermutation.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparsePermutation.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparsePermutation.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparsePermutation.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseProduct.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseProduct.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseProduct.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseProduct.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseRedux.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseRedux.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseRedux.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseRedux.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseSelfAdjointView.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseSelfAdjointView.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseSelfAdjointView.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseSelfAdjointView.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseSparseProductWithPruning.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseSparseProductWithPruning.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseSparseProductWithPruning.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseSparseProductWithPruning.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseTranspose.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseTranspose.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseTranspose.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseTranspose.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseTriangularView.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseTriangularView.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseTriangularView.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseTriangularView.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseUtil.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseUtil.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseUtil.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseUtil.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseVector.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseVector.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseVector.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseVector.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseView.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseView.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseCore/SparseView.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseCore/SparseView.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseCore/TriangularSolver.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseCore/TriangularSolver.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseCore/TriangularSolver.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseCore/TriangularSolver.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLUImpl.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLUImpl.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLUImpl.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLUImpl.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_Memory.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_Memory.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_Memory.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_Memory.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_Structs.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_Structs.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_Structs.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_Structs.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_Utils.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_Utils.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_Utils.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_Utils.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_column_bmod.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_column_bmod.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_column_bmod.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_column_bmod.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_column_dfs.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_column_dfs.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_column_dfs.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_column_dfs.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_copy_to_ucol.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_copy_to_ucol.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_copy_to_ucol.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_copy_to_ucol.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_gemm_kernel.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_gemm_kernel.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_gemm_kernel.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_gemm_kernel.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_heap_relax_snode.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_heap_relax_snode.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_heap_relax_snode.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_heap_relax_snode.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_kernel_bmod.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_kernel_bmod.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_kernel_bmod.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_kernel_bmod.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_panel_bmod.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_panel_bmod.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_panel_bmod.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_panel_bmod.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_panel_dfs.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_panel_dfs.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_panel_dfs.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_panel_dfs.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_pivotL.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_pivotL.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_pivotL.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_pivotL.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_pruneL.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_pruneL.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_pruneL.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_pruneL.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_relax_snode.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_relax_snode.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseLU/SparseLU_relax_snode.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseLU/SparseLU_relax_snode.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SparseQR/SparseQR.h b/thirdparty/eigen-3.2.8/Eigen/src/SparseQR/SparseQR.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SparseQR/SparseQR.h rename to thirdparty/eigen-3.2.8/Eigen/src/SparseQR/SparseQR.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/StlSupport/StdDeque.h b/thirdparty/eigen-3.2.8/Eigen/src/StlSupport/StdDeque.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/StlSupport/StdDeque.h rename to thirdparty/eigen-3.2.8/Eigen/src/StlSupport/StdDeque.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/StlSupport/StdList.h b/thirdparty/eigen-3.2.8/Eigen/src/StlSupport/StdList.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/StlSupport/StdList.h rename to thirdparty/eigen-3.2.8/Eigen/src/StlSupport/StdList.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/StlSupport/StdVector.h b/thirdparty/eigen-3.2.8/Eigen/src/StlSupport/StdVector.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/StlSupport/StdVector.h rename to thirdparty/eigen-3.2.8/Eigen/src/StlSupport/StdVector.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/StlSupport/details.h b/thirdparty/eigen-3.2.8/Eigen/src/StlSupport/details.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/StlSupport/details.h rename to thirdparty/eigen-3.2.8/Eigen/src/StlSupport/details.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/SuperLUSupport/SuperLUSupport.h b/thirdparty/eigen-3.2.8/Eigen/src/SuperLUSupport/SuperLUSupport.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/SuperLUSupport/SuperLUSupport.h rename to thirdparty/eigen-3.2.8/Eigen/src/SuperLUSupport/SuperLUSupport.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/UmfPackSupport/UmfPackSupport.h b/thirdparty/eigen-3.2.8/Eigen/src/UmfPackSupport/UmfPackSupport.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/UmfPackSupport/UmfPackSupport.h rename to thirdparty/eigen-3.2.8/Eigen/src/UmfPackSupport/UmfPackSupport.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/misc/Image.h b/thirdparty/eigen-3.2.8/Eigen/src/misc/Image.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/misc/Image.h rename to thirdparty/eigen-3.2.8/Eigen/src/misc/Image.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/misc/Kernel.h b/thirdparty/eigen-3.2.8/Eigen/src/misc/Kernel.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/misc/Kernel.h rename to thirdparty/eigen-3.2.8/Eigen/src/misc/Kernel.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/misc/Solve.h b/thirdparty/eigen-3.2.8/Eigen/src/misc/Solve.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/misc/Solve.h rename to thirdparty/eigen-3.2.8/Eigen/src/misc/Solve.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/misc/SparseSolve.h b/thirdparty/eigen-3.2.8/Eigen/src/misc/SparseSolve.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/misc/SparseSolve.h rename to thirdparty/eigen-3.2.8/Eigen/src/misc/SparseSolve.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/misc/blas.h b/thirdparty/eigen-3.2.8/Eigen/src/misc/blas.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/misc/blas.h rename to thirdparty/eigen-3.2.8/Eigen/src/misc/blas.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/plugins/ArrayCwiseBinaryOps.h b/thirdparty/eigen-3.2.8/Eigen/src/plugins/ArrayCwiseBinaryOps.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/plugins/ArrayCwiseBinaryOps.h rename to thirdparty/eigen-3.2.8/Eigen/src/plugins/ArrayCwiseBinaryOps.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/plugins/ArrayCwiseUnaryOps.h b/thirdparty/eigen-3.2.8/Eigen/src/plugins/ArrayCwiseUnaryOps.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/plugins/ArrayCwiseUnaryOps.h rename to thirdparty/eigen-3.2.8/Eigen/src/plugins/ArrayCwiseUnaryOps.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/plugins/BlockMethods.h b/thirdparty/eigen-3.2.8/Eigen/src/plugins/BlockMethods.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/plugins/BlockMethods.h rename to thirdparty/eigen-3.2.8/Eigen/src/plugins/BlockMethods.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/plugins/CommonCwiseBinaryOps.h b/thirdparty/eigen-3.2.8/Eigen/src/plugins/CommonCwiseBinaryOps.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/plugins/CommonCwiseBinaryOps.h rename to thirdparty/eigen-3.2.8/Eigen/src/plugins/CommonCwiseBinaryOps.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/plugins/CommonCwiseUnaryOps.h b/thirdparty/eigen-3.2.8/Eigen/src/plugins/CommonCwiseUnaryOps.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/plugins/CommonCwiseUnaryOps.h rename to thirdparty/eigen-3.2.8/Eigen/src/plugins/CommonCwiseUnaryOps.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/plugins/MatrixCwiseBinaryOps.h b/thirdparty/eigen-3.2.8/Eigen/src/plugins/MatrixCwiseBinaryOps.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/plugins/MatrixCwiseBinaryOps.h rename to thirdparty/eigen-3.2.8/Eigen/src/plugins/MatrixCwiseBinaryOps.h diff --git a/thirdparty/eigen-3.2.7/Eigen/src/plugins/MatrixCwiseUnaryOps.h b/thirdparty/eigen-3.2.8/Eigen/src/plugins/MatrixCwiseUnaryOps.h similarity index 100% rename from thirdparty/eigen-3.2.7/Eigen/src/plugins/MatrixCwiseUnaryOps.h rename to thirdparty/eigen-3.2.8/Eigen/src/plugins/MatrixCwiseUnaryOps.h From 96e1ed0df1a427eb9dd92fb5a881135641bd7a61 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Sat, 27 Feb 2016 16:23:25 +0100 Subject: [PATCH 207/402] fixed a typo in ihcmap3 Signed-off-by: Etienne Schmitt --- cgogn/multiresolution/cph/ihcmap3.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cgogn/multiresolution/cph/ihcmap3.h b/cgogn/multiresolution/cph/ihcmap3.h index d9a438e4..e300ef3b 100644 --- a/cgogn/multiresolution/cph/ihcmap3.h +++ b/cgogn/multiresolution/cph/ihcmap3.h @@ -187,8 +187,8 @@ class IHCMap3_T :public CMap3_T, public CPH3 { cgogn_message_assert(Inherit_CPH::get_dart_level(d) <= Inherit_CPH::get_current_level(), "Access to a dart introduced after current level") ; - if(Inherit_CMAP::phi3(d) == d); - return d; + if(Inherit_CMAP::phi3(d) == d) + return d; return Inherit_CMAP::phi3(Inherit_CMAP::phi_1(phi1(d))); } From 3e2c2da1510b9fc276b0a9e20864b3ddf827c13f Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Sat, 27 Feb 2016 17:03:54 +0100 Subject: [PATCH 208/402] added swap_endianness functions for signed integers Signed-off-by: Etienne Schmitt --- cgogn/core/utils/endian.h | 74 ++++++++++++++++---- thirdparty/OffBinConverter/off_ascii2bin.cpp | 10 +-- 2 files changed, 64 insertions(+), 20 deletions(-) diff --git a/cgogn/core/utils/endian.h b/cgogn/core/utils/endian.h index 289d5e55..2cea502e 100644 --- a/cgogn/core/utils/endian.h +++ b/cgogn/core/utils/endian.h @@ -27,7 +27,7 @@ #include #include #include - +#include namespace cgogn { @@ -42,18 +42,18 @@ const bool cgogn_is_big_endian = false; const bool cgogn_is_little_endian = true; #endif -inline std::uint16_t swap_endianness16(std::uint16_t x) +inline std::uint16_t swap_endianness16u(std::uint16_t x) { return ((x >> 8) & 0x00FF) | ((x << 8) & 0xFF00); } -inline std::uint32_t swap_endianness32(std::uint32_t x) +inline std::uint32_t swap_endianness32u(std::uint32_t x) { return ((x >> 24) & 0x000000FF) | ((x >> 8) & 0x0000FF00) | ((x << 8) & 0x00FF0000) | ((x << 24) & 0xFF000000); } -inline std::uint64_t swap_endianness64(std::uint64_t x) +inline std::uint64_t swap_endianness64u(std::uint64_t x) { return ((x >> 56) & 0x00000000000000FF) | ((x >> 40) & 0x000000000000FF00) | ((x >> 24) & 0x0000000000FF0000) | ((x >> 8) & 0x00000000FF000000) | @@ -61,6 +61,38 @@ inline std::uint64_t swap_endianness64(std::uint64_t x) ((x << 40) & 0x00FF000000000000) | ((x << 56) & 0xFF00000000000000); } +inline std::int16_t swap_endianness16(std::int16_t x) +{ +// boost/endian/conversion.hpp + return (static_cast(x) << 8) | + (static_cast(x) >> 8); +} + +inline std::int32_t swap_endianness32(std::int32_t x) +{ +// boost/endian/conversion.hpp + using std::uint32_t; + + uint32_t step16; + step16 = static_cast(x) << 16 | static_cast(x) >> 16; + return ((static_cast(step16) << 8) & 0xff00ff00) | + ((static_cast(step16) >> 8) & 0x00ff00ff); +} + +inline std::int64_t swap_endianness64(std::int64_t x) +{ +// boost/endian/conversion.hpp + using std::uint64_t; + using std::int64_t; + + uint64_t step32, step16; + step32 = static_cast(x) << 32 | static_cast(x) >> 32; + step16 = (step32 & 0x0000FFFF0000FFFFULL) << 16 | + (step32 & 0xFFFF0000FFFF0000ULL) >> 16; + return static_cast( (step16 & 0x00FF00FF00FF00FFULL) << 8 | + (step16 & 0xFF00FF00FF00FF00ULL) >> 8); +} + inline float swap_endianness_float(float x) { union U32F32 @@ -69,7 +101,7 @@ inline float swap_endianness_float(float x) float as_f32; } u; u.as_f32 = x; - u.as_u32 = swap_endianness32(u.as_u32); + u.as_u32 = swap_endianness32u(u.as_u32); return u.as_f32; } @@ -81,26 +113,38 @@ inline double swap_endianness_double(double x) double as_f64; } u; u.as_f64 = x; - u.as_u64 = swap_endianness64(u.as_u64); + u.as_u64 = swap_endianness64u(u.as_u64); return u.as_f64; } template inline T swap_endianness_if(T x) { - static_assert(std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value, "This function is specialized for 16, 32 or 64 bits uints, floats and doubles."); + static_assert( std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value, "This function is specialized for 8,16, 32 or 64 bits (u))ints, floats and doubles."); if (COND) { if (std::is_same::value) - return swap_endianness16(x); + return swap_endianness16u(x); if (std::is_same::value) - return swap_endianness32(x); + return swap_endianness32u(x); if (std::is_same::value) + return swap_endianness64u(x); + if (std::is_same::value) + return swap_endianness16(x); + if (std::is_same::value) + return swap_endianness32(x); + if (std::is_same::value) return swap_endianness64(x); if (std::is_same::value) return swap_endianness_float(x); @@ -119,13 +163,13 @@ inline T swap_endianness(T x) } template -inline T swap_endianness_system_big(T x) +inline T swap_endianness_native_big(T x) { return internal::swap_endianness_if(x); } template -inline T swap_endianness_system_little(T x) +inline T swap_endianness_native_little(T x) { return internal::swap_endianness_if(x); } diff --git a/thirdparty/OffBinConverter/off_ascii2bin.cpp b/thirdparty/OffBinConverter/off_ascii2bin.cpp index b2cb3a69..0539d047 100644 --- a/thirdparty/OffBinConverter/off_ascii2bin.cpp +++ b/thirdparty/OffBinConverter/off_ascii2bin.cpp @@ -34,9 +34,9 @@ int main(int argc, char **argv) ifs >> np; ifs >> ne; - unsigned int nv_be = cgogn::swap_endianness_system_big(nv); - unsigned int np_be = cgogn::swap_endianness_system_big(np); - unsigned int ne_be = cgogn::swap_endianness_system_big(ne); + unsigned int nv_be = cgogn::swap_endianness_native_big(nv); + unsigned int np_be = cgogn::swap_endianness_native_big(np); + unsigned int ne_be = cgogn::swap_endianness_native_big(ne); ofs << "OFF BINARY"<< std::endl; @@ -54,7 +54,7 @@ int main(int argc, char **argv) unsigned int* ptr = reinterpret_cast(vertices); for (unsigned int i=0; i<3*nv;++i) { - *ptr = cgogn::swap_endianness_system_big(*ptr); + *ptr = cgogn::swap_endianness_native_big(*ptr); ptr++; } @@ -82,7 +82,7 @@ int main(int argc, char **argv) ptr = reinterpret_cast(&(prim[0])); for (unsigned int i=0; i Date: Sat, 27 Feb 2016 17:24:10 +0100 Subject: [PATCH 209/402] Added some documentation in surface_import. Signed-off-by: Etienne Schmitt --- cgogn/io/surface_import.h | 149 +++++++++++++++++++++++++------------- 1 file changed, 98 insertions(+), 51 deletions(-) diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index c4a9356c..6cd30cc1 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -49,6 +49,11 @@ namespace cgogn namespace io { +/** + * @brief vtk_data_type_to_cgogn_name_of_type : convert the type names we can find in VTK files to the one we use in cgogn. + * @param vtk_type_str a typename extracted from a vtk file + * @return a typename string that can be match with some cgogn::name_of_type + */ inline std::string vtk_data_type_to_cgogn_name_of_type(const std::string& vtk_type_str) { const std::string& data_type = to_lower(vtk_type_str); @@ -77,22 +82,29 @@ inline std::string vtk_data_type_to_cgogn_name_of_type(const std::string& vtk_ty return std::string(); } - -template +/** + * @brief read_n_scalars, read N scalars of type BUFFER_T in an ifstream (binary or ascii mode, little or big endian) + * @param fp, an ifstream + * @param n, the number of scalars to read + * @param binary, true if the scalars are encoded in binary + * @param big_endian, true if the scalars are encoded in binary and big endian + * @return n scalars of type T (converted if necessary from type BUFFER_T) if successful, nullptr otherwith + */ +template inline std::unique_ptr> read_n_scalars(std::ifstream& fp, std::size_t n, bool binary, bool big_endian) { using VecT = std::vector; - using VecU = std::vector; + using VecBufferT = std::vector; - std::cerr << "read_n_scalars called with T = " << name_of_type(T()) << " and U = " << name_of_type(U()) << std::endl; + std::cerr << "read_n_scalars called with T = " << name_of_type(T()) << " and U = " << name_of_type(BUFFER_T()) << std::endl; std::unique_ptr res = make_unique(); res->reserve(n); - std::unique_ptr buffer = make_unique(n); + std::unique_ptr buffer = make_unique(n); if (binary) { - fp.read(reinterpret_cast(std::addressof(buffer->operator[](0))), n * sizeof(U)); + fp.read(reinterpret_cast(std::addressof(buffer->operator[](0))), n * sizeof(BUFFER_T)); if (big_endian != internal::cgogn_is_little_endian) { @@ -118,7 +130,7 @@ inline std::unique_ptr> read_n_scalars(std::ifstream& fp, std::si buffer->clear(); } - if (std::is_same::value) + if (std::is_same::value) res.reset(reinterpret_cast(buffer.release())); else { @@ -129,49 +141,84 @@ inline std::unique_ptr> read_n_scalars(std::ifstream& fp, std::si return res; } +/** + * @brief read_n_scalars, read n scalars of type given by the STRING type_name in the ifstream fp, and convert them to the template type T + * @param fp, the file we want to read + * @param type_name, the type_name (CAUTION : consistent with cgogn name_of_type method) + * @param n, number of scalars to read + * @param binary, true if the scalars are encoded in binary + * @param big_endian, ignored if !binary. True if the file we read chose to encod the scalars in big endian + * @return + */ template inline std::unique_ptr> read_n_scalars(std::ifstream& fp, const std::string& type_name, std::size_t n, bool binary, bool big_endian) { using VecT = std::vector; - std::unique_ptr> res; - std::cerr << "read_n_scalars called with type " << type_name << std::endl; - const std::string& type = vtk_data_type_to_cgogn_name_of_type(type_name); - if (type == name_of_type(float())) - { - std::unique_ptr> scalars(std::move(read_n_scalars(fp,n,binary,big_endian))); - res.reset(reinterpret_cast(scalars.release())); - } - if (type == name_of_type(double())) - { - std::unique_ptr> scalars(std::move(read_n_scalars(fp,n,binary,big_endian))); - res.reset(reinterpret_cast(scalars.release())); - } - - if (type == name_of_type(std::uint32_t())) - { - std::unique_ptr> scalars(std::move(read_n_scalars(fp,n,binary,big_endian))); - res.reset(reinterpret_cast(scalars.release())); + if (type_name == name_of_type(float())) + return std::move(read_n_scalars(fp,n,binary,big_endian)); + else { + if (type_name == name_of_type(double())) + return std::move(read_n_scalars(fp,n,binary,big_endian)); + else { + if (type_name == name_of_type(char())) + return std::move(read_n_scalars(fp,n,binary,big_endian)); + else + { + if (type_name == name_of_type(std::int8_t())) + return std::move(read_n_scalars(fp,n,binary,big_endian)); + else + { + if (type_name == name_of_type(std::uint8_t())) + return std::move(read_n_scalars(fp,n,binary,big_endian)); + else + { + if (type_name == name_of_type(std::int16_t())) + return std::move(read_n_scalars(fp,n,binary,big_endian)); + else + { + if (type_name == name_of_type(std::uint32_t())) + return std::move(read_n_scalars(fp,n,binary,big_endian)); + else + { + if (type_name == name_of_type(std::int32_t())) + return std::move(read_n_scalars(fp,n,binary,big_endian)); + else + { + if (type_name == name_of_type(std::uint64_t())) + return std::move(read_n_scalars(fp,n,binary,big_endian)); + else + { + if (type_name == name_of_type(std::int64_t())) + return std::move(read_n_scalars(fp,n,binary,big_endian)); + } + } + } + } + } + } + } + } } - - return res; + return std::unique_ptr>(); } -template -inline std::unique_ptr> read_n_vec(std::ifstream& fp, const std::string& type_name, std::size_t n, bool binary, bool big_endian) -{ - using Scalar = typename geometry::vector_traits::Scalar; - const std::size_t size = geometry::vector_traits::SIZE; - std::unique_ptr> scalars(std::move(read_n_scalars(fp, type_name,n*size,binary,big_endian))); - std::unique_ptr> res = make_unique>(); - res->reserve(n); - for (auto it = scalars->begin(), end = scalars->end() ; it != end;) - { - res->emplace_back(Scalar(*it++), Scalar(*it++), Scalar(*it++)); - } +//template +//inline std::unique_ptr> read_n_vec(std::ifstream& fp, const std::string& type_name, std::size_t n, bool binary, bool big_endian) +//{ +// using Scalar = typename geometry::vector_traits::Scalar; +// const std::size_t size = geometry::vector_traits::SIZE; +// std::unique_ptr> scalars(std::move(read_n_scalars(fp, type_name,n*size,binary,big_endian))); +// std::unique_ptr> res = make_unique>(); +// res->reserve(n); +// for (auto it = scalars->begin(), end = scalars->end() ; it != end;) +// { +// res->emplace_back(Scalar(*it), Scalar(*(it+ 1)), Scalar(*(it+2))); +// it+=3; +// } - return res; -} +// return res; +//} enum SurfaceFileType @@ -504,9 +551,9 @@ class SurfaceImport char buffer1[12]; fp.read(buffer1,12); - nb_vertices_= swap_endianness_system_big(*(reinterpret_cast(buffer1))); - nb_faces_= swap_endianness_system_big(*(reinterpret_cast(buffer1+4))); - nb_edges_= swap_endianness_system_big(*(reinterpret_cast(buffer1+8))); + nb_vertices_= swap_endianness_native_big(*(reinterpret_cast(buffer1))); + nb_faces_= swap_endianness_native_big(*(reinterpret_cast(buffer1+4))); + nb_edges_= swap_endianness_native_big(*(reinterpret_cast(buffer1+8))); ChunkArray* position = vertex_attributes_.template add_attribute("position"); @@ -533,7 +580,7 @@ class SurfaceImport unsigned int* ptr = reinterpret_cast(buff_pos); for (unsigned int i=0; i< 3*BUFFER_SZ;++i) { - *ptr = swap_endianness_system_big(*ptr); + *ptr = swap_endianness_native_big(*ptr); ++ptr; } } @@ -564,7 +611,7 @@ class SurfaceImport ptr = buff_ind; for (unsigned int i=0; i< BUFFER_SZ;++i) { - *ptr = swap_endianness_system_big(*ptr); + *ptr = swap_endianness_native_big(*ptr); ++ptr; } ptr = buff_ind; @@ -583,7 +630,7 @@ class SurfaceImport ptr = buff_ind; for (unsigned int i=0; i< BUFFER_SZ;++i) { - *ptr = swap_endianness_system_big(*ptr); + *ptr = swap_endianness_native_big(*ptr); ++ptr; } ptr = buff_ind; @@ -831,11 +878,11 @@ class SurfaceImport type_str = to_lower(type_str); std::cout << nb_vertices_ << " points" << " of type " << type_str << std::endl; verticesID.reserve(nb_vertices_); - std::unique_ptr> pos(std::move(read_n_scalars(fp, type_str, 3*nb_vertices_, !ascii_file, false /*don't deal with endianness yet*/))); + std::unique_ptr> pos(std::move(read_n_scalars(fp, vtk_data_type_to_cgogn_name_of_type(type_str), 3*nb_vertices_, !ascii_file, false /*don't deal with endianness yet*/))); cgogn_assert(pos); for (std::size_t i = 0ul ; i < 3ul*nb_vertices_ ; i+=3ul) { - VEC3 P(Scalar((*pos)[i]), Scalar((*pos)[i+1ul]), Scalar((*pos)[i+2ul])); + VEC3 P(Scalar(pos->operator[](i)), Scalar((*pos)[i+1ul]), Scalar((*pos)[i+2ul])); std::cout << P[0] << " " << P[1] << " " << P[2] << std::endl; unsigned int id = vertex_attributes_.template insert_lines<1>(); position->operator [](id) = P; @@ -849,7 +896,7 @@ class SurfaceImport unsigned int size; sstream >> this->nb_faces_ >> size; std::cerr << "nb cells " << nb_faces_ << " and size " << size << std::endl; - cells = std::move(read_n_scalars(fp, "unsigned_int", size, !ascii_file, false)); + cells = std::move(read_n_scalars(fp, name_of_type(std::uint32_t()), size, !ascii_file, false)); std::size_t i = 0ul; } @@ -859,7 +906,7 @@ class SurfaceImport unsigned int nbc; sstream >> nbc; std::cerr << "nb cells " << nbc << std::endl; - cell_types = std::move(read_n_scalars(fp, "unsigned_int", nbc, !ascii_file, false)); + cell_types = std::move(read_n_scalars(fp, name_of_type(std::uint32_t()), nbc, !ascii_file, false)); } } } From 033d691301a8d56696e39bf2e18ed526a20fc878 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Sun, 28 Feb 2016 17:47:35 +0100 Subject: [PATCH 210/402] less warning VS --- cgogn/core/basic/cell.h | 6 +++++- cgogn/core/cmap/map_base.h | 2 +- cgogn/core/{basic => }/dll.h | 0 cgogn/core/examples/chunk_array/chunk_array.cpp | 2 +- cgogn/core/utils/assert.cpp | 8 ++++---- cgogn/core/utils/assert.h | 6 +++--- cgogn/core/utils/endian.h | 6 +++--- cgogn/core/utils/name_types.cpp | 4 ++-- cgogn/core/utils/name_types.h | 4 ++-- cgogn/core/utils/serialization.cpp | 10 +++++----- cgogn/core/utils/serialization.h | 10 +++++----- cgogn/core/utils/string.h | 4 ++-- cgogn/core/utils/thread.cpp | 14 +++++++------- cgogn/core/utils/thread.h | 14 +++++++------- cgogn/core/utils/thread_pool.cpp | 2 +- cgogn/core/utils/thread_pool.h | 8 ++++++-- cgogn/geometry/algos/ear_triangulation.h | 2 ++ cgogn/geometry/types/bounding_box.cpp | 4 ++-- cgogn/geometry/types/bounding_box.h | 6 +++++- cgogn/io/examples/cmap3_import.cpp | 2 +- cgogn/io/surface_import.h | 6 +++--- 21 files changed, 67 insertions(+), 53 deletions(-) rename cgogn/core/{basic => }/dll.h (100%) diff --git a/cgogn/core/basic/cell.h b/cgogn/core/basic/cell.h index 8c2883df..3a22b81f 100644 --- a/cgogn/core/basic/cell.h +++ b/cgogn/core/basic/cell.h @@ -66,8 +66,12 @@ inline std::string orbit_name(Orbit orbit) case Orbit::PHI2_PHI3: return "cgogn::Orbit::PHI2_PHI3"; break; case Orbit::PHI21: return "cgogn::Orbit::PHI21"; break; case Orbit::PHI21_PHI31: return "cgogn::Orbit::PHI21_PHI31"; break; - default: cgogn_assert_not_reached("This orbit does not exist"); return "UNKNOWN"; break; +// default: cgogn_assert_not_reached("This orbit does not exist"); return "UNKNOWN"; break; } + cgogn_assert_not_reached("This orbit does not exist"); +#ifdef NDEBUG + return "UNKNOWN"; // little trick to avoid waning on VS +#endif } /** diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index e41f922a..9c13923e 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -998,7 +998,7 @@ class MapBase : public MapBaseData // do block of PARALLEL_BUFFER_SIZE only if nb cells is huge else just divide if ((end - it) < 16 * nb_threads_pool * PARALLEL_BUFFER_SIZE) - nbc = (end - it) / nb_threads_pool; + nbc = static_cast((end - it) / nb_threads_pool); unsigned int local_end = it+nbc; diff --git a/cgogn/core/basic/dll.h b/cgogn/core/dll.h similarity index 100% rename from cgogn/core/basic/dll.h rename to cgogn/core/dll.h diff --git a/cgogn/core/examples/chunk_array/chunk_array.cpp b/cgogn/core/examples/chunk_array/chunk_array.cpp index 16250e6d..81d67d0a 100644 --- a/cgogn/core/examples/chunk_array/chunk_array.cpp +++ b/cgogn/core/examples/chunk_array/chunk_array.cpp @@ -225,7 +225,7 @@ int test4() { (*att1)[i] = 1+int(i); (*att2)[i] = 3.0f + 0.1f*float(i); - (*att3).set_value(i, static_cast(i%2)); + (*att3).set_value(i, static_cast(i%2 != 0)); (*att4)[i] = {{3.0 + 0.1*double(i),15.0 + 0.1*double(i)}, {103.0 + 0.1*double(i), 203.0 + 0.1*double(i), 303.0 + 0.1*double(i)}}; (*att5)[i] = {{3.0 + 0.1*double(i),15.0 + 0.1*double(i)}, {103.0 + 0.1*double(i), 203.0 + 0.1*double(i), 303.0 + 0.1*double(i)}}; } diff --git a/cgogn/core/utils/assert.cpp b/cgogn/core/utils/assert.cpp index 6b6c2046..27469957 100644 --- a/cgogn/core/utils/assert.cpp +++ b/cgogn/core/utils/assert.cpp @@ -21,9 +21,9 @@ * * *******************************************************************************/ -#define CGOGN_UTILS_DLL_EXPORT +#define CGOGN_CORE_DLL_EXPORT -#include +#include #include #include #include @@ -32,7 +32,7 @@ namespace cgogn { -CGOGN_UTILS_API CGOGN_NORETURN void assertion_failed( +CGOGN_CORE_API CGOGN_NORETURN void assertion_failed( const std::string& expression, const std::string& message, const std::string& file_name, @@ -52,7 +52,7 @@ CGOGN_UTILS_API CGOGN_NORETURN void assertion_failed( std::abort(); } -CGOGN_UTILS_API CGOGN_NORETURN void should_not_have_reached( +CGOGN_CORE_API CGOGN_NORETURN void should_not_have_reached( const std::string& message, const std::string& file_name, const std::string& function_name, diff --git a/cgogn/core/utils/assert.h b/cgogn/core/utils/assert.h index 2e61394d..a6b60818 100644 --- a/cgogn/core/utils/assert.h +++ b/cgogn/core/utils/assert.h @@ -27,7 +27,7 @@ #include #include -#include +#include #include #if defined (WIN32) && !defined(__func__) @@ -53,7 +53,7 @@ namespace cgogn * \param[in] function_name function where the assertion failed. * \param[in] line_number line where the assertion failed. */ -CGOGN_UTILS_API CGOGN_NORETURN void assertion_failed( +CGOGN_CORE_API CGOGN_NORETURN void assertion_failed( const std::string& expression, const std::string& message, const std::string& file_name, @@ -71,7 +71,7 @@ CGOGN_UTILS_API CGOGN_NORETURN void assertion_failed( * \param[in] function_name function where the assertion failed. * \param[in] line_number line where the assertion failed. */ -CGOGN_UTILS_API CGOGN_NORETURN void should_not_have_reached( +CGOGN_CORE_API CGOGN_NORETURN void should_not_have_reached( const std::string& message, const std::string& file_name, const std::string& function_name, diff --git a/cgogn/core/utils/endian.h b/cgogn/core/utils/endian.h index b4380bb8..8cb8cbfa 100644 --- a/cgogn/core/utils/endian.h +++ b/cgogn/core/utils/endian.h @@ -71,11 +71,11 @@ inline UINT swap_endianness_if(UINT x) if (COND) { if (std::is_same::value) - return swap_endianness16(x); + return UINT(swap_endianness16(std::uint16_t(x))); if (std::is_same::value) - return swap_endianness32(x); + return UINT(swap_endianness32(std::uint32_t(x))); if (std::is_same::value) - return swap_endianness64(x); + return UINT(swap_endianness64(std::uint64_t(x))); } return x; } diff --git a/cgogn/core/utils/name_types.cpp b/cgogn/core/utils/name_types.cpp index c9382419..c2e6b8ce 100644 --- a/cgogn/core/utils/name_types.cpp +++ b/cgogn/core/utils/name_types.cpp @@ -21,7 +21,7 @@ * * *******************************************************************************/ -#define CGOGN_UTILS_DLL_EXPORT +#define CGOGN_CORE_DLL_EXPORT #include @@ -42,7 +42,7 @@ namespace internal * @param str, a type name * @return the demangled type name is succeded, otherwise a copy of str */ -CGOGN_UTILS_API std::string demangle(const std::string& str) +CGOGN_CORE_API std::string demangle(const std::string& str) { #ifndef __GNUG__ return str; diff --git a/cgogn/core/utils/name_types.h b/cgogn/core/utils/name_types.h index 08b8b5f5..37e6f7d8 100644 --- a/cgogn/core/utils/name_types.h +++ b/cgogn/core/utils/name_types.h @@ -41,7 +41,7 @@ #include #endif // __GNUG__ -#include +#include #include namespace cgogn @@ -93,7 +93,7 @@ inline std::string name_of_type_impl(const std::basic_string&); template inline std::string name_of_type_impl(const std::array&); -CGOGN_UTILS_API std::string demangle(const std::string& str); +CGOGN_CORE_API std::string demangle(const std::string& str); // definitions diff --git a/cgogn/core/utils/serialization.cpp b/cgogn/core/utils/serialization.cpp index c65a8406..5a17b8fb 100644 --- a/cgogn/core/utils/serialization.cpp +++ b/cgogn/core/utils/serialization.cpp @@ -21,7 +21,7 @@ * * *******************************************************************************/ -#define CGOGN_UTILS_DLL_EXPORT +#define CGOGN_CORE_DLL_EXPORT #include namespace cgogn @@ -31,14 +31,14 @@ namespace serialization { template <> -CGOGN_UTILS_API bool known_size(std::string const* /*src*/) +CGOGN_CORE_API bool known_size(std::string const* /*src*/) { return false; } // load string template <> -CGOGN_UTILS_API void load(std::istream& istream, std::string* dest, std::size_t quantity) +CGOGN_CORE_API void load(std::istream& istream, std::string* dest, std::size_t quantity) { cgogn_assert(istream.good()); cgogn_assert(dest != nullptr); @@ -58,7 +58,7 @@ CGOGN_UTILS_API void load(std::istream& istream, std::string* dest, //save string template <> -CGOGN_UTILS_API void save(std::ostream& ostream, std::string const* src, std::size_t quantity) +CGOGN_CORE_API void save(std::ostream& ostream, std::string const* src, std::size_t quantity) { cgogn_assert(ostream.good()); cgogn_assert(src != nullptr); @@ -74,7 +74,7 @@ CGOGN_UTILS_API void save(std::ostream& ostream, std::string const* // compute data length of string template <> -CGOGN_UTILS_API std::size_t data_length(std::string const* src, std::size_t quantity) +CGOGN_CORE_API std::size_t data_length(std::string const* src, std::size_t quantity) { cgogn_assert(src != nullptr); diff --git a/cgogn/core/utils/serialization.h b/cgogn/core/utils/serialization.h index 27b8a6e0..372dcb02 100644 --- a/cgogn/core/utils/serialization.h +++ b/cgogn/core/utils/serialization.h @@ -30,7 +30,7 @@ #include #include -#include +#include namespace cgogn { @@ -66,7 +66,7 @@ bool known_size(T const* /*src*/) } template <> -CGOGN_UTILS_API bool known_size(std::string const* /*src*/); +CGOGN_CORE_API bool known_size(std::string const* /*src*/); template bool known_size(std::vector const* /*src*/) @@ -118,13 +118,13 @@ std::size_t data_length(std::arrayconst* src, std::size_t quantity); template <> -CGOGN_UTILS_API void load(std::istream& istream, std::string* dest, std::size_t quantity); +CGOGN_CORE_API void load(std::istream& istream, std::string* dest, std::size_t quantity); template <> -CGOGN_UTILS_API void save(std::ostream& ostream, std::string const* src, std::size_t quantity); +CGOGN_CORE_API void save(std::ostream& ostream, std::string const* src, std::size_t quantity); template <> -CGOGN_UTILS_API std::size_t data_length(std::string const* src, std::size_t quantity); +CGOGN_CORE_API std::size_t data_length(std::string const* src, std::size_t quantity); // loading n vectors diff --git a/cgogn/core/utils/string.h b/cgogn/core/utils/string.h index 8233a046..b3c9126e 100644 --- a/cgogn/core/utils/string.h +++ b/cgogn/core/utils/string.h @@ -36,7 +36,7 @@ inline std::basic_string to_upper(const std::basic_string& str) { std::basic_string res(str); for (auto& c : res) - c = std::toupper(c); + c = Char_T(std::toupper(c)); return res; } @@ -45,7 +45,7 @@ inline std::basic_string to_lower(const std::basic_string& str) { std::basic_string res(str); for (auto& c : res) - c = std::tolower(c); + c = Char_T(std::tolower(c)); return res; } diff --git a/cgogn/core/utils/thread.cpp b/cgogn/core/utils/thread.cpp index b234f9fe..ba02f15c 100644 --- a/cgogn/core/utils/thread.cpp +++ b/cgogn/core/utils/thread.cpp @@ -21,7 +21,7 @@ * * *******************************************************************************/ -#define CGOGN_UTILS_DLL_EXPORT +#define CGOGN_CORE_DLL_EXPORT #include #include @@ -30,12 +30,12 @@ namespace cgogn { -CGOGN_UTILS_API unsigned int NB_THREADS = get_nb_threads(); +CGOGN_CORE_API unsigned int NB_THREADS = get_nb_threads(); CGOGN_TLS Buffers* dart_buffers_thread = nullptr; CGOGN_TLS Buffers* uint_buffers_thread = nullptr; -CGOGN_UTILS_API void thread_start() +CGOGN_CORE_API void thread_start() { if (dart_buffers_thread == nullptr) dart_buffers_thread = new Buffers(); @@ -44,7 +44,7 @@ CGOGN_UTILS_API void thread_start() uint_buffers_thread = new Buffers(); } -CGOGN_UTILS_API void thread_stop() +CGOGN_CORE_API void thread_stop() { delete dart_buffers_thread; delete uint_buffers_thread; @@ -52,17 +52,17 @@ CGOGN_UTILS_API void thread_stop() uint_buffers_thread = nullptr; } -CGOGN_UTILS_API Buffers* get_dart_buffers() +CGOGN_CORE_API Buffers* get_dart_buffers() { return dart_buffers_thread; } -CGOGN_UTILS_API Buffers* get_uint_buffers() +CGOGN_CORE_API Buffers* get_uint_buffers() { return uint_buffers_thread; } -CGOGN_UTILS_API ThreadPool* get_thread_pool() +CGOGN_CORE_API ThreadPool* get_thread_pool() { // thread safe accoring to http://stackoverflow.com/questions/8102125/is-local-static-variable-initialization-thread-safe-in-c11 static ThreadPool pool; diff --git a/cgogn/core/utils/thread.h b/cgogn/core/utils/thread.h index f52e394c..8a3b329c 100644 --- a/cgogn/core/utils/thread.h +++ b/cgogn/core/utils/thread.h @@ -26,7 +26,7 @@ #include -#include +#include #include #include @@ -46,9 +46,9 @@ class Buffers; * \brief The maximum nunmber of threads created by the API. */ const unsigned int MAX_NB_THREADS = 8u; -CGOGN_UTILS_API extern unsigned int NB_THREADS; +CGOGN_CORE_API extern unsigned int NB_THREADS; -CGOGN_UTILS_API ThreadPool* get_thread_pool(); +CGOGN_CORE_API ThreadPool* get_thread_pool(); inline unsigned int get_nb_threads() { @@ -65,15 +65,15 @@ extern CGOGN_TLS Buffers* uint_buffers_thread; /** * @brief function to call at begin of each thread which use a map */ -CGOGN_UTILS_API void thread_start(); +CGOGN_CORE_API void thread_start(); /** * @brief function to call at end of each thread which use a map */ -CGOGN_UTILS_API void thread_stop(); +CGOGN_CORE_API void thread_stop(); -CGOGN_UTILS_API Buffers* get_dart_buffers(); -CGOGN_UTILS_API Buffers* get_uint_buffers(); +CGOGN_CORE_API Buffers* get_dart_buffers(); +CGOGN_CORE_API Buffers* get_uint_buffers(); template class ThreadFunction diff --git a/cgogn/core/utils/thread_pool.cpp b/cgogn/core/utils/thread_pool.cpp index b806e0f6..53663c3b 100644 --- a/cgogn/core/utils/thread_pool.cpp +++ b/cgogn/core/utils/thread_pool.cpp @@ -21,7 +21,7 @@ * * *******************************************************************************/ -#define CGOGN_UTILS_DLL_EXPORT +#define CGOGN_CORE_DLL_EXPORT #include diff --git a/cgogn/core/utils/thread_pool.h b/cgogn/core/utils/thread_pool.h index caa81728..867bdd3f 100644 --- a/cgogn/core/utils/thread_pool.h +++ b/cgogn/core/utils/thread_pool.h @@ -71,7 +71,7 @@ namespace cgogn { -class CGOGN_UTILS_API ThreadPool { +class CGOGN_CORE_API ThreadPool { public: ThreadPool(); ThreadPool(const ThreadPool&) = delete; @@ -121,8 +121,12 @@ auto ThreadPool::enqueue(const F& f, Args&&... args) { std::unique_lock lock(queue_mutex_); // don't allow enqueueing after stopping the pool - if(stop_) + if (stop_) + { cgogn_assert_not_reached("enqueue on stopped ThreadPool"); +// std::cerr << "enqueue on stopped ThreadPool" << std::endl; +// exit(1); + } // Push work back on the queue tasks_.emplace([task](unsigned int i){ (*task)(i); }); } diff --git a/cgogn/geometry/algos/ear_triangulation.h b/cgogn/geometry/algos/ear_triangulation.h index 15aafab2..75afb671 100644 --- a/cgogn/geometry/algos/ear_triangulation.h +++ b/cgogn/geometry/algos/ear_triangulation.h @@ -380,6 +380,8 @@ class EarTriangulation } } } + + EarTriangulation& operator=(const EarTriangulation&) = delete; }; /** diff --git a/cgogn/geometry/types/bounding_box.cpp b/cgogn/geometry/types/bounding_box.cpp index 3317ec7b..e7392540 100644 --- a/cgogn/geometry/types/bounding_box.cpp +++ b/cgogn/geometry/types/bounding_box.cpp @@ -32,8 +32,8 @@ namespace cgogn namespace geometry { -//template class CGOGN_GEOMETRY_API BoundingBox; -//template class CGOGN_GEOMETRY_API BoundingBox; +template class CGOGN_GEOMETRY_API BoundingBox; +template class CGOGN_GEOMETRY_API BoundingBox; template class CGOGN_GEOMETRY_API BoundingBox>>; template class CGOGN_GEOMETRY_API BoundingBox>>; diff --git a/cgogn/geometry/types/bounding_box.h b/cgogn/geometry/types/bounding_box.h index 6793d21d..31b690f3 100644 --- a/cgogn/geometry/types/bounding_box.h +++ b/cgogn/geometry/types/bounding_box.h @@ -151,7 +151,11 @@ class BoundingBox return center; } - bool is_initialized() const; + bool is_initialized() const + { + return initialized_; + + } // reinitialize the bounding box void reset() diff --git a/cgogn/io/examples/cmap3_import.cpp b/cgogn/io/examples/cmap3_import.cpp index 8c353d3d..2509f1fd 100644 --- a/cgogn/io/examples/cmap3_import.cpp +++ b/cgogn/io/examples/cmap3_import.cpp @@ -68,7 +68,7 @@ int main(int argc, char** argv) { ++nbv; unsigned int nb_incident = 0; - map.foreach_incident_face(v, [&] (Map3::Face f) + map.foreach_incident_face(v, [&] (Map3::Face /*f*/) { ++nb_incident; }); diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index 9f649497..ebd505dc 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -86,7 +86,7 @@ class SurfaceImport unsigned int nb_edges_; unsigned int nb_faces_; - std::vector faces_nb_edges_; + std::vector faces_nb_edges_; std::vector faces_vertex_indices_; ChunkArrayContainer vertex_attributes_; @@ -183,7 +183,7 @@ class SurfaceImport for (unsigned int i = 0; i < this->nb_faces_; ++i) { - unsigned short nbe = this->faces_nb_edges_[i]; + unsigned int nbe = this->faces_nb_edges_[i]; vertices_buffer.clear(); unsigned int prev = std::numeric_limits::max(); @@ -580,7 +580,7 @@ class SurfaceImport } ChunkArray* position = vertex_attributes_.template add_attribute("position"); - ChunkArray* color; + ChunkArray* color = nullptr; if (pid.has_colors()) { color = vertex_attributes_.template add_attribute("color"); From e52113299825559fe11538566c6e367fc44a95fa Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Sun, 28 Feb 2016 17:50:20 +0100 Subject: [PATCH 211/402] remove linking warning VS --- cgogn/core/basic/cell.h | 4 +++- cgogn/core/utils/assert.cpp | 8 ++++---- cgogn/core/utils/assert.h | 6 +++--- cgogn/core/utils/endian.h | 6 +++--- cgogn/core/utils/name_types.cpp | 4 ++-- cgogn/core/utils/name_types.h | 4 ++-- cgogn/core/utils/serialization.cpp | 10 +++++----- cgogn/core/utils/serialization.h | 10 +++++----- cgogn/core/utils/thread.cpp | 14 +++++++------- cgogn/core/utils/thread.h | 14 +++++++------- cgogn/core/utils/thread_pool.cpp | 2 +- cgogn/core/utils/thread_pool.h | 2 +- 12 files changed, 43 insertions(+), 41 deletions(-) diff --git a/cgogn/core/basic/cell.h b/cgogn/core/basic/cell.h index 8c2883df..1e17cb9c 100644 --- a/cgogn/core/basic/cell.h +++ b/cgogn/core/basic/cell.h @@ -66,8 +66,10 @@ inline std::string orbit_name(Orbit orbit) case Orbit::PHI2_PHI3: return "cgogn::Orbit::PHI2_PHI3"; break; case Orbit::PHI21: return "cgogn::Orbit::PHI21"; break; case Orbit::PHI21_PHI31: return "cgogn::Orbit::PHI21_PHI31"; break; - default: cgogn_assert_not_reached("This orbit does not exist"); return "UNKNOWN"; break; +// default: cgogn_assert_not_reached("This orbit does not exist"); return "UNKNOWN"; break; } + cgogn_assert_not_reached("This orbit does not exist"); +// return "UNKNOWN"; } /** diff --git a/cgogn/core/utils/assert.cpp b/cgogn/core/utils/assert.cpp index 6b6c2046..27469957 100644 --- a/cgogn/core/utils/assert.cpp +++ b/cgogn/core/utils/assert.cpp @@ -21,9 +21,9 @@ * * *******************************************************************************/ -#define CGOGN_UTILS_DLL_EXPORT +#define CGOGN_CORE_DLL_EXPORT -#include +#include #include #include #include @@ -32,7 +32,7 @@ namespace cgogn { -CGOGN_UTILS_API CGOGN_NORETURN void assertion_failed( +CGOGN_CORE_API CGOGN_NORETURN void assertion_failed( const std::string& expression, const std::string& message, const std::string& file_name, @@ -52,7 +52,7 @@ CGOGN_UTILS_API CGOGN_NORETURN void assertion_failed( std::abort(); } -CGOGN_UTILS_API CGOGN_NORETURN void should_not_have_reached( +CGOGN_CORE_API CGOGN_NORETURN void should_not_have_reached( const std::string& message, const std::string& file_name, const std::string& function_name, diff --git a/cgogn/core/utils/assert.h b/cgogn/core/utils/assert.h index 2e61394d..a6b60818 100644 --- a/cgogn/core/utils/assert.h +++ b/cgogn/core/utils/assert.h @@ -27,7 +27,7 @@ #include #include -#include +#include #include #if defined (WIN32) && !defined(__func__) @@ -53,7 +53,7 @@ namespace cgogn * \param[in] function_name function where the assertion failed. * \param[in] line_number line where the assertion failed. */ -CGOGN_UTILS_API CGOGN_NORETURN void assertion_failed( +CGOGN_CORE_API CGOGN_NORETURN void assertion_failed( const std::string& expression, const std::string& message, const std::string& file_name, @@ -71,7 +71,7 @@ CGOGN_UTILS_API CGOGN_NORETURN void assertion_failed( * \param[in] function_name function where the assertion failed. * \param[in] line_number line where the assertion failed. */ -CGOGN_UTILS_API CGOGN_NORETURN void should_not_have_reached( +CGOGN_CORE_API CGOGN_NORETURN void should_not_have_reached( const std::string& message, const std::string& file_name, const std::string& function_name, diff --git a/cgogn/core/utils/endian.h b/cgogn/core/utils/endian.h index b4380bb8..8cb8cbfa 100644 --- a/cgogn/core/utils/endian.h +++ b/cgogn/core/utils/endian.h @@ -71,11 +71,11 @@ inline UINT swap_endianness_if(UINT x) if (COND) { if (std::is_same::value) - return swap_endianness16(x); + return UINT(swap_endianness16(std::uint16_t(x))); if (std::is_same::value) - return swap_endianness32(x); + return UINT(swap_endianness32(std::uint32_t(x))); if (std::is_same::value) - return swap_endianness64(x); + return UINT(swap_endianness64(std::uint64_t(x))); } return x; } diff --git a/cgogn/core/utils/name_types.cpp b/cgogn/core/utils/name_types.cpp index c9382419..c2e6b8ce 100644 --- a/cgogn/core/utils/name_types.cpp +++ b/cgogn/core/utils/name_types.cpp @@ -21,7 +21,7 @@ * * *******************************************************************************/ -#define CGOGN_UTILS_DLL_EXPORT +#define CGOGN_CORE_DLL_EXPORT #include @@ -42,7 +42,7 @@ namespace internal * @param str, a type name * @return the demangled type name is succeded, otherwise a copy of str */ -CGOGN_UTILS_API std::string demangle(const std::string& str) +CGOGN_CORE_API std::string demangle(const std::string& str) { #ifndef __GNUG__ return str; diff --git a/cgogn/core/utils/name_types.h b/cgogn/core/utils/name_types.h index 08b8b5f5..37e6f7d8 100644 --- a/cgogn/core/utils/name_types.h +++ b/cgogn/core/utils/name_types.h @@ -41,7 +41,7 @@ #include #endif // __GNUG__ -#include +#include #include namespace cgogn @@ -93,7 +93,7 @@ inline std::string name_of_type_impl(const std::basic_string&); template inline std::string name_of_type_impl(const std::array&); -CGOGN_UTILS_API std::string demangle(const std::string& str); +CGOGN_CORE_API std::string demangle(const std::string& str); // definitions diff --git a/cgogn/core/utils/serialization.cpp b/cgogn/core/utils/serialization.cpp index c65a8406..5a17b8fb 100644 --- a/cgogn/core/utils/serialization.cpp +++ b/cgogn/core/utils/serialization.cpp @@ -21,7 +21,7 @@ * * *******************************************************************************/ -#define CGOGN_UTILS_DLL_EXPORT +#define CGOGN_CORE_DLL_EXPORT #include namespace cgogn @@ -31,14 +31,14 @@ namespace serialization { template <> -CGOGN_UTILS_API bool known_size(std::string const* /*src*/) +CGOGN_CORE_API bool known_size(std::string const* /*src*/) { return false; } // load string template <> -CGOGN_UTILS_API void load(std::istream& istream, std::string* dest, std::size_t quantity) +CGOGN_CORE_API void load(std::istream& istream, std::string* dest, std::size_t quantity) { cgogn_assert(istream.good()); cgogn_assert(dest != nullptr); @@ -58,7 +58,7 @@ CGOGN_UTILS_API void load(std::istream& istream, std::string* dest, //save string template <> -CGOGN_UTILS_API void save(std::ostream& ostream, std::string const* src, std::size_t quantity) +CGOGN_CORE_API void save(std::ostream& ostream, std::string const* src, std::size_t quantity) { cgogn_assert(ostream.good()); cgogn_assert(src != nullptr); @@ -74,7 +74,7 @@ CGOGN_UTILS_API void save(std::ostream& ostream, std::string const* // compute data length of string template <> -CGOGN_UTILS_API std::size_t data_length(std::string const* src, std::size_t quantity) +CGOGN_CORE_API std::size_t data_length(std::string const* src, std::size_t quantity) { cgogn_assert(src != nullptr); diff --git a/cgogn/core/utils/serialization.h b/cgogn/core/utils/serialization.h index 27b8a6e0..372dcb02 100644 --- a/cgogn/core/utils/serialization.h +++ b/cgogn/core/utils/serialization.h @@ -30,7 +30,7 @@ #include #include -#include +#include namespace cgogn { @@ -66,7 +66,7 @@ bool known_size(T const* /*src*/) } template <> -CGOGN_UTILS_API bool known_size(std::string const* /*src*/); +CGOGN_CORE_API bool known_size(std::string const* /*src*/); template bool known_size(std::vector const* /*src*/) @@ -118,13 +118,13 @@ std::size_t data_length(std::arrayconst* src, std::size_t quantity); template <> -CGOGN_UTILS_API void load(std::istream& istream, std::string* dest, std::size_t quantity); +CGOGN_CORE_API void load(std::istream& istream, std::string* dest, std::size_t quantity); template <> -CGOGN_UTILS_API void save(std::ostream& ostream, std::string const* src, std::size_t quantity); +CGOGN_CORE_API void save(std::ostream& ostream, std::string const* src, std::size_t quantity); template <> -CGOGN_UTILS_API std::size_t data_length(std::string const* src, std::size_t quantity); +CGOGN_CORE_API std::size_t data_length(std::string const* src, std::size_t quantity); // loading n vectors diff --git a/cgogn/core/utils/thread.cpp b/cgogn/core/utils/thread.cpp index b234f9fe..ba02f15c 100644 --- a/cgogn/core/utils/thread.cpp +++ b/cgogn/core/utils/thread.cpp @@ -21,7 +21,7 @@ * * *******************************************************************************/ -#define CGOGN_UTILS_DLL_EXPORT +#define CGOGN_CORE_DLL_EXPORT #include #include @@ -30,12 +30,12 @@ namespace cgogn { -CGOGN_UTILS_API unsigned int NB_THREADS = get_nb_threads(); +CGOGN_CORE_API unsigned int NB_THREADS = get_nb_threads(); CGOGN_TLS Buffers* dart_buffers_thread = nullptr; CGOGN_TLS Buffers* uint_buffers_thread = nullptr; -CGOGN_UTILS_API void thread_start() +CGOGN_CORE_API void thread_start() { if (dart_buffers_thread == nullptr) dart_buffers_thread = new Buffers(); @@ -44,7 +44,7 @@ CGOGN_UTILS_API void thread_start() uint_buffers_thread = new Buffers(); } -CGOGN_UTILS_API void thread_stop() +CGOGN_CORE_API void thread_stop() { delete dart_buffers_thread; delete uint_buffers_thread; @@ -52,17 +52,17 @@ CGOGN_UTILS_API void thread_stop() uint_buffers_thread = nullptr; } -CGOGN_UTILS_API Buffers* get_dart_buffers() +CGOGN_CORE_API Buffers* get_dart_buffers() { return dart_buffers_thread; } -CGOGN_UTILS_API Buffers* get_uint_buffers() +CGOGN_CORE_API Buffers* get_uint_buffers() { return uint_buffers_thread; } -CGOGN_UTILS_API ThreadPool* get_thread_pool() +CGOGN_CORE_API ThreadPool* get_thread_pool() { // thread safe accoring to http://stackoverflow.com/questions/8102125/is-local-static-variable-initialization-thread-safe-in-c11 static ThreadPool pool; diff --git a/cgogn/core/utils/thread.h b/cgogn/core/utils/thread.h index f52e394c..8a3b329c 100644 --- a/cgogn/core/utils/thread.h +++ b/cgogn/core/utils/thread.h @@ -26,7 +26,7 @@ #include -#include +#include #include #include @@ -46,9 +46,9 @@ class Buffers; * \brief The maximum nunmber of threads created by the API. */ const unsigned int MAX_NB_THREADS = 8u; -CGOGN_UTILS_API extern unsigned int NB_THREADS; +CGOGN_CORE_API extern unsigned int NB_THREADS; -CGOGN_UTILS_API ThreadPool* get_thread_pool(); +CGOGN_CORE_API ThreadPool* get_thread_pool(); inline unsigned int get_nb_threads() { @@ -65,15 +65,15 @@ extern CGOGN_TLS Buffers* uint_buffers_thread; /** * @brief function to call at begin of each thread which use a map */ -CGOGN_UTILS_API void thread_start(); +CGOGN_CORE_API void thread_start(); /** * @brief function to call at end of each thread which use a map */ -CGOGN_UTILS_API void thread_stop(); +CGOGN_CORE_API void thread_stop(); -CGOGN_UTILS_API Buffers* get_dart_buffers(); -CGOGN_UTILS_API Buffers* get_uint_buffers(); +CGOGN_CORE_API Buffers* get_dart_buffers(); +CGOGN_CORE_API Buffers* get_uint_buffers(); template class ThreadFunction diff --git a/cgogn/core/utils/thread_pool.cpp b/cgogn/core/utils/thread_pool.cpp index b806e0f6..53663c3b 100644 --- a/cgogn/core/utils/thread_pool.cpp +++ b/cgogn/core/utils/thread_pool.cpp @@ -21,7 +21,7 @@ * * *******************************************************************************/ -#define CGOGN_UTILS_DLL_EXPORT +#define CGOGN_CORE_DLL_EXPORT #include diff --git a/cgogn/core/utils/thread_pool.h b/cgogn/core/utils/thread_pool.h index caa81728..1cb36ffa 100644 --- a/cgogn/core/utils/thread_pool.h +++ b/cgogn/core/utils/thread_pool.h @@ -71,7 +71,7 @@ namespace cgogn { -class CGOGN_UTILS_API ThreadPool { +class CGOGN_CORE_API ThreadPool { public: ThreadPool(); ThreadPool(const ThreadPool&) = delete; From 791e355e3d4ac4cf56cff6a881f06c9e95da3520 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Sun, 28 Feb 2016 17:59:41 +0100 Subject: [PATCH 212/402] less warning QGLViewer VS --- .../libQGLViewer/QOGLViewer/CMakeLists.txt | 2 +- .../libQGLViewer/QOGLViewer/constraint.h | 2 ++ .../QOGLViewer/keyFrameInterpolator.h | 1 + .../libQGLViewer/QOGLViewer/qoglviewer.cpp | 22 +++++-------------- .../libQGLViewer/QOGLViewer/qoglviewer.h | 8 ++++++- thirdparty/libQGLViewer/QOGLViewer/vec.h | 5 +++-- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt b/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt index 64f3c40e..2cea9109 100644 --- a/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt +++ b/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt @@ -40,7 +40,7 @@ set(SOURCE_FILES ) if(WIN32) - ADD_DEFINITIONS(-DCREATE_QGLVIEWER_DLL -DNOMINMAX) + ADD_DEFINITIONS(-DCREATE_QGLVIEWER_DLL -DNOMINMAX /W3) else() ADD_DEFINITIONS(-fPIC) endif() diff --git a/thirdparty/libQGLViewer/QOGLViewer/constraint.h b/thirdparty/libQGLViewer/QOGLViewer/constraint.h index e90f36fe..8ce272c2 100644 --- a/thirdparty/libQGLViewer/QOGLViewer/constraint.h +++ b/thirdparty/libQGLViewer/QOGLViewer/constraint.h @@ -329,8 +329,10 @@ class QGLVIEWER_EXPORT CameraConstraint : public AxisPlaneConstraint /*! Returns the associated Camera. Set using the CameraConstraint constructor. */ const Camera* camera() const { return camera_; }; + CameraConstraint& operator=(const CameraConstraint&) = delete; private: const Camera* const camera_; + }; } // namespace qoglviewer diff --git a/thirdparty/libQGLViewer/QOGLViewer/keyFrameInterpolator.h b/thirdparty/libQGLViewer/QOGLViewer/keyFrameInterpolator.h index 4b991c4c..8c61b29a 100644 --- a/thirdparty/libQGLViewer/QOGLViewer/keyFrameInterpolator.h +++ b/thirdparty/libQGLViewer/QOGLViewer/keyFrameInterpolator.h @@ -312,6 +312,7 @@ private Q_SLOTS: void updateValuesFromPointer(); void flipOrientationIfNeeded(const Quaternion& prev); void computeTangent(const KeyFrame* const prev, const KeyFrame* const next); + KeyFrame& operator=(const KeyFrame&) = delete; private: Vec p_, tgP_; Quaternion q_, tgQ_; diff --git a/thirdparty/libQGLViewer/QOGLViewer/qoglviewer.cpp b/thirdparty/libQGLViewer/QOGLViewer/qoglviewer.cpp index 14233b00..b5288e02 100644 --- a/thirdparty/libQGLViewer/QOGLViewer/qoglviewer.cpp +++ b/thirdparty/libQGLViewer/QOGLViewer/qoglviewer.cpp @@ -354,16 +354,6 @@ void QOGLViewer::postDraw() /// REMOVED } -/*! Called before draw() (instead of preDraw()) when viewer displaysInStereo(). - -Same as preDraw() except that the glDrawBuffer() is set to \c GL_BACK_LEFT or \c GL_BACK_RIGHT -depending on \p leftBuffer, and it uses qoglviewer::Camera::loadProjectionMatrixStereo() and -qoglviewer::Camera::loadModelViewMatrixStereo() instead. */ -void QOGLViewer::preDrawStereo(bool leftBuffer) -{ - /// REMOVED -} - /*! Draws a simplified version of the scene to guarantee interactive camera displacements. This method is called instead of draw() when the qoglviewer::Camera::frame() is @@ -697,7 +687,7 @@ near clipping plane and 1.0 being just beyond the far clipping plane). This inte values that can be read from the z-buffer. Note that if you use the convenient \c glVertex2i() to provide coordinates, the implicit 0.0 z coordinate will make your drawings appear \e on \e top of the rest of the scene. */ -void QOGLViewer::startScreenCoordinatesSystem(bool upward) const +void QOGLViewer::startScreenCoordinatesSystem(bool /*upward*/) const { /// REMOVED } @@ -786,7 +776,7 @@ example) to implement your selection mechanism. This method is called when you use the QOGLViewer::SELECT mouse binding(s) (default is Shift + left button). Use setMouseBinding() to change this. */ -void QOGLViewer::select(const QMouseEvent* event) +void QOGLViewer::select(const QMouseEvent* /*event*/) { /// REMOVED } @@ -841,7 +831,7 @@ perform an analytical intersection. \attention \c GL_SELECT mode seems to report wrong results when used in conjunction with backface culling. If you encounter problems try to \c glDisable(GL_CULL_FACE). */ -void QOGLViewer::select(const QPoint& point) +void QOGLViewer::select(const QPoint& /*point*/) { /// REMOVED } @@ -857,7 +847,7 @@ using qoglviewer::Camera::loadModelViewMatrix(). See the gluPickMatrix() documen You should not need to redefine this method (if you use the \c GL_SELECT mode to perform your selection), since this code is fairly classical and can be tuned. You are more likely to overload endSelection() if you want to use a more complex select buffer structure. */ -void QOGLViewer::beginSelection(const QPoint& point) +void QOGLViewer::beginSelection(const QPoint& /*point*/) { /// REMOVED } @@ -1959,7 +1949,7 @@ void QOGLViewer::keyPressEvent(QKeyEvent *e) camera()->addKeyFrameToPath(index); if (nullBefore) connect(camera()->keyFrameInterpolator(index), SIGNAL(interpolated()), SLOT(update())); - int nbKF = camera()->keyFrameInterpolator(index)->numberOfKeyFrames(); +// int nbKF = camera()->keyFrameInterpolator(index)->numberOfKeyFrames(); // if (nbKF > 1) // displayMessage(tr("Path %1, position %2 added", "Feedback message").arg(index).arg(nbKF)); // else @@ -2740,7 +2730,7 @@ unsigned int QOGLViewer::wheelButtonState(MouseHandler handler, MouseAction acti if ( (it.value().handler == handler) && (it.value().action == action) && (it.value().withConstraint == withConstraint) ) return it.key().key + it.key().modifiers; - return -1; + return 0xffffffff; } /*! This method is deprecated since version 2.5.0 diff --git a/thirdparty/libQGLViewer/QOGLViewer/qoglviewer.h b/thirdparty/libQGLViewer/QOGLViewer/qoglviewer.h index 702ee12f..269c61e7 100644 --- a/thirdparty/libQGLViewer/QOGLViewer/qoglviewer.h +++ b/thirdparty/libQGLViewer/QOGLViewer/qoglviewer.h @@ -629,7 +629,7 @@ public Q_SLOTS: virtual void paintGL(); virtual void preDraw(); - virtual void preDrawStereo(bool leftBuffer=true); +// virtual void preDrawStereo(bool leftBuffer=true); /*! The core method of the viewer, that draws the scene. @@ -1087,6 +1087,8 @@ private Q_SLOTS: return modifiers < mbp.modifiers; return button < mbp.button; } + + MouseBindingPrivate& operator=(const MouseBindingPrivate&) = delete; }; // W h e e l b i n d i n g s @@ -1104,6 +1106,8 @@ private Q_SLOTS: return key < wbp.key; return modifiers < wbp.modifiers; } + + WheelBindingPrivate& operator=(const WheelBindingPrivate&) = delete; }; // C l i c k b i n d i n g s @@ -1130,6 +1134,8 @@ private Q_SLOTS: return button < cbp.button; return doubleClick != cbp.doubleClick; } + + ClickBindingPrivate& operator=(const ClickBindingPrivate&) = delete; }; #endif static QString formatClickActionPrivate(ClickBindingPrivate cbp); diff --git a/thirdparty/libQGLViewer/QOGLViewer/vec.h b/thirdparty/libQGLViewer/QOGLViewer/vec.h index c943c6b9..9464d0b8 100644 --- a/thirdparty/libQGLViewer/QOGLViewer/vec.h +++ b/thirdparty/libQGLViewer/QOGLViewer/vec.h @@ -69,13 +69,14 @@ class QGLVIEWER_EXPORT Vec # define QGLVIEWER_UNION_NOT_SUPPORTED #endif +# define QGLVIEWER_UNION_NOT_SUPPORTED + public: /*! The internal data representation is public. One can use v.x, v.y, v.z. See also operator[](). */ #if defined (DOXYGEN) || defined (QGLVIEWER_UNION_NOT_SUPPORTED) qreal x, y, z; #else - union - { + union { struct { qreal x, y, z; }; qreal v_[3]; }; From e6e5974be0ac91ddd2ac6fc47f2d4eab2bb5d2b0 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Sun, 28 Feb 2016 19:01:14 +0100 Subject: [PATCH 213/402] less warning --- cgogn/core/CMakeLists.txt | 3 +- cgogn/core/container/chunk_array.cpp | 2 +- cgogn/core/container/chunk_array.h | 2 +- cgogn/core/container/chunk_array_container.h | 2 +- cgogn/core/container/chunk_array_gen.h | 2 +- cgogn/core/container/chunk_stack.h | 2 +- cgogn/core/utils/dll.h | 42 ---- cgogn/core/utils/thread_pool.h | 3 +- .../tests/types/bounding_box_test.cpp | 66 +++--- cgogn/geometry/types/vec.h | 11 +- cgogn/io/import_ply_data.cpp | 198 +++++++++--------- cgogn/rendering/examples/simple_viewer.cpp | 2 +- cgogn/rendering/map_render.h | 2 +- cgogn/rendering/shaders/shader_program.h | 2 +- 14 files changed, 158 insertions(+), 181 deletions(-) delete mode 100644 cgogn/core/utils/dll.h diff --git a/cgogn/core/CMakeLists.txt b/cgogn/core/CMakeLists.txt index d422b5a3..e0d2f45e 100644 --- a/cgogn/core/CMakeLists.txt +++ b/cgogn/core/CMakeLists.txt @@ -3,7 +3,8 @@ project(cgogn_core ) set(HEADER_FILES - basic/dll.h + dll.h + basic/dart.h basic/dart_marker.h basic/cell.h diff --git a/cgogn/core/container/chunk_array.cpp b/cgogn/core/container/chunk_array.cpp index 84d0acce..b4767598 100644 --- a/cgogn/core/container/chunk_array.cpp +++ b/cgogn/core/container/chunk_array.cpp @@ -24,7 +24,7 @@ #define CGOGN_CORE_DLL_EXPORT #define CORE_CONTAINER_CHUNK_ARRAY_CPP_ -#include +#include #include namespace cgogn diff --git a/cgogn/core/container/chunk_array.h b/cgogn/core/container/chunk_array.h index 2e755708..5f582a52 100644 --- a/cgogn/core/container/chunk_array.h +++ b/cgogn/core/container/chunk_array.h @@ -33,7 +33,7 @@ #include #include #include -#include +#include namespace cgogn diff --git a/cgogn/core/container/chunk_array_container.h b/cgogn/core/container/chunk_array_container.h index 0ada02b8..4f040092 100644 --- a/cgogn/core/container/chunk_array_container.h +++ b/cgogn/core/container/chunk_array_container.h @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/cgogn/core/container/chunk_array_gen.h b/cgogn/core/container/chunk_array_gen.h index de53307f..9291a013 100644 --- a/cgogn/core/container/chunk_array_gen.h +++ b/cgogn/core/container/chunk_array_gen.h @@ -25,7 +25,7 @@ #define CORE_CONTAINER_CHUNK_ARRAY_GEN_H_ #include -#include +#include #include #include diff --git a/cgogn/core/container/chunk_stack.h b/cgogn/core/container/chunk_stack.h index 2620dd20..4536a4b7 100644 --- a/cgogn/core/container/chunk_stack.h +++ b/cgogn/core/container/chunk_stack.h @@ -26,7 +26,7 @@ #include #include -#include +#include namespace cgogn { diff --git a/cgogn/core/utils/dll.h b/cgogn/core/utils/dll.h deleted file mode 100644 index 7a93c8aa..00000000 --- a/cgogn/core/utils/dll.h +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************* -* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * -* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * -* * -* This library is free software; you can redistribute it and/or modify it * -* under the terms of the GNU Lesser General Public License as published by the * -* Free Software Foundation; either version 2.1 of the License, or (at your * -* option) any later version. * -* * -* This library is distributed in the hope that it will be useful, but WITHOUT * -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * -* for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with this library; if not, write to the Free Software Foundation, * -* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * -* * -* Web site: http://cgogn.unistra.fr/ * -* Contact information: cgogn@unistra.fr * -* * -*******************************************************************************/ - -#ifndef CORE_UTILS_DLL_H_ -#define CORE_UTILS_DLL_H_ - -/** -* \brief Linkage declaration for CGOGN symbols. -*/ -#ifdef WIN32 -#ifndef CGOGN_UTILS_API -#if defined CGOGN_UTILS_DLL_EXPORT -#define CGOGN_UTILS_API __declspec(dllexport) -#else -#define CGOGN_UTILS_API __declspec(dllimport) -#endif -#endif -#else -#define CGOGN_UTILS_API -#endif - -#endif // CORE_UTILS_DLL_H_ diff --git a/cgogn/core/utils/thread_pool.h b/cgogn/core/utils/thread_pool.h index 867bdd3f..20c0b081 100644 --- a/cgogn/core/utils/thread_pool.h +++ b/cgogn/core/utils/thread_pool.h @@ -123,9 +123,8 @@ auto ThreadPool::enqueue(const F& f, Args&&... args) // don't allow enqueueing after stopping the pool if (stop_) { + std::cerr << "enqueue on stopped ThreadPool" << std::endl; cgogn_assert_not_reached("enqueue on stopped ThreadPool"); -// std::cerr << "enqueue on stopped ThreadPool" << std::endl; -// exit(1); } // Push work back on the queue tasks_.emplace([task](unsigned int i){ (*task)(i); }); diff --git a/cgogn/geometry/tests/types/bounding_box_test.cpp b/cgogn/geometry/tests/types/bounding_box_test.cpp index 70c49a90..b607ea0d 100644 --- a/cgogn/geometry/tests/types/bounding_box_test.cpp +++ b/cgogn/geometry/tests/types/bounding_box_test.cpp @@ -27,14 +27,14 @@ #include using StdArray = cgogn::geometry::Vec_T>; -//using EigenVec3d = Eigen::Vector3d; +using EigenVec3d = Eigen::Vector3d; using BoundingBox_Array = cgogn::geometry::BoundingBox; -//using BoundingBox_Eigen = cgogn::geometry::BoundingBox; +using BoundingBox_Eigen = cgogn::geometry::BoundingBox; TEST(BoundingBox_TEST, NameOfType) { EXPECT_EQ(cgogn::name_of_type(BoundingBox_Array()), "cgogn::geometry::BoundingBox>>"); -// EXPECT_EQ(cgogn::name_of_type(BoundingBox_Eigen()), "cgogn::geometry::BoundingBox>"); + EXPECT_EQ(cgogn::name_of_type(BoundingBox_Eigen()), "cgogn::geometry::BoundingBox>"); } TEST(BoundingBox_TEST, Basics) @@ -55,17 +55,17 @@ TEST(BoundingBox_TEST, Basics) EXPECT_EQ(bb.center(), StdArray({0.,0.,0.})); } { -// BoundingBox_Eigen bb; -// bb.add_point(EigenVec3d(0.5,0.4,0.3)); -// bb.add_point(EigenVec3d(-1,2,-3)); -// bb.add_point(EigenVec3d(1,-2,3)); - -// EXPECT_EQ(bb.min(), EigenVec3d(-1,-2,-3)); -// EXPECT_EQ(bb.max(), EigenVec3d(1,2,3)); -// EXPECT_EQ(bb.max_size(), 6); -// EXPECT_EQ(bb.min_size(), 2); -// EXPECT_TRUE(cgogn::almost_equal_relative(bb.diag_size(), std::sqrt(2.0*2+4*4+6*6))); -// EXPECT_EQ(bb.center(), EigenVec3d(0,0,0)); + BoundingBox_Eigen bb; + bb.add_point(EigenVec3d(0.5,0.4,0.3)); + bb.add_point(EigenVec3d(-1,2,-3)); + bb.add_point(EigenVec3d(1,-2,3)); + + EXPECT_EQ(bb.min(), EigenVec3d(-1,-2,-3)); + EXPECT_EQ(bb.max(), EigenVec3d(1,2,3)); + EXPECT_EQ(bb.max_size(), 6); + EXPECT_EQ(bb.min_size(), 2); + EXPECT_TRUE(cgogn::almost_equal_relative(bb.diag_size(), std::sqrt(2.0*2+4*4+6*6))); + EXPECT_EQ(bb.center(), EigenVec3d(0,0,0)); } } @@ -93,28 +93,36 @@ TEST(BoundingBox_TEST, testing) EXPECT_TRUE(bb.ray_intersect(StdArray({-9.,-9.,-9.}), StdArray({1.,1.,1.}))); EXPECT_FALSE(bb.ray_intersect(StdArray({-9.,-9.,-9.}), StdArray({1.,-1.,0.}))); + + EXPECT_TRUE(bb3.contains(StdArray({ 0.2, 0.2, 0.2 }), StdArray({ 0.5, 0.5, 0.5 }))); + EXPECT_FALSE(bb3.contains(StdArray({ -0.5, -0.5, -0.5 }), StdArray({ 0.5, 0.5, 0.5 }))); + EXPECT_FALSE(bb3.contains(StdArray({ 0.5, 0.5, 0.5 }), StdArray({ 1.5, 0.5, 1.5 }))); } { -// BoundingBox_Eigen bb; -// bb.add_point(EigenVec3d(0.5,0.4,0.3)); -// bb.add_point(EigenVec3d(-1,2,-3)); -// bb.add_point(EigenVec3d(1,-2,3)); + BoundingBox_Eigen bb; + bb.add_point(EigenVec3d(0.5,0.4,0.3)); + bb.add_point(EigenVec3d(-1,2,-3)); + bb.add_point(EigenVec3d(1,-2,3)); + + EXPECT_TRUE(bb.contains(EigenVec3d(1,1,1))); -// EXPECT_TRUE(bb.contains(EigenVec3d(1,1,1))); + BoundingBox_Eigen bb2; + bb2.add_point(EigenVec3d(0,0,0)); + bb2.add_point(EigenVec3d(4,5,2)); -// BoundingBox_Eigen bb2; -// bb2.add_point(EigenVec3d(0,0,0)); -// bb2.add_point(EigenVec3d(4,5,2)); + EXPECT_TRUE(bb.intersects(bb2)); -// EXPECT_TRUE(bb.intersects(bb2)); + BoundingBox_Eigen bb3; + bb3.add_point(EigenVec3d(0,0,0)); + bb3.add_point(EigenVec3d(1,1,1)); -// BoundingBox_Eigen bb3; -// bb3.add_point(EigenVec3d(0,0,0)); -// bb3.add_point(EigenVec3d(1,1,1)); + EXPECT_TRUE(bb.contains(bb3)); -// EXPECT_TRUE(bb.contains(bb3)); + EXPECT_TRUE(bb.ray_intersect(EigenVec3d(-9,-9,-9), EigenVec3d(1,1,1))); + EXPECT_FALSE(bb.ray_intersect(EigenVec3d(-9,-9,-9), EigenVec3d(1,-1,0))); -// EXPECT_TRUE(bb.ray_intersect(EigenVec3d(-9,-9,-9), EigenVec3d(1,1,1))); -// EXPECT_FALSE(bb.ray_intersect(EigenVec3d(-9,-9,-9), EigenVec3d(1,-1,0))); + EXPECT_TRUE(bb3.contains(EigenVec3d(0.2, 0.2, 0.2), EigenVec3d(0.5, 0.5, 0.5))); + EXPECT_FALSE(bb3.contains(EigenVec3d(-0.5, -0.5, -0.5), EigenVec3d(0.5, 0.5, 0.5))); + EXPECT_FALSE(bb3.contains(EigenVec3d(0.5, 0.5, 0.5), EigenVec3d(1.5, 0.5, 1.5))); } } diff --git a/cgogn/geometry/types/vec.h b/cgogn/geometry/types/vec.h index 4a290bdc..32675add 100644 --- a/cgogn/geometry/types/vec.h +++ b/cgogn/geometry/types/vec.h @@ -58,11 +58,16 @@ class Vec_T using Self = Vec_T; using Scalar = typename std::remove_cv< typename std::remove_reference::type >::type; + inline Vec_T(Scalar a) { data_[0] = a; } + inline Vec_T(Scalar a, Scalar b) { data_[0] = a; data_[1] = b; } + inline Vec_T(Scalar a, Scalar b, Scalar c) { data_[0] = a; data_[1] = b; data_[2] = c; } + inline Vec_T(Scalar a, Scalar b, Scalar c, Scalar d) { data_[0] = a; data_[1] = b; data_[2] = c; data_[3] = d; } + inline Vec_T() : data_() {} - template - inline Vec_T(Args... a) : data_({ std::forward(a)... }) - {} + //template + //inline Vec_T(Args... a) : data_({ { std::forward(a)... } }) + //{} Vec_T(const Self&v) = default; Self& operator=(const Self& v) = default; diff --git a/cgogn/io/import_ply_data.cpp b/cgogn/io/import_ply_data.cpp index 0de57a11..63caa1a5 100644 --- a/cgogn/io/import_ply_data.cpp +++ b/cgogn/io/import_ply_data.cpp @@ -20,6 +20,11 @@ * Contact information: cgogn@unistra.fr * * * *******************************************************************************/ + +#ifdef WIN32 +#pragma warning(disable:4996) +#endif + #define CGOGN_IO_DLL_EXPORT #define IO_IMPORT_PLY_DATA_CPP_ @@ -101,7 +106,6 @@ PlyImportData::~PlyImportData() } - bool PlyImportData::read_file(const std::string& filename) { FILE* fp = NULL; @@ -126,115 +130,117 @@ bool PlyImportData::read_file(const std::string& filename) else fp = fopen(filename.c_str(), "rb"); + /*** Read in the original PLY object ***/ - /*** Read in the original PLY object ***/ - - if (fp==NULL) - return false; - - PlyFile *in_ply = read_ply (fp); - if (in_ply==NULL) - return false; - - for (int i = 0; i < in_ply->num_elem_types; i++) - { - int elem_count; - /* prepare to read the i'th list of elements */ - char *elem_name = setup_element_read_ply (in_ply, i, &elem_count); - - if (equal_strings ((char*) "vertex", elem_name)) { + if (fp == NULL) + return false; - /* create a vertex list to hold all the vertices */ - vlist = (VertexPly **) malloc (sizeof (VertexPly *) * elem_count); - nverts = elem_count; + PlyFile *in_ply = read_ply(fp); - /* set up for getting vertex elements */ + fclose(fp); - setup_property_ply (in_ply, &vert_props[0]); - setup_property_ply (in_ply, &vert_props[1]); - setup_property_ply (in_ply, &vert_props[2]); + if (in_ply == NULL) + return false; - for (int j = 0; j < in_ply->elems[i]->nprops; j++) - { - PlyProperty *prop; - prop = in_ply->elems[i]->props[j]; - if (equal_strings ((char*) "red", prop->name)) { - setup_property_ply (in_ply, &vert_props[3]); - per_vertex_color_uint8 = 1; - } - if (equal_strings ((char*) "green", prop->name)) { - setup_property_ply (in_ply, &vert_props[4]); - per_vertex_color_uint8 = 1; - } - if (equal_strings ((char*) "blue", prop->name)) { - setup_property_ply (in_ply, &vert_props[5]); - per_vertex_color_uint8 = 1; - } - if (equal_strings ((char*) "r", prop->name)) { - setup_property_ply (in_ply, &vert_props[6]); - per_vertex_color_float32 = 1; - } - if (equal_strings ((char*) "g", prop->name)) { - setup_property_ply (in_ply, &vert_props[7]); - per_vertex_color_float32 = 1; - } - if (equal_strings ((char*) "b", prop->name)) { - setup_property_ply (in_ply, &vert_props[8]); - per_vertex_color_float32 = 1; - } - if (equal_strings ((char*) "nx", prop->name)) { - setup_property_ply (in_ply, &vert_props[9]); - has_normals_ = 1; - } - if (equal_strings ((char*) "ny", prop->name)) { - setup_property_ply (in_ply, &vert_props[10]); - has_normals_ = 1; - } - if (equal_strings ((char*) "nz", prop->name)) { - setup_property_ply (in_ply, &vert_props[11]); - has_normals_ = 1; + for (int i = 0; i < in_ply->num_elem_types; i++) + { + int elem_count; + /* prepare to read the i'th list of elements */ + char *elem_name = setup_element_read_ply(in_ply, i, &elem_count); + + if (equal_strings((char*) "vertex", elem_name)) { + + /* create a vertex list to hold all the vertices */ + vlist = (VertexPly **)malloc(sizeof (VertexPly *)* elem_count); + nverts = elem_count; + + /* set up for getting vertex elements */ + + setup_property_ply(in_ply, &vert_props[0]); + setup_property_ply(in_ply, &vert_props[1]); + setup_property_ply(in_ply, &vert_props[2]); + + for (int j = 0; j < in_ply->elems[i]->nprops; j++) + { + PlyProperty *prop; + prop = in_ply->elems[i]->props[j]; + if (equal_strings((char*) "red", prop->name)) { + setup_property_ply(in_ply, &vert_props[3]); + per_vertex_color_uint8 = 1; + } + if (equal_strings((char*) "green", prop->name)) { + setup_property_ply(in_ply, &vert_props[4]); + per_vertex_color_uint8 = 1; + } + if (equal_strings((char*) "blue", prop->name)) { + setup_property_ply(in_ply, &vert_props[5]); + per_vertex_color_uint8 = 1; + } + if (equal_strings((char*) "r", prop->name)) { + setup_property_ply(in_ply, &vert_props[6]); + per_vertex_color_float32 = 1; + } + if (equal_strings((char*) "g", prop->name)) { + setup_property_ply(in_ply, &vert_props[7]); + per_vertex_color_float32 = 1; + } + if (equal_strings((char*) "b", prop->name)) { + setup_property_ply(in_ply, &vert_props[8]); + per_vertex_color_float32 = 1; + } + if (equal_strings((char*) "nx", prop->name)) { + setup_property_ply(in_ply, &vert_props[9]); + has_normals_ = 1; + } + if (equal_strings((char*) "ny", prop->name)) { + setup_property_ply(in_ply, &vert_props[10]); + has_normals_ = 1; + } + if (equal_strings((char*) "nz", prop->name)) { + setup_property_ply(in_ply, &vert_props[11]); + has_normals_ = 1; + } + } + + vert_other = get_other_properties_ply(in_ply, + offsetof(VertexPly, other_props)); + + /* grab all the vertex elements */ + for (int j = 0; j < elem_count; j++) { + vlist[j] = (VertexPly *)malloc(sizeof (VertexPly)); + vlist[j]->r = 1; + vlist[j]->g = 1; + vlist[j]->b = 1; + get_element_ply(in_ply, (void *)vlist[j]); + } } - } - - vert_other = get_other_properties_ply (in_ply, - offsetof(VertexPly,other_props)); - - /* grab all the vertex elements */ - for (int j = 0; j < elem_count; j++) { - vlist[j] = (VertexPly *) malloc (sizeof (VertexPly)); - vlist[j]->r = 1; - vlist[j]->g = 1; - vlist[j]->b = 1; - get_element_ply (in_ply, (void *) vlist[j]); - } - } - else if (equal_strings ((char*) "face", elem_name)) { + else if (equal_strings((char*) "face", elem_name)) { - /* create a list to hold all the face elements */ - flist = (FacePly **) malloc (sizeof (FacePly *) * elem_count); - nfaces = elem_count; + /* create a list to hold all the face elements */ + flist = (FacePly **)malloc(sizeof (FacePly *)* elem_count); + nfaces = elem_count; - /* set up for getting face elements */ + /* set up for getting face elements */ - setup_property_ply (in_ply, &face_props[0]); - face_other = get_other_properties_ply (in_ply, - offsetof(FacePly,other_props)); + setup_property_ply(in_ply, &face_props[0]); + face_other = get_other_properties_ply(in_ply, + offsetof(FacePly, other_props)); - /* grab all the face elements */ - for (int j = 0; j < elem_count; j++) { - flist[j] = (FacePly *) malloc (sizeof (FacePly)); - get_element_ply (in_ply, (void *) flist[j]); - } + /* grab all the face elements */ + for (int j = 0; j < elem_count; j++) { + flist[j] = (FacePly *)malloc(sizeof (FacePly)); + get_element_ply(in_ply, (void *)flist[j]); + } + } + else + get_other_element_ply(in_ply); } - else - get_other_element_ply (in_ply); - } - close_ply (in_ply); + close_ply(in_ply); - free_ply (in_ply); + free_ply(in_ply); - return true; + return true; } } // namespace io diff --git a/cgogn/rendering/examples/simple_viewer.cpp b/cgogn/rendering/examples/simple_viewer.cpp index e5c797d9..5ed5291c 100644 --- a/cgogn/rendering/examples/simple_viewer.cpp +++ b/cgogn/rendering/examples/simple_viewer.cpp @@ -167,7 +167,7 @@ void Viewer::draw() void Viewer::init() { - glClearColor(0.1,0.1,0.3,0.0); + glClearColor(0.1f,0.1f,0.3f,0.0f); vbo_pos_ = new cgogn::rendering::VBO; cgogn::rendering::update_vbo(vertex_position_, *vbo_pos_); diff --git a/cgogn/rendering/map_render.h b/cgogn/rendering/map_render.h index 6db49967..54601bdf 100644 --- a/cgogn/rendering/map_render.h +++ b/cgogn/rendering/map_render.h @@ -141,7 +141,7 @@ class MapRender indices_buffers_[prim]->create(); indices_buffers_uptodate_[prim] = true; - nb_indices_[prim] = table_indices.size(); + nb_indices_[prim] = static_cast(table_indices.size()); indices_buffers_[prim]->bind(); indices_buffers_[prim]->allocate(&(table_indices[0]), nb_indices_[prim] * sizeof(unsigned int)); indices_buffers_[prim]->release(); diff --git a/cgogn/rendering/shaders/shader_program.h b/cgogn/rendering/shaders/shader_program.h index ee38b97c..08397945 100644 --- a/cgogn/rendering/shaders/shader_program.h +++ b/cgogn/rendering/shaders/shader_program.h @@ -78,7 +78,7 @@ class CGOGN_RENDERING_API ShaderProgram : protected QOpenGLFunctions_3_3_Core { vaos_.emplace_back(new QOpenGLVertexArrayObject); vaos_.back()->create(); - return vaos_.size() - 1; + return static_cast(vaos_.size() - 1); } /** From d81e431c72d57560789879071129fb3520067ca4 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Sun, 28 Feb 2016 19:43:56 +0100 Subject: [PATCH 214/402] add some assert on Vec_T constructor --- cgogn/core/CMakeLists.txt | 1 - cgogn/geometry/types/vec.h | 27 +++++++++++++++++++++++---- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/cgogn/core/CMakeLists.txt b/cgogn/core/CMakeLists.txt index e0d2f45e..8a21eb6e 100644 --- a/cgogn/core/CMakeLists.txt +++ b/cgogn/core/CMakeLists.txt @@ -31,7 +31,6 @@ set(HEADER_FILES utils/assert.h utils/buffers.h utils/definitions.h - utils/dll.h utils/endian.h utils/make_unique.h utils/name_types.h diff --git a/cgogn/geometry/types/vec.h b/cgogn/geometry/types/vec.h index 32675add..ccfa851c 100644 --- a/cgogn/geometry/types/vec.h +++ b/cgogn/geometry/types/vec.h @@ -58,10 +58,29 @@ class Vec_T using Self = Vec_T; using Scalar = typename std::remove_cv< typename std::remove_reference::type >::type; - inline Vec_T(Scalar a) { data_[0] = a; } - inline Vec_T(Scalar a, Scalar b) { data_[0] = a; data_[1] = b; } - inline Vec_T(Scalar a, Scalar b, Scalar c) { data_[0] = a; data_[1] = b; data_[2] = c; } - inline Vec_T(Scalar a, Scalar b, Scalar c, Scalar d) { data_[0] = a; data_[1] = b; data_[2] = c; data_[3] = d; } + inline Vec_T(Scalar a) + { + cgogn_message_assert(std::tuple_size::value >= 1, "wrong contructor, too many data"); + data_[0] = a; + } + + inline Vec_T(Scalar a, Scalar b) + { + cgogn_message_assert(std::tuple_size::value >= 2, "wrong contructor, too many data"); + data_[0] = a; data_[1] = b; + } + + inline Vec_T(Scalar a, Scalar b, Scalar c) + { + cgogn_message_assert(std::tuple_size::value >= 3, "wrong contructor, too many data"); + data_[0] = a; data_[1] = b; data_[2] = c; + } + + inline Vec_T(Scalar a, Scalar b, Scalar c, Scalar d) + { + cgogn_message_assert(std::tuple_size::value >= 4, "wrong contructor, too many data"); + data_[0] = a; data_[1] = b; data_[2] = c; data_[3] = d; + } inline Vec_T() : data_() {} From 325448b0186aa20a8746f1f3eb2b5a8a8edfc81f Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Sun, 28 Feb 2016 23:59:51 +0100 Subject: [PATCH 215/402] less warnings --- cgogn/geometry/algos/centroid.h | 2 +- cgogn/geometry/functions/area.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cgogn/geometry/algos/centroid.h b/cgogn/geometry/algos/centroid.h index 5feb5eea..e9be6a75 100644 --- a/cgogn/geometry/algos/centroid.h +++ b/cgogn/geometry/algos/centroid.h @@ -43,7 +43,7 @@ inline T centroid(const MAP& map, Cell c, const typename MAP::template Ve result += attribute[v]; ++count; }); - result /= count; + result /= T::Scalar(count); return result; } diff --git a/cgogn/geometry/functions/area.h b/cgogn/geometry/functions/area.h index b3d96c70..fe041b63 100644 --- a/cgogn/geometry/functions/area.h +++ b/cgogn/geometry/functions/area.h @@ -36,7 +36,7 @@ namespace geometry template inline typename VEC3_T::Scalar triangle_area(const VEC3_T& p1, const VEC3_T& p2, const VEC3_T& p3) { - return (0.5 * ((p2-p1).cross(p3-p1)).norm()); + return (typename VEC3_T::Scalar(0.5) * ((p2 - p1).cross(p3 - p1)).norm()); } } // namespace geometry From b8501285548b8f538761f1e8d058d92de1301030 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Mon, 29 Feb 2016 10:43:59 +0100 Subject: [PATCH 216/402] check Linux compile --- cgogn/geometry/algos/centroid.h | 2 +- thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/cgogn/geometry/algos/centroid.h b/cgogn/geometry/algos/centroid.h index e9be6a75..3caeb0e2 100644 --- a/cgogn/geometry/algos/centroid.h +++ b/cgogn/geometry/algos/centroid.h @@ -43,7 +43,7 @@ inline T centroid(const MAP& map, Cell c, const typename MAP::template Ve result += attribute[v]; ++count; }); - result /= T::Scalar(count); + result /= typename T::Scalar(count); return result; } diff --git a/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt b/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt index 2cea9109..8945ea81 100644 --- a/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt +++ b/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt @@ -39,15 +39,18 @@ set(SOURCE_FILES vec.cpp ) + +add_library(QOGLViewer SHARED ${HEADER_FILES} ${SOURCE_FILES}) +target_link_libraries(QOGLViewer ${OPENGL_LIBRARY} Qt5::Widgets) + if(WIN32) ADD_DEFINITIONS(-DCREATE_QGLVIEWER_DLL -DNOMINMAX /W3) else() + target_compile_options(${PROJECT_NAME} PUBLIC "-std=c++11") ADD_DEFINITIONS(-fPIC) endif() -add_library(QOGLViewer SHARED ${HEADER_FILES} ${SOURCE_FILES}) -target_link_libraries(QOGLViewer ${OPENGL_LIBRARY} Qt5::Widgets) From 5ddd537807441b2f9a92f6cee93b05dff40f45c4 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Mon, 29 Feb 2016 14:50:21 +0100 Subject: [PATCH 217/402] fix locale pb during import on mac & some Arch --- cgogn/io/CMakeLists.txt | 1 + cgogn/io/c_locale.h | 47 ++++++++++++++++++++++++++++++++++++ cgogn/io/import_ply_data.cpp | 4 +-- cgogn/io/import_ply_data.h | 2 -- cgogn/io/surface_import.h | 4 +++ cgogn/io/volume_import.h | 3 +++ cmake/CompilerOptions.cmake | 4 ++- 7 files changed, 59 insertions(+), 6 deletions(-) create mode 100644 cgogn/io/c_locale.h diff --git a/cgogn/io/CMakeLists.txt b/cgogn/io/CMakeLists.txt index 2a752f71..4aa1ff81 100644 --- a/cgogn/io/CMakeLists.txt +++ b/cgogn/io/CMakeLists.txt @@ -9,6 +9,7 @@ set(HEADER_FILES map_export.h import_ply_data.h dll.h + c_locale.h ) set(SOURCE_FILES diff --git a/cgogn/io/c_locale.h b/cgogn/io/c_locale.h new file mode 100644 index 00000000..1421c8ec --- /dev/null +++ b/cgogn/io/c_locale.h @@ -0,0 +1,47 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef IO_C_LOCALE_H_ +#define IO_C_LOCALE_H_ + +class Scoped_C_Locale +{ + std::string current_locale_; +public: + + /// set numeric locale to C after saving current locale + inline Scoped_C_Locale() + { + current_locale_ = std::string(setlocale(LC_NUMERIC, NULL)); + setlocale(LC_NUMERIC, "C"); + } + + /// restore locale + inline ~Scoped_C_Locale() + { + setlocale(LC_NUMERIC, current_locale_.c_str()); + } +}; + + +#endif // IO_C_LOCALE_H_ diff --git a/cgogn/io/import_ply_data.cpp b/cgogn/io/import_ply_data.cpp index 63caa1a5..96e798d5 100644 --- a/cgogn/io/import_ply_data.cpp +++ b/cgogn/io/import_ply_data.cpp @@ -75,8 +75,6 @@ PlyImportData::PlyImportData(): per_vertex_color_uint8(0), has_normals_(0) { - old_locale = setlocale(LC_NUMERIC, NULL); - setlocale(LC_NUMERIC, "C"); } PlyImportData::~PlyImportData() @@ -102,7 +100,7 @@ PlyImportData::~PlyImportData() // } // need to free *vert_other,*face_other ???? - setlocale(LC_NUMERIC, old_locale); + } diff --git a/cgogn/io/import_ply_data.h b/cgogn/io/import_ply_data.h index 70d99e8b..88340f79 100644 --- a/cgogn/io/import_ply_data.h +++ b/cgogn/io/import_ply_data.h @@ -123,8 +123,6 @@ class CGOGN_IO_API PlyImportData int per_vertex_color_float32, per_vertex_color_uint8 ; int has_normals_; - - char *old_locale; }; } // namespace io diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index ebd505dc..953ee9c3 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -33,6 +33,7 @@ #include #include +#include #include namespace cgogn @@ -126,6 +127,9 @@ class SurfaceImport template bool import_file(const std::string& filename, SurfaceFileType type) { + //ensure that locale are set to C for reading files + Scoped_C_Locale loc; + clear(); std::ifstream fp(filename.c_str(), std::ios::in); diff --git a/cgogn/io/volume_import.h b/cgogn/io/volume_import.h index 45d15051..717ed07f 100644 --- a/cgogn/io/volume_import.h +++ b/cgogn/io/volume_import.h @@ -32,6 +32,7 @@ #include +#include #include #include @@ -107,6 +108,8 @@ class VolumeImport template bool import_file(const std::string& filename) { + Scoped_C_Locale loc; + const std::string& extension = to_lower(get_extension(filename)); if (extension.empty()) return false; diff --git a/cmake/CompilerOptions.cmake b/cmake/CompilerOptions.cmake index f1329e07..32e69990 100644 --- a/cmake/CompilerOptions.cmake +++ b/cmake/CompilerOptions.cmake @@ -33,7 +33,9 @@ endif(CGOGN_USE_TSAN) if (NOT MSVC) # This is the correcty way to activate threads. It should be prefered to "-lpthread" - add_flags(CMAKE_CXX_FLAGS "-pthread") + if (NOT(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")) + add_flags(CMAKE_CXX_FLAGS "-pthread") + endif() # Warning flags set(NORMAL_WARNINGS -Wall -Wextra) From b301e2cf449df20403734d1253341708d2c7292b Mon Sep 17 00:00:00 2001 From: thery Date: Mon, 29 Feb 2016 15:36:35 +0100 Subject: [PATCH 218/402] bugfix import --- cgogn/io/surface_import.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index 953ee9c3..f370e736 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -396,7 +396,7 @@ class SurfaceImport //endian unsigned int* ptr = reinterpret_cast(buff_pos); - for (unsigned int i=0; i< 3*BUFFER_SZ;++i) + for (unsigned int k=0; k< 3*BUFFER_SZ;++k) { *ptr = swap_endianness_system_big(*ptr); ++ptr; @@ -446,7 +446,7 @@ class SurfaceImport { fp.read(reinterpret_cast(buff_ind),BUFFER_SZ*sizeof(unsigned int)); ptr = buff_ind; - for (unsigned int i=0; i< BUFFER_SZ;++i) + for (unsigned int k=0; i< BUFFER_SZ;++k) { *ptr = swap_endianness_system_big(*ptr); ++ptr; From 71e9deeec618f8ffd260b96a73860f1d83239623 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Mon, 29 Feb 2016 17:25:07 +0100 Subject: [PATCH 219/402] forgotten indice error --- cgogn/io/surface_import.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index f370e736..5a69b0d6 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -446,7 +446,7 @@ class SurfaceImport { fp.read(reinterpret_cast(buff_ind),BUFFER_SZ*sizeof(unsigned int)); ptr = buff_ind; - for (unsigned int k=0; i< BUFFER_SZ;++k) + for (unsigned int k=0; k< BUFFER_SZ;++k) { *ptr = swap_endianness_system_big(*ptr); ++ptr; From 22ab03826cc021f9c04c87f4c6a27173f50f3475 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Mon, 29 Feb 2016 18:28:53 +0100 Subject: [PATCH 220/402] resolve mysteriousbug of ply crashing --- cgogn/io/import_ply_data.cpp | 85 +++++++++++++++++------------------- 1 file changed, 41 insertions(+), 44 deletions(-) diff --git a/cgogn/io/import_ply_data.cpp b/cgogn/io/import_ply_data.cpp index 96e798d5..a6b22c49 100644 --- a/cgogn/io/import_ply_data.cpp +++ b/cgogn/io/import_ply_data.cpp @@ -130,113 +130,110 @@ bool PlyImportData::read_file(const std::string& filename) /*** Read in the original PLY object ***/ - if (fp == NULL) + if (fp==NULL) return false; - PlyFile *in_ply = read_ply(fp); - - fclose(fp); - - if (in_ply == NULL) + PlyFile *in_ply = read_ply (fp); + if (in_ply==NULL) return false; for (int i = 0; i < in_ply->num_elem_types; i++) { int elem_count; /* prepare to read the i'th list of elements */ - char *elem_name = setup_element_read_ply(in_ply, i, &elem_count); + char *elem_name = setup_element_read_ply (in_ply, i, &elem_count); - if (equal_strings((char*) "vertex", elem_name)) { + if (equal_strings ((char*) "vertex", elem_name)) { /* create a vertex list to hold all the vertices */ - vlist = (VertexPly **)malloc(sizeof (VertexPly *)* elem_count); + vlist = (VertexPly **) malloc (sizeof (VertexPly *) * elem_count); nverts = elem_count; /* set up for getting vertex elements */ - setup_property_ply(in_ply, &vert_props[0]); - setup_property_ply(in_ply, &vert_props[1]); - setup_property_ply(in_ply, &vert_props[2]); + setup_property_ply (in_ply, &vert_props[0]); + setup_property_ply (in_ply, &vert_props[1]); + setup_property_ply (in_ply, &vert_props[2]); for (int j = 0; j < in_ply->elems[i]->nprops; j++) { PlyProperty *prop; prop = in_ply->elems[i]->props[j]; - if (equal_strings((char*) "red", prop->name)) { - setup_property_ply(in_ply, &vert_props[3]); + if (equal_strings ((char*) "red", prop->name)) { + setup_property_ply (in_ply, &vert_props[3]); per_vertex_color_uint8 = 1; } - if (equal_strings((char*) "green", prop->name)) { - setup_property_ply(in_ply, &vert_props[4]); + if (equal_strings ((char*) "green", prop->name)) { + setup_property_ply (in_ply, &vert_props[4]); per_vertex_color_uint8 = 1; } - if (equal_strings((char*) "blue", prop->name)) { - setup_property_ply(in_ply, &vert_props[5]); + if (equal_strings ((char*) "blue", prop->name)) { + setup_property_ply (in_ply, &vert_props[5]); per_vertex_color_uint8 = 1; } - if (equal_strings((char*) "r", prop->name)) { - setup_property_ply(in_ply, &vert_props[6]); + if (equal_strings ((char*) "r", prop->name)) { + setup_property_ply (in_ply, &vert_props[6]); per_vertex_color_float32 = 1; } - if (equal_strings((char*) "g", prop->name)) { - setup_property_ply(in_ply, &vert_props[7]); + if (equal_strings ((char*) "g", prop->name)) { + setup_property_ply (in_ply, &vert_props[7]); per_vertex_color_float32 = 1; } - if (equal_strings((char*) "b", prop->name)) { - setup_property_ply(in_ply, &vert_props[8]); + if (equal_strings ((char*) "b", prop->name)) { + setup_property_ply (in_ply, &vert_props[8]); per_vertex_color_float32 = 1; } - if (equal_strings((char*) "nx", prop->name)) { - setup_property_ply(in_ply, &vert_props[9]); + if (equal_strings ((char*) "nx", prop->name)) { + setup_property_ply (in_ply, &vert_props[9]); has_normals_ = 1; } - if (equal_strings((char*) "ny", prop->name)) { - setup_property_ply(in_ply, &vert_props[10]); + if (equal_strings ((char*) "ny", prop->name)) { + setup_property_ply (in_ply, &vert_props[10]); has_normals_ = 1; } - if (equal_strings((char*) "nz", prop->name)) { - setup_property_ply(in_ply, &vert_props[11]); + if (equal_strings ((char*) "nz", prop->name)) { + setup_property_ply (in_ply, &vert_props[11]); has_normals_ = 1; } } - vert_other = get_other_properties_ply(in_ply, - offsetof(VertexPly, other_props)); + vert_other = get_other_properties_ply (in_ply, + offsetof(VertexPly,other_props)); /* grab all the vertex elements */ for (int j = 0; j < elem_count; j++) { - vlist[j] = (VertexPly *)malloc(sizeof (VertexPly)); + vlist[j] = (VertexPly *) malloc (sizeof (VertexPly)); vlist[j]->r = 1; vlist[j]->g = 1; vlist[j]->b = 1; - get_element_ply(in_ply, (void *)vlist[j]); + get_element_ply (in_ply, (void *) vlist[j]); } } - else if (equal_strings((char*) "face", elem_name)) { + else if (equal_strings ((char*) "face", elem_name)) { /* create a list to hold all the face elements */ - flist = (FacePly **)malloc(sizeof (FacePly *)* elem_count); + flist = (FacePly **) malloc (sizeof (FacePly *) * elem_count); nfaces = elem_count; /* set up for getting face elements */ - setup_property_ply(in_ply, &face_props[0]); - face_other = get_other_properties_ply(in_ply, - offsetof(FacePly, other_props)); + setup_property_ply (in_ply, &face_props[0]); + face_other = get_other_properties_ply (in_ply, + offsetof(FacePly,other_props)); /* grab all the face elements */ for (int j = 0; j < elem_count; j++) { - flist[j] = (FacePly *)malloc(sizeof (FacePly)); - get_element_ply(in_ply, (void *)flist[j]); + flist[j] = (FacePly *) malloc (sizeof (FacePly)); + get_element_ply (in_ply, (void *) flist[j]); } } else - get_other_element_ply(in_ply); + get_other_element_ply (in_ply); } - close_ply(in_ply); + close_ply (in_ply); - free_ply(in_ply); + free_ply (in_ply); return true; } From cf903f9d967bb9afd5cc017d884a7aa553ef2c2b Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Tue, 1 Mar 2016 10:38:19 +0100 Subject: [PATCH 221/402] bold AA (or not) lines in drawer --- cgogn/rendering/drawer.cpp | 66 ++++++++++------ cgogn/rendering/drawer.h | 27 ++++++- cgogn/rendering/examples/simple_viewer.cpp | 87 +++++++++++++++------- cgogn/rendering/shaders/shader_bold_line.h | 2 +- 4 files changed, 128 insertions(+), 54 deletions(-) diff --git a/cgogn/rendering/drawer.cpp b/cgogn/rendering/drawer.cpp index 731c74cd..f431862d 100644 --- a/cgogn/rendering/drawer.cpp +++ b/cgogn/rendering/drawer.cpp @@ -39,8 +39,9 @@ ShaderColorPerVertex* Drawer::shader_cpv_= NULL; ShaderBoldLine* Drawer::shader_bl_= NULL; Drawer::Drawer(QOpenGLFunctions_3_3_Core* ogl33): - ogl33_(ogl33), - current_size_(1.0f) + current_size_(1.0f), + current_aa_(true), + ogl33_(ogl33) { vbo_pos_ = new VBO(3); vbo_col_ = new VBO(3); @@ -48,17 +49,17 @@ Drawer::Drawer(QOpenGLFunctions_3_3_Core* ogl33): if (shader_cpv_ == NULL) shader_cpv_ = new ShaderColorPerVertex(); - vao_ = shader_cpv_->add_vao(); - shader_cpv_->set_vao(vao_,vbo_pos_,vbo_col_); + vao_cpv_ = shader_cpv_->add_vao(); + shader_cpv_->set_vao(vao_cpv_,vbo_pos_,vbo_col_); if (shader_bl_ == NULL) - shader_bl_ = new ShaderBoldLine(false); + shader_bl_ = new ShaderBoldLine(true); - vao2_ = shader_bl_->add_vao(); + vao_bl_ = shader_bl_->add_vao(); shader_bl_->bind(); shader_bl_->set_color(QColor(255,255,0,255)); shader_bl_->release(); - shader_bl_->set_vao(vao2_,vbo_pos_/*,vbo_col_*/); + shader_bl_->set_vao(vao_bl_,vbo_pos_,vbo_col_); } Drawer::~Drawer() @@ -72,6 +73,7 @@ void Drawer::new_list() data_col_.clear(); begins_point_.clear(); begins_line_.clear(); + begins_bold_line_.clear(); begins_face_.clear(); } @@ -80,17 +82,25 @@ void Drawer::begin(GLenum mode) switch (mode) { case GL_POINTS: - begins_point_.push_back(PrimParam(data_pos_.size(), mode, current_size_)); + begins_point_.push_back(PrimParam(data_pos_.size(), mode, current_size_,false)); current_begin_ = &begins_point_; break; case GL_LINES: case GL_LINE_STRIP: case GL_LINE_LOOP: - begins_line_.push_back(PrimParam(data_pos_.size(), mode, current_size_)); - current_begin_ = &begins_line_; + if (current_size_ > 1.0) + { + begins_bold_line_.push_back(PrimParam(data_pos_.size(), mode, current_size_,current_aa_)); + current_begin_ = &begins_bold_line_; + } + else + { + begins_line_.push_back(PrimParam(data_pos_.size(), mode, 1.0,current_aa_)); + current_begin_ = &begins_line_; + } break; default: - begins_face_.push_back(PrimParam(data_pos_.size(), mode, 1.0f)); + begins_face_.push_back(PrimParam(data_pos_.size(), mode, 1.0f,false)); current_begin_ = &begins_face_; break; } @@ -137,7 +147,6 @@ void Drawer::end_list() std::memcpy(ptr,data_pos_[0].data(),nb_elts*12); vbo_pos_->release_pointer(); - vbo_col_->allocate(nb_elts,3); ptr = vbo_col_->lock_pointer(); std::memcpy(ptr,data_col_[0].data(),nb_elts*12); @@ -153,43 +162,56 @@ void Drawer::end_list() void Drawer::callList(const QMatrix4x4& projection, const QMatrix4x4& modelview) { -// QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); - shader_cpv_->bind(); shader_cpv_->set_matrices(projection,modelview); - shader_cpv_->bind_vao(vao_); + shader_cpv_->bind_vao(vao_cpv_); for (auto& pp : begins_point_) { ogl33_->glPointSize(pp.width); ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); } + for (auto& pp : begins_line_) + { + ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); + } for (auto& pp : begins_face_) { ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); } - shader_cpv_->release_vao(vao_); + shader_cpv_->release_vao(vao_cpv_); shader_cpv_->release(); + shader_bl_->bind(); shader_bl_->set_matrices(projection,modelview); - shader_bl_->bind_vao(vao2_); + shader_bl_->bind_vao(vao_bl_); - ogl33_->glEnable(GL_BLEND); - ogl33_->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - for (auto& pp : begins_line_) + + for (auto& pp : begins_bold_line_) { shader_bl_->set_width(pp.width); shader_bl_->set_color(QColor(255,255,0)); + + if (pp.aa) + { + ogl33_->glEnable(GL_BLEND); + ogl33_->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); + + if (pp.aa) + ogl33_->glDisable(GL_BLEND); + } - ogl33_->glDisable(GL_BLEND); - shader_bl_->release_vao(vao2_); + + shader_bl_->release_vao(vao_bl_); shader_bl_->release(); diff --git a/cgogn/rendering/drawer.h b/cgogn/rendering/drawer.h index adce1fbe..d1483883 100644 --- a/cgogn/rendering/drawer.h +++ b/cgogn/rendering/drawer.h @@ -47,7 +47,8 @@ class CGOGN_RENDERING_API Drawer//: protected QOpenGLFunctions_3_3_Core GLenum mode; float width; unsigned int nb; - PrimParam(unsigned int b, GLenum m, float w): begin(b),mode(m),width(w),nb(0) {} + bool aa; + PrimParam(unsigned int b, GLenum m, float w, bool a): begin(b),mode(m),width(w),nb(0),aa(a){} }; using Vec3f = std::array; @@ -55,14 +56,14 @@ class CGOGN_RENDERING_API Drawer//: protected QOpenGLFunctions_3_3_Core protected: VBO* vbo_pos_; VBO* vbo_col_; - unsigned int vao_; - unsigned int vao2_; - + unsigned int vao_cpv_; + unsigned int vao_bl_; std::vector data_pos_; std::vector data_col_; std::vector begins_point_; std::vector begins_line_; + std::vector begins_bold_line_; std::vector begins_face_; std::vector* current_begin_; @@ -71,6 +72,8 @@ class CGOGN_RENDERING_API Drawer//: protected QOpenGLFunctions_3_3_Core static ShaderColorPerVertex* shader_cpv_; static ShaderBoldLine* shader_bl_; + bool current_aa_; + QOpenGLFunctions_3_3_Core* ogl33_; public: @@ -147,6 +150,22 @@ class CGOGN_RENDERING_API Drawer//: protected QOpenGLFunctions_3_3_Core current_size_ = ps; } + /** + * usr as glLineWidth + */ + inline void lineWidth(float lw) + { + current_aa_ = false; + current_size_ = lw; + } + + inline void lineWidthAA(float lw) + { + current_aa_ = true; + current_size_ = 2.0*lw; + } + + }; diff --git a/cgogn/rendering/examples/simple_viewer.cpp b/cgogn/rendering/examples/simple_viewer.cpp index b1ce9317..9b461d5a 100644 --- a/cgogn/rendering/examples/simple_viewer.cpp +++ b/cgogn/rendering/examples/simple_viewer.cpp @@ -40,6 +40,8 @@ #include #include #include +#include + #include @@ -83,7 +85,8 @@ class Viewer : public QOGLViewer cgogn::rendering::VBO* vbo_color_; - cgogn::rendering::ShaderSimpleColor* shader_vertex_edge_; + cgogn::rendering::ShaderSimpleColor* shader_vertex_; + cgogn::rendering::ShaderBoldLine* shader_edge_; cgogn::rendering::ShaderFlat* shader_flat_; cgogn::rendering::ShaderVectorPerVertex* shader_normal_; cgogn::rendering::ShaderPhong* shader_phong_; @@ -128,7 +131,7 @@ Viewer::~Viewer() delete vbo_pos_; delete vbo_norm_; delete vbo_color_; - delete shader_vertex_edge_; + delete shader_vertex_; delete shader_flat_; delete shader_normal_; delete shader_phong_; @@ -142,7 +145,7 @@ Viewer::Viewer() : render_(nullptr), vbo_pos_(nullptr), vbo_norm_(nullptr), - shader_vertex_edge_(nullptr), + shader_vertex_(nullptr), shader_flat_(nullptr), shader_normal_(nullptr), phong_rendering_(true), @@ -192,26 +195,6 @@ void Viewer::draw() camera()->getProjectionMatrix(proj); camera()->getModelViewMatrix(view); - shader_vertex_edge_->bind(); - shader_vertex_edge_->set_matrices(proj,view); - shader_vertex_edge_->bind_vao(0); - - if (vertices_rendering_) - { - glPointSize(3.0f); - shader_vertex_edge_->set_color(QColor(255,0,0)); - render_->draw(cgogn::rendering::POINTS); - } - - if (edge_rendering_) - { - shader_vertex_edge_->set_color(QColor(255,255,0)); - render_->draw(cgogn::rendering::LINES); - } - - shader_vertex_edge_->release_vao(0); - shader_vertex_edge_->release(); - glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(1.0f, 1.0f); @@ -234,6 +217,38 @@ void Viewer::draw() shader_phong_->release_vao(0); shader_phong_->release(); } + glDisable(GL_POLYGON_OFFSET_FILL); + + + if (vertices_rendering_) + { + shader_vertex_->bind(); + shader_vertex_->set_matrices(proj,view); + shader_vertex_->bind_vao(0); + + glPointSize(3.0f); + shader_vertex_->set_color(QColor(255,0,0)); + render_->draw(cgogn::rendering::POINTS); + + shader_vertex_->release_vao(0); + shader_vertex_->release(); + + } + + if (edge_rendering_) + { + shader_edge_->bind(); + shader_edge_->set_matrices(proj,view); + shader_edge_->bind_vao(0); + shader_edge_->set_width(2.5f); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + render_->draw(cgogn::rendering::LINES); + glDisable(GL_BLEND); + shader_edge_->release_vao(0); + shader_edge_->release(); + + } if (normal_rendering_) { @@ -273,9 +288,16 @@ void Viewer::init() render_->init_primitives(map_, cgogn::rendering::LINES, vertex_position_); render_->init_primitives(map_, cgogn::rendering::TRIANGLES, vertex_position_); - shader_vertex_edge_ = new cgogn::rendering::ShaderSimpleColor; - shader_vertex_edge_->add_vao(); - shader_vertex_edge_->set_vao(0, vbo_pos_); + shader_vertex_ = new cgogn::rendering::ShaderSimpleColor; + shader_vertex_->add_vao(); + shader_vertex_->set_vao(0, vbo_pos_); + + shader_edge_ = new cgogn::rendering::ShaderBoldLine() ; + shader_edge_->add_vao(); + shader_edge_->set_vao(0, vbo_pos_); + shader_edge_->bind(); + shader_edge_->set_color(QColor(255,255,0)); + shader_edge_->release(); shader_flat_ = new cgogn::rendering::ShaderFlat; shader_flat_->add_vao(); @@ -319,22 +341,33 @@ void Viewer::init() // drawer_->vertex3fv(bb_.min().data()); // fv work with float & double // drawer_->vertex3fv(bb_.max().data()); // drawer_->end(); + drawer_->lineWidth(2.0); drawer_->begin(GL_LINE_LOOP); - drawer_->color3f(1.0,1.0,1.0); + drawer_->color3f(1.0,0.0,0.0); drawer_->vertex3f(bb_.min()[0],bb_.min()[1],bb_.min()[2]); + drawer_->color3f(0.0,1.0,1.0); drawer_->vertex3f(bb_.max()[0],bb_.min()[1],bb_.min()[2]); + drawer_->color3f(1.0,0.0,1.0); drawer_->vertex3f(bb_.max()[0],bb_.max()[1],bb_.min()[2]); + drawer_->color3f(1.0,1.0,0.0); drawer_->vertex3f(bb_.min()[0],bb_.max()[1],bb_.min()[2]); drawer_->vertex3f(bb_.min()[0],bb_.max()[1],bb_.max()[2]); drawer_->vertex3f(bb_.max()[0],bb_.max()[1],bb_.max()[2]); drawer_->vertex3f(bb_.max()[0],bb_.min()[1],bb_.max()[2]); drawer_->vertex3f(bb_.min()[0],bb_.min()[1],bb_.max()[2]); drawer_->end(); +// drawer_->pointSize(10.0); + drawer_->lineWidthAA(1.2); drawer_->begin(GL_LINES); + drawer_->color3f(1.0,1.0,1.0); drawer_->vertex3f(bb_.min()[0],bb_.min()[1],bb_.min()[2]); drawer_->vertex3f(bb_.min()[0],bb_.max()[1],bb_.min()[2]); drawer_->vertex3f(bb_.min()[0],bb_.min()[1],bb_.max()[2]); drawer_->vertex3f(bb_.min()[0],bb_.max()[1],bb_.max()[2]); + drawer_->end(); + drawer_->lineWidthAA(2.0); + drawer_->begin(GL_LINES); + drawer_->color3f(0.0,1.0,0.0); drawer_->vertex3f(bb_.max()[0],bb_.min()[1],bb_.min()[2]); drawer_->vertex3f(bb_.max()[0],bb_.min()[1],bb_.max()[2]); drawer_->vertex3f(bb_.max()[0],bb_.max()[1],bb_.min()[2]); diff --git a/cgogn/rendering/shaders/shader_bold_line.h b/cgogn/rendering/shaders/shader_bold_line.h index a563cd23..95389328 100644 --- a/cgogn/rendering/shaders/shader_bold_line.h +++ b/cgogn/rendering/shaders/shader_bold_line.h @@ -65,7 +65,7 @@ class CGOGN_RENDERING_API ShaderBoldLine : public ShaderProgram void set_color(const QColor& rgb); /** - * @brief set the width of lines + * @brief set the width of lines (call before each draw) * @param w width in pixel */ void set_width(float w); From 0f96614c47b18b1d0f8ff6443743a3455f14b027 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Tue, 1 Mar 2016 14:04:20 +0100 Subject: [PATCH 222/402] Some documentation + complete the indexation checking --- cgogn/core/cmap/map_base.h | 14 +++++++-- cgogn/core/tests/cmap/cmap0_test.cpp | 37 ++++++++++++++++++++--- cgogn/core/tests/cmap/cmap0_topo_test.cpp | 36 +++++++++++++++++----- cgogn/core/tests/cmap/cmap1_test.cpp | 8 +++-- cgogn/core/tests/cmap/cmap1_topo_test.cpp | 8 ++--- 5 files changed, 82 insertions(+), 21 deletions(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index b8150811..7d7c17fb 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -430,6 +430,7 @@ class MapBase : public MapBaseData CellMarker marker(*cmap); bool result = true; + // Check that the indexation of cells is correct cmap->foreach_cell_until_dart_marking([&] (CellType c) { // insure that two cells do not share the same index @@ -446,7 +447,7 @@ class MapBase : public MapBaseData result = false; return false; } - // check all darts of the cell use the same index (and thus not equal to EMBNULL) + // check all darts of the cell use the same index (distinct to EMBNULL) cmap->foreach_dart_of_orbit_until(c, [&] (Dart d) { if (this->template get_embedding(d) != idx) @@ -455,8 +456,15 @@ class MapBase : public MapBaseData }); return result; - }); + // check that all cells present in the attribute handler are used + if (result) + cmap->foreach_cell_until([&] (CellType c) { + if (!marker.is_marked(c)) { + result = false; + return false; + } + }); return result; } @@ -465,6 +473,7 @@ class MapBase : public MapBaseData ConcreteMap* cmap = to_concrete(); bool result = true; + // check the integrity of topological relations or the correct sewing of darts foreach_dart_until( [&cmap,&result] (Dart d) { if (!cmap->check_integrity(d)) result = false; return result; @@ -474,6 +483,7 @@ class MapBase : public MapBaseData return false; } + // check the embedding indexation for the concrete map result = cmap->check_embedding_integrity(); if (!result) { std::cerr << "Integrity of the embeddings is broken" << std::endl; diff --git a/cgogn/core/tests/cmap/cmap0_test.cpp b/cgogn/core/tests/cmap/cmap0_test.cpp index d39f8f1a..0e7edc03 100644 --- a/cgogn/core/tests/cmap/cmap0_test.cpp +++ b/cgogn/core/tests/cmap/cmap0_test.cpp @@ -31,25 +31,42 @@ namespace cgogn #define NB_MAX 100 +/*! + * \brief The CMap0Test class implements tests on embedded CMap0 + * It contains a CMap0 to which a vertex attribute is added + * to enforce the indexation mecanism + */ class CMap0Test: public ::testing::Test { public: using testCMap0 = CMap0; + using VertexAttributeHandler = testCMap0::VertexAttributeHandler; using Vertex = testCMap0::Vertex; protected: testCMap0 cmap_; + VertexAttributeHandler vertices_; + /*! + * \brief Add a vertex attribute to the testing configuration + */ CMap0Test() { - cmap_.add_attribute("vertices"); + vertices_ = cmap_.add_attribute("vertices"); } + /*! + * \brief An array of darts on which the methods are tested. + */ std::array tdarts_; + /*! + * \brief Initialize the darts in tdarts_ + * \return The number of added darts or vertices + */ int addVertices() { for (int i = 0; i < NB_MAX; ++i) tdarts_[i] = cmap_.add_vertex(); @@ -58,21 +75,32 @@ class CMap0Test: public ::testing::Test } }; +/*! + * \brief An empty CMap0 contains no vertex (the attribute is used) + */ TEST_F(CMap0Test, testCMap0Constructor) { EXPECT_EQ(cmap_.nb_cells(), 0u); } +/*! + * \brief Adding vertices add one cell in the vertex attribute + * and the cell indexation is preserved + */ TEST_F(CMap0Test, testAddVertex) { for (int i = 1; i< NB_MAX; ++i) { - cmap_.add_vertex(); - EXPECT_EQ(cmap_.nb_darts(), i); + Dart d = cmap_.add_vertex(); + vertices_[d] = i; EXPECT_EQ(cmap_.nb_cells(), i); } EXPECT_TRUE(cmap_.check_map_integrity()); } +/*! + * \brief Removing vertices remove one cell in the vertex attribute + * and the cell indexation is preserved + */ TEST_F(CMap0Test, testRemoveVertex) { int n = addVertices(); @@ -80,10 +108,9 @@ TEST_F(CMap0Test, testRemoveVertex) int countVertices = n; for (int i = 0; i < n; ++i) { Vertex d = tdarts_[i]; - if (i%2 == 1) { + if (std::rand()%3 == 1) { cmap_.remove_vertex(Vertex(d)); --countVertices; - EXPECT_EQ(cmap_.nb_darts(), countVertices); EXPECT_EQ(cmap_.nb_cells(), countVertices); } } diff --git a/cgogn/core/tests/cmap/cmap0_topo_test.cpp b/cgogn/core/tests/cmap/cmap0_topo_test.cpp index 5054e649..3359971b 100644 --- a/cgogn/core/tests/cmap/cmap0_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap0_topo_test.cpp @@ -28,8 +28,12 @@ namespace cgogn { -#define NB_MAX 1000 +#define NB_MAX 100 +/*! + * \brief The CMap0TopoTest class implements topological tests on CMap0 + * It derives from CMap0 to allow the test of protected methods + */ class CMap0TopoTest: public ::testing::Test { @@ -44,27 +48,42 @@ class CMap0TopoTest: public ::testing::Test CMap0TopoTest() { + std::srand(static_cast(std::time(0))); } + /*! + * \brief An array of darts on which the methods are tested. + */ std::array tdarts_; - int addVertices() { - for (int i = 0; i < NB_MAX; ++i) + /*! + * \brief Initialize the darts in tdarts_ + * \return The number of added darts or vertices + */ + unsigned int addVertices() { + for (unsigned int i = 0; i < NB_MAX; ++i) tdarts_[i] = cmap_.add_vertex(); return NB_MAX; } }; +/*! + * \brief An empty CMap0 contains no dart and no vertex + */ TEST_F(CMap0TopoTest, testCMap0Constructor) { EXPECT_EQ(cmap_.nb_darts(), 0u); EXPECT_EQ(cmap_.nb_cells(), 0u); } +/*! + * \brief Adding vertices add one dart per vertex + * and the map integrity is preserved + */ TEST_F(CMap0TopoTest, testAddVertex) { - for (int i = 1; i< NB_MAX; ++i) { + for (unsigned int i = 1; i< NB_MAX; ++i) { cmap_.add_vertex(); EXPECT_EQ(cmap_.nb_darts(), i); EXPECT_EQ(cmap_.nb_cells(), i); @@ -72,6 +91,10 @@ TEST_F(CMap0TopoTest, testAddVertex) EXPECT_TRUE(cmap_.check_map_integrity()); } +/*! + * \brief Removing vertices remove one dart per vertex + * and the map integrity is preserved + */ TEST_F(CMap0TopoTest, testRemoveVertex) { int n = addVertices(); @@ -79,16 +102,13 @@ TEST_F(CMap0TopoTest, testRemoveVertex) int countVertices = n; for (int i = 0; i < n; ++i) { Vertex d = tdarts_[i]; - if (i%2 == 1) { + if (std::rand()%3 == 1) { cmap_.remove_vertex(Vertex(d)); --countVertices; EXPECT_EQ(cmap_.nb_darts(), countVertices); EXPECT_EQ(cmap_.nb_cells(), countVertices); } } - - EXPECT_EQ(cmap_.nb_darts(), countVertex); - EXPECT_EQ(cmap_.nb_cells(), countVertex); EXPECT_TRUE(cmap_.check_map_integrity()); } diff --git a/cgogn/core/tests/cmap/cmap1_test.cpp b/cgogn/core/tests/cmap/cmap1_test.cpp index b8d632fe..bc7697b9 100644 --- a/cgogn/core/tests/cmap/cmap1_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_test.cpp @@ -40,19 +40,23 @@ class CMap1Test: public ::testing::Test public: using testCMap1 = CMap1; + using VertexAttributeHandler = testCMap1::VertexAttributeHandler; using Vertex = testCMap1::Vertex; + using FaceAttributeHandler = testCMap1::FaceAttributeHandler; using Face = testCMap1::Face; protected: testCMap1 cmap_; + VertexAttributeHandler vertices_; + FaceAttributeHandler faces_; CMap1Test() { std::srand(static_cast(std::time(0))); - cmap_.add_attribute("vertices"); - cmap_.add_attribute("faces"); + vertices_ = cmap_.add_attribute("vertices"); + faces_ = cmap_.add_attribute("faces"); } int randomFaces() { diff --git a/cgogn/core/tests/cmap/cmap1_topo_test.cpp b/cgogn/core/tests/cmap/cmap1_topo_test.cpp index 264153d1..d8ee46d2 100644 --- a/cgogn/core/tests/cmap/cmap1_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_topo_test.cpp @@ -21,9 +21,6 @@ * * *******************************************************************************/ -#include -#include - #include #include @@ -33,6 +30,9 @@ namespace cgogn #define NB_MAX 1000 +/*! + * \brief The CMap1TopoTest class implements tests + */ class CMap1TopoTest: public CMap1, public ::testing::Test { @@ -44,7 +44,7 @@ class CMap1TopoTest: public CMap1, public ::testing::Test protected: /*! - * \brief An array of randomly genrated darts on which the methods are tested. + * \brief An array of randomly generated darts on which the methods are tested. */ std::array tdarts_; From 34b56cab4bdab6ca0bff1a09846ba41d7de43442 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Tue, 1 Mar 2016 15:28:13 +0100 Subject: [PATCH 223/402] rendering per face --- cgogn/rendering/examples/CMakeLists.txt | 2 + cgogn/rendering/map_render.h | 48 ++++++++++++++ cgogn/rendering/shaders/shader_flat.cpp | 82 ++++++++++++++++++++---- cgogn/rendering/shaders/shader_flat.h | 12 +++- cgogn/rendering/shaders/shader_phong.cpp | 7 +- cgogn/rendering/shaders/vbo.h | 60 ++++++++++++++++- 6 files changed, 186 insertions(+), 25 deletions(-) diff --git a/cgogn/rendering/examples/CMakeLists.txt b/cgogn/rendering/examples/CMakeLists.txt index 8e4a85d2..3e214ff2 100644 --- a/cgogn/rendering/examples/CMakeLists.txt +++ b/cgogn/rendering/examples/CMakeLists.txt @@ -15,6 +15,8 @@ add_definitions("-DCGOGN_TEST_MESHES_PATH=${CGOGN_TEST_MESHES_PATH}") add_executable(simple_viewer simple_viewer.cpp) target_link_libraries(simple_viewer cgogn_core cgogn_io cgogn_rendering QOGLViewer) +add_executable(viewer_per_face viewer_per_face.cpp) +target_link_libraries(viewer_per_face cgogn_core cgogn_io cgogn_rendering QOGLViewer) diff --git a/cgogn/rendering/map_render.h b/cgogn/rendering/map_render.h index 6db49967..97c5fc6b 100644 --- a/cgogn/rendering/map_render.h +++ b/cgogn/rendering/map_render.h @@ -171,6 +171,54 @@ class MapRender } }; + + +/** + * @brief create embedding indices of vertices and faces for arch vertx of each face + * @param m + * @param position vertex positions use for ear triangulation) + * @param indices1 embedding indices of vertices + * @param indices2 embedding indices of faces + */ +template +void create_indices_vertices_faces(MAP& m, const typename MAP::template VertexAttributeHandler& position, std::vector& indices1, std::vector& indices2) +{ + using Vertex = typename MAP::Vertex; + using Face = typename MAP::Face; + + indices1.reserve(m.nb_darts()); + indices2.reserve(m.nb_darts()); + indices1.clear(); + indices2.clear(); + std::vector local_vert_indices; + local_vert_indices.reserve(256); + + m.foreach_cell([&] (Face f) + { + unsigned int ef = m.get_embedding(Face(f.dart)); + if (m.has_degree(f,3)) + { + indices1.push_back(m.get_embedding(Vertex(f.dart))); + indices1.push_back(m.get_embedding(Vertex(m.phi1(f.dart)))); + indices1.push_back(m.get_embedding(Vertex(m.phi1(m.phi1(f.dart))))); + indices2.push_back(ef); + indices2.push_back(ef); + indices2.push_back(ef); + + } + else + { + cgogn::geometry::compute_ear_triangulation(m,f,position,local_vert_indices); + for (unsigned int i : local_vert_indices) + { + indices1.push_back(i); + indices2.push_back(ef); + } + } + }); +} + + } // namespace rendering } // namespace cgogn diff --git a/cgogn/rendering/shaders/shader_flat.cpp b/cgogn/rendering/shaders/shader_flat.cpp index 44d26c12..4c5a8acf 100644 --- a/cgogn/rendering/shaders/shader_flat.cpp +++ b/cgogn/rendering/shaders/shader_flat.cpp @@ -40,7 +40,7 @@ const char* ShaderFlat::vertex_shader_source_ = "in vec3 vertex_pos;\n" "uniform mat4 projection_matrix;\n" "uniform mat4 model_view_matrix;\n" - "out vec3 pos;" + "out vec3 pos;\n" "void main() {\n" " vec4 pos4 = model_view_matrix * vec4(vertex_pos,1.0);\n" " pos = pos4.xyz;" @@ -65,18 +65,64 @@ const char* ShaderFlat::fragment_shader_source_ = " fragColor = ambiant_color+lambert*back_color;\n" "}\n"; -ShaderFlat::ShaderFlat() + +const char* ShaderFlat::vertex_shader_source2_ = + "#version 150\n" + "in vec3 vertex_pos;\n" + "in vec3 vertex_col;\n" + "uniform mat4 projection_matrix;\n" + "uniform mat4 model_view_matrix;\n" + "out vec3 pos;\n" + "out vec3 col;\n" + "void main() {\n" + " vec4 pos4 = model_view_matrix * vec4(vertex_pos,1.0);\n" + " pos = pos4.xyz;\n" + " col = vertex_col;\n" + " gl_Position = projection_matrix * pos4;\n" + "}\n"; + +const char* ShaderFlat::fragment_shader_source2_ = + "#version 150\n" + "out vec4 fragColor;\n" + "uniform vec4 front_color;\n" + "uniform vec4 back_color;\n" + "uniform vec4 ambiant_color;\n" + "vec3 light_pos = vec3(100,100,1000);\n" + "in vec3 pos;\n" + "in vec3 col;\n" + "void main() {\n" + " vec3 N = normalize(cross(dFdx(pos),dFdy(pos)));\n" + " vec3 L = normalize(light_pos-pos);\n" + " float lambert = abs(dot(N,L));\n" + " fragColor = ambiant_color+vec4(lambert*col,1.0);\n" + "}\n"; + + +ShaderFlat::ShaderFlat(bool color_per_vertex) { - prg_.addShaderFromSourceCode(QOpenGLShader::Vertex, vertex_shader_source_); - prg_.addShaderFromSourceCode(QOpenGLShader::Fragment, fragment_shader_source_); - prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); - prg_.link(); + if (color_per_vertex) + { + prg_.addShaderFromSourceCode(QOpenGLShader::Vertex, vertex_shader_source2_); + prg_.addShaderFromSourceCode(QOpenGLShader::Fragment, fragment_shader_source2_); + prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); + prg_.bindAttributeLocation("vertex_col", ATTRIB_COLOR); + prg_.link(); + get_matrices_uniforms(); + unif_ambiant_color_ = prg_.uniformLocation("ambiant_color"); + } + else + { + prg_.addShaderFromSourceCode(QOpenGLShader::Vertex, vertex_shader_source_); + prg_.addShaderFromSourceCode(QOpenGLShader::Fragment, fragment_shader_source_); + prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); + prg_.link(); + get_matrices_uniforms(); + unif_front_color_ = prg_.uniformLocation("front_color"); + unif_back_color_ = prg_.uniformLocation("back_color"); + unif_ambiant_color_ = prg_.uniformLocation("ambiant_color"); - get_matrices_uniforms(); - unif_front_color_ = prg_.uniformLocation("front_color"); - unif_back_color_ = prg_.uniformLocation("back_color"); - unif_ambiant_color_ = prg_.uniformLocation("ambiant_color"); + } } void ShaderFlat::set_front_color(const QColor& rgb) @@ -94,7 +140,8 @@ void ShaderFlat::set_ambiant_color(const QColor& rgb) prg_.setUniformValue(unif_ambiant_color_,rgb); } -bool ShaderFlat::set_vao(unsigned int i, VBO* vbo_pos) + +bool ShaderFlat::set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color) { if (i >= vaos_.size()) { @@ -113,10 +160,19 @@ bool ShaderFlat::set_vao(unsigned int i, VBO* vbo_pos) ogl->glVertexAttribPointer(ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); vbo_pos->release(); - vaos_[i]->release(); + if (vbo_color) + { + // color vbo + vbo_color->bind(); + ogl->glEnableVertexAttribArray(ATTRIB_COLOR); + ogl->glVertexAttribPointer(ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_color->release(); + } + + vaos_[i]->release(); prg_.release(); - return true; + return true; } } // namespace rendering diff --git a/cgogn/rendering/shaders/shader_flat.h b/cgogn/rendering/shaders/shader_flat.h index cc8855ee..2c1856c2 100644 --- a/cgogn/rendering/shaders/shader_flat.h +++ b/cgogn/rendering/shaders/shader_flat.h @@ -41,9 +41,13 @@ class CGOGN_RENDERING_API ShaderFlat : public ShaderProgram static const char* vertex_shader_source_; static const char* fragment_shader_source_; + static const char* vertex_shader_source2_; + static const char* fragment_shader_source2_; + enum { - ATTRIB_POS = 0 + ATTRIB_POS = 0, + ATTRIB_COLOR }; // uniform ids @@ -53,7 +57,7 @@ class CGOGN_RENDERING_API ShaderFlat : public ShaderProgram public: - ShaderFlat(); + ShaderFlat(bool color_per_vertex = false); /** * @brief set current front color @@ -77,9 +81,11 @@ class CGOGN_RENDERING_API ShaderFlat : public ShaderProgram * @brief set a vao configuration * @param i id of vao (0,1,....) * @param vbo_pos pointer on position vbo (XYZ) + * @param vbo_color pointer on color vbo (RGB) * @return true if ok */ - bool set_vao(unsigned int i, VBO* vbo_pos); + bool set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_col = NULL); + }; } // namespace rendering diff --git a/cgogn/rendering/shaders/shader_phong.cpp b/cgogn/rendering/shaders/shader_phong.cpp index 41a30e23..5d8ee653 100644 --- a/cgogn/rendering/shaders/shader_phong.cpp +++ b/cgogn/rendering/shaders/shader_phong.cpp @@ -235,7 +235,7 @@ bool ShaderPhong::set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_norm, VBO* vbo_ ogl->glVertexAttribPointer(ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); vbo_pos->release(); - // position vbo + // normal vbo vbo_norm->bind(); ogl->glEnableVertexAttribArray(ATTRIB_NORM); ogl->glVertexAttribPointer(ATTRIB_NORM, vbo_norm->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); @@ -249,11 +249,6 @@ bool ShaderPhong::set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_norm, VBO* vbo_ ogl->glVertexAttribPointer(ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); vbo_color->release(); } - else - { - if (unif_front_color_<0) - std::cerr << "ShaderPhong: no color attribute, no color uniform"<< std::endl; - } vaos_[i]->release(); prg_.release(); diff --git a/cgogn/rendering/shaders/vbo.h b/cgogn/rendering/shaders/vbo.h index 2d5eb174..3c36afbe 100644 --- a/cgogn/rendering/shaders/vbo.h +++ b/cgogn/rendering/shaders/vbo.h @@ -122,10 +122,15 @@ class VBO /** * @brief dimension of vectors stored in buffer */ - inline int vector_dimension() + inline int vector_dimension() const { return vector_dimension_; } + + unsigned int size() const + { + return nb_vectors_; + } }; /** @@ -185,7 +190,7 @@ void update_vbo(const ATTR& attr, VBO& vbo) * @brief update vbo from one AttributeHandler with conversion lambda * @param attr AttributeHandler * @param vbo vbo to update - * @param convert conversion lambda + * @param convert conversion lambda -> float or std::array */ template void update_vbo(const ATTR& attr, VBO& vbo, const FUNC& convert) @@ -240,7 +245,7 @@ void update_vbo(const ATTR& attr, VBO& vbo, const FUNC& convert) * @param attr first AttributeHandler * @param attr2 second AttributeHandler * @param vbo vbo to update - * @param convert conversion lambda + * @param convert conversion lambda -> float or std::array */ template void update_vbo(const ATTR& attr, const ATTR2& attr2, VBO& vbo, const FUNC& convert) @@ -305,6 +310,55 @@ void update_vbo(const ATTR& attr, const ATTR2& attr2, VBO& vbo, const FUNC& conv +/** + * @brief generate a vbo from an attribute and it's indices + * @param attr the AttributeHandler + * @param indices indices in the AttributeHandler + * @param vbo the vbo to generate + * @param convert conversion lambda -> float or std::array + */ +template +void generate_vbo(const ATTR& attr, const std::vector& indices, VBO& vbo, const FUNC& convert) +{ + // check that convert has 1 param + static_assert(function_traits::arity == 1, "convert lambda function must have only one arg"); + + // check that convert param is compatible with attr + using InputConvert = typename std::remove_cv< typename std::remove_reference::template arg<0>::type>::type >::type; + static_assert(std::is_same::value, "wrong parameter 1"); + + // check that out of convert is float or std::array + using Vec2f = std::array; + using Vec3f = std::array; + using Vec4f = std::array; + static_assert(check_func_return_type(FUNC,float) || check_func_return_type(FUNC,Vec2f) || check_func_return_type(FUNC,Vec3f) ||check_func_return_type(FUNC,Vec4f), "convert output must be float or std::array" ); + + // set vec dimension + unsigned int vec_dim = 0; + if (check_func_return_type(FUNC,float) ) + vec_dim = 1; + else if (check_func_return_type(FUNC,Vec2f) ) + vec_dim = 2; + else if (check_func_return_type(FUNC,Vec3f) ) + vec_dim = 3; + else if (check_func_return_type(FUNC,Vec4f) ) + vec_dim = 4; + + // allocate vbo + vbo.allocate(indices.size(), vec_dim); + + // copy (after conversion) + using OutputConvert = typename function_traits::result_type; + OutputConvert* dst = reinterpret_cast(vbo.lock_pointer()); + + for (unsigned int i: indices) + *dst++ = convert(attr[i]); + + vbo.release_pointer(); +} + + + From 5519c86314a3a2c57508b0c06daad5bc93d205d6 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Tue, 1 Mar 2016 15:30:22 +0100 Subject: [PATCH 224/402] ... with all files --- cgogn/rendering/examples/viewer_per_face.cpp | 260 +++++++++++++++++++ 1 file changed, 260 insertions(+) create mode 100644 cgogn/rendering/examples/viewer_per_face.cpp diff --git a/cgogn/rendering/examples/viewer_per_face.cpp b/cgogn/rendering/examples/viewer_per_face.cpp new file mode 100644 index 00000000..ab0f5fe7 --- /dev/null +++ b/cgogn/rendering/examples/viewer_per_face.cpp @@ -0,0 +1,260 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#include +#include + +#include +#include + +#include + +#include + +#include +#include + +#include +//#include +#include +#include +#include + +#define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) + +using Map2 = cgogn::CMap2; +using Vec3 = Eigen::Vector3d; +//using Vec3 = cgogn::geometry::Vec_T>; + +template +using VertexAttributeHandler = Map2::VertexAttributeHandler; + +template +using FaceAttributeHandler = Map2::FaceAttributeHandler; + + +class Viewer : public QOGLViewer +{ +public: + Viewer(); + Viewer(const Viewer&) = delete; + Viewer& operator=(const Viewer&) = delete; + + virtual void draw(); + virtual void init(); + + virtual void keyPressEvent(QKeyEvent *); + void import(const std::string& surfaceMesh); + virtual ~Viewer(); + +private: + Map2 map_; + VertexAttributeHandler vertex_position_; + FaceAttributeHandler face_normal_; + + cgogn::geometry::BoundingBox bb_; + + cgogn::rendering::VBO* vbo_pos_; + cgogn::rendering::VBO* vbo_norm_; + cgogn::rendering::VBO* vbo_color_; + +// cgogn::rendering::ShaderSimpleColor* shader_color_; + cgogn::rendering::ShaderFlat* shader_flat_; + cgogn::rendering::ShaderPhong* shader_phong_; + + bool phong_rendering_; + bool flat_rendering_; +}; + + +// +// IMPLEMENTATION +// + + +void Viewer::import(const std::string& surfaceMesh) +{ + cgogn::io::import_surface(map_, surfaceMesh); + + vertex_position_ = map_.get_attribute("position"); + face_normal_ = map_.add_attribute("normal"); + + cgogn::geometry::compute_normal_faces(map_, vertex_position_, face_normal_); + cgogn::geometry::compute_bounding_box(vertex_position_, bb_); + + setSceneRadius(bb_.diag_size()/2.0); + Vec3 center = bb_.center(); + setSceneCenter(qoglviewer::Vec(center[0], center[1], center[2])); + showEntireScene(); +} + +Viewer::~Viewer() +{ + delete vbo_pos_; + delete vbo_norm_; + delete vbo_color_; + delete shader_phong_; +} + +Viewer::Viewer() : + map_(), + vertex_position_(), + face_normal_(), + bb_(), + vbo_pos_(nullptr), + vbo_color_(nullptr), + phong_rendering_(true), + flat_rendering_(false) +{} + +void Viewer::keyPressEvent(QKeyEvent *ev) +{ + switch (ev->key()) { + case Qt::Key_P: + phong_rendering_ = true; + flat_rendering_ = false; + break; + case Qt::Key_F: + flat_rendering_ = true; + phong_rendering_ = false; + break; + case Qt::Key_Escape: + exit(0); + break; + default: + break; + } + update(); +} + +void Viewer::draw() +{ + QMatrix4x4 proj; + QMatrix4x4 view; + camera()->getProjectionMatrix(proj); + camera()->getModelViewMatrix(view); + + + if (flat_rendering_) + { + shader_flat_->bind(); + shader_flat_->set_matrices(proj,view); + shader_flat_->bind_vao(0); + glDrawArrays(GL_TRIANGLES,0,vbo_pos_->size()); + shader_flat_->release_vao(0); + shader_flat_->release(); + } + + if (phong_rendering_) + { + shader_phong_->bind(); + shader_phong_->set_matrices(proj,view); + shader_phong_->bind_vao(0); + glDrawArrays(GL_TRIANGLES,0,vbo_pos_->size()); + shader_phong_->release_vao(0); + shader_phong_->release(); + } +} + +void Viewer::init() +{ + glClearColor(0.1,0.1,0.3,0.0); + + + vbo_pos_ = new cgogn::rendering::VBO(3); + vbo_norm_ = new cgogn::rendering::VBO(3); + vbo_color_ = new cgogn::rendering::VBO(3); + + // indices of vertices emb (f1_v1,f1_v2,f1_v3, f2_v1,f2_v2,f2_v3, f3_v1...) + std::vector ind_v; + // indices of faces emb (f1,f1,f1, f2,f2,f2, f3,f3,f3...) + std::vector ind_f; + + // create indices ( need to be done only after topo modifications + cgogn::rendering::create_indices_vertices_faces(map_,vertex_position_,ind_v,ind_f); + + // generate VBO: positions + cgogn::rendering::generate_vbo(vertex_position_, ind_v, *vbo_pos_, [] (const Vec3& v) -> std::array + { + return {float(v[0]), float(v[1]), float(v[2])}; + }); + + // generate VBO: normals + cgogn::rendering::generate_vbo(face_normal_, ind_f, *vbo_norm_, [] (const Vec3& n) -> std::array + { + return {float(n[0]), float(n[1]), float(n[2])}; + }); + + // generate VBO: colors (here abs of normals) + cgogn::rendering::generate_vbo(face_normal_, ind_f, *vbo_color_, [] (const Vec3& n) -> std::array + { + return {float(std::abs(n[0])), float(std::abs(n[1])), float(std::abs(n[2]))}; + }); + + + shader_phong_ = new cgogn::rendering::ShaderPhong(true); + shader_phong_->add_vao(); + shader_phong_->set_vao(0, vbo_pos_, vbo_norm_, vbo_color_); + shader_phong_->bind(); + shader_phong_->set_ambiant_color(QColor(5,5,5)); + shader_phong_->set_double_side(true); + shader_phong_->set_specular_color(QColor(255,255,255)); + shader_phong_->set_specular_coef(100.0); + shader_phong_->release(); + + + shader_flat_ = new cgogn::rendering::ShaderFlat(true); + shader_flat_->add_vao(); + shader_flat_->set_vao(0, vbo_pos_, vbo_color_); + shader_flat_->bind(); + shader_flat_->set_ambiant_color(QColor(5,5,5)); + shader_flat_->release(); + + + +} + +int main(int argc, char** argv) +{ + std::string surfaceMesh; + if (argc < 2) + { + std::cout << "USAGE: " << argv[0] << " [filename]" << std::endl; + surfaceMesh = std::string(DEFAULT_MESH_PATH) + std::string("aneurysm3D_1.off"); + std::cout << "Using default mesh : " << surfaceMesh << std::endl; + } + else + surfaceMesh = std::string(argv[1]); + + QApplication application(argc, argv); + qoglviewer::init_ogl_context(); + + // Instantiate the viewer. + Viewer viewer; + viewer.setWindowTitle("simpleViewer"); + viewer.import(surfaceMesh); + viewer.show(); + + // Run main loop. + return application.exec(); +} From 72967e08aa1b0dfeae0912df4eb6b8464f34810b Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Tue, 1 Mar 2016 17:07:05 +0100 Subject: [PATCH 225/402] fix bug of parallel_foreach_cell_topo_cache with very little meshes --- cgogn/core/cmap/map_base.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 6b81b3d4..cda3a2eb 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -1006,10 +1006,10 @@ class MapBase : public MapBaseData unsigned int nbc = PARALLEL_BUFFER_SIZE; // do block of PARALLEL_BUFFER_SIZE only if nb cells is huge else just divide - if ( (end - it) < 16*nb_threads_pool*PARALLEL_BUFFER_SIZE ) + if ( ((end - it) < 16*nb_threads_pool*PARALLEL_BUFFER_SIZE ) && ((end - it) > nb_threads_pool)) nbc = (end - it) / nb_threads_pool; - unsigned int local_end = it+nbc; + unsigned int local_end = std::min(it+nbc,end); const auto& cache = *(this->global_topo_cache_[ORBIT]); From 4d9244f5791ef0e0c49a111e50c814e12b87f8b2 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Wed, 2 Mar 2016 10:27:02 +0100 Subject: [PATCH 226/402] change BB contains(A,B) in intersects(A,B) --- cgogn/geometry/tests/types/bounding_box_test.cpp | 11 ++++++++--- cgogn/geometry/types/bounding_box.h | 6 +++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/cgogn/geometry/tests/types/bounding_box_test.cpp b/cgogn/geometry/tests/types/bounding_box_test.cpp index a114bf30..a0769e19 100644 --- a/cgogn/geometry/tests/types/bounding_box_test.cpp +++ b/cgogn/geometry/tests/types/bounding_box_test.cpp @@ -93,9 +93,14 @@ TYPED_TEST(BoundingBox_TEST, testing) EXPECT_TRUE(this->bb_.ray_intersect(TypeParam({ Scalar(-9), Scalar(-9), Scalar(-9) }), TypeParam({ Scalar(1), Scalar(1), Scalar(1) }))); EXPECT_FALSE(this->bb_.ray_intersect(TypeParam({ Scalar(-9), Scalar(-9), Scalar(-9) }), TypeParam({ Scalar(1), Scalar(-1), Scalar(0) }))); - EXPECT_TRUE(bb3.contains(TypeParam({ Scalar(0.2), Scalar(0.2), Scalar(0.2) }), TypeParam({ Scalar(0.5), Scalar(0.5), Scalar(0.5) }))); - EXPECT_FALSE(bb3.contains(TypeParam({ Scalar(-0.5), Scalar(-0.5), Scalar(-0.5) }), TypeParam({ Scalar(1.5), Scalar(0.5), Scalar(1.5) }))); - EXPECT_FALSE(bb3.contains(TypeParam({ Scalar(0.2), Scalar(0.2), Scalar(-0.2) }), TypeParam({ Scalar(1.5), Scalar(0.5), Scalar(1.5) }))); + EXPECT_TRUE(bb3.intersects(TypeParam({ Scalar(0.2), Scalar(0.2), Scalar(0.2) }), TypeParam({ Scalar(0.5), Scalar(0.5), Scalar(0.5) }))); + EXPECT_TRUE(bb3.intersects(TypeParam({ Scalar(-1.0), Scalar(-1.0), Scalar(-1.0) }), TypeParam({ Scalar(2.0), Scalar(2.2), Scalar(2.5) }))); + EXPECT_TRUE(bb3.intersects(TypeParam({ Scalar(0.5), Scalar(-0.2), Scalar(0.5) }), TypeParam({ Scalar(-0.2), Scalar(0.5), Scalar(0.5) }))); + + + EXPECT_FALSE(bb3.intersects(TypeParam({ Scalar(3.0), Scalar(2.5), Scalar(1.5) }), TypeParam({ Scalar(1.5), Scalar(2.5), Scalar(3.5) }))); + EXPECT_FALSE(bb3.intersects(TypeParam({ Scalar(0.5), Scalar(-0.6), Scalar(0.5) }), TypeParam({ Scalar(-0.6), Scalar(0.5), Scalar(0.5) }))); + } diff --git a/cgogn/geometry/types/bounding_box.h b/cgogn/geometry/types/bounding_box.h index 31b690f3..73f9df8f 100644 --- a/cgogn/geometry/types/bounding_box.h +++ b/cgogn/geometry/types/bounding_box.h @@ -230,8 +230,8 @@ class BoundingBox } - // return true if the segment belongs strictly to a bounding box - bool contains(const Vec& a, const Vec& b) const + // return true if the segment intersect the bounding box + bool intersects(const Vec& a, const Vec& b) const { cgogn_message_assert(initialized_, "Bounding box not initialized"); @@ -309,7 +309,7 @@ class BoundingBox } } - return (coord - b).dot(a - b); // intersection in segment ? + return (coord - b).dot(a - b) > 0.0; // intersection in segment ? } // return true if the bounding box belongs strictly to a bounding box From fe70f242bbaea86e39e895c47773499b837b1f51 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Wed, 2 Mar 2016 10:54:34 +0100 Subject: [PATCH 227/402] correct some typos --- cgogn/core/cmap/cmap0.h | 2 +- cgogn/core/cmap/cmap3.h | 6 +++--- cgogn/core/cmap/map_base.h | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index ce88cffa..ee9f8107 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -102,7 +102,7 @@ class CMap0_T : public MapBase { } - inline bool check_integrity(Dart d) const { + inline bool check_integrity(Dart /*d*/) const { return true; } /******************************************************************************* diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 0582bc97..d464f8ea 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -114,19 +114,19 @@ class CMap3_T : public CMap2_T if (this->template is_embedded()) result = result && this->template is_well_embedded(); - if (this->template is_embedded()) + if (this->template is_embedded()) result = result && this->template is_well_embedded(); if (this->template is_embedded()) result = result && this->template is_well_embedded(); - if (this->template is_embedded()) + if (this->template is_embedded()) result = result && this->template is_well_embedded(); if (this->template is_embedded()) result = result && this->template is_well_embedded(); - if (this->template is_embedded()) + if (this->template is_embedded()) result = result && this->template is_well_embedded(); if (this->template is_embedded()) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 7d7c17fb..0408a913 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -404,7 +404,7 @@ class MapBase : public MapBaseData result = false; std::map::iterator it; for (auto const& de : emb_set) - std::cout << "\t dart #" << de.second << " has embed index #" << de.first << std::endl; + std::cout << "\t dart #" << de.second << " has embed index #" << de.first << std::endl; std::cout << std::endl; } @@ -431,7 +431,7 @@ class MapBase : public MapBaseData bool result = true; // Check that the indexation of cells is correct - cmap->foreach_cell_until_dart_marking([&] (CellType c) + foreach_cell_until_dart_marking([&] (CellType c) { // insure that two cells do not share the same index if (marker.is_marked(c)) @@ -462,9 +462,9 @@ class MapBase : public MapBaseData cmap->foreach_cell_until([&] (CellType c) { if (!marker.is_marked(c)) { result = false; - return false; } - }); + return result; + }); return result; } From 80b6352203c99c71d22cb6564b293ce513f12a84 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Wed, 2 Mar 2016 12:49:17 +0100 Subject: [PATCH 228/402] Write some documentation for tests --- cgogn/core/cmap/map_base.h | 7 +- cgogn/core/tests/cmap/cmap0_topo_test.cpp | 5 +- cgogn/core/tests/cmap/cmap1_topo_test.cpp | 152 ++++++++++++++-------- 3 files changed, 104 insertions(+), 60 deletions(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 0408a913..a7b044f6 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -450,8 +450,7 @@ class MapBase : public MapBaseData // check all darts of the cell use the same index (distinct to EMBNULL) cmap->foreach_dart_of_orbit_until(c, [&] (Dart d) { - if (this->template get_embedding(d) != idx) - result = false; + if (this->template get_embedding(d) != idx) result = false; return result; }); @@ -460,9 +459,7 @@ class MapBase : public MapBaseData // check that all cells present in the attribute handler are used if (result) cmap->foreach_cell_until([&] (CellType c) { - if (!marker.is_marked(c)) { - result = false; - } + if (!marker.is_marked(c)) result = false; return result; }); return result; diff --git a/cgogn/core/tests/cmap/cmap0_topo_test.cpp b/cgogn/core/tests/cmap/cmap0_topo_test.cpp index 3359971b..c4089228 100644 --- a/cgogn/core/tests/cmap/cmap0_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap0_topo_test.cpp @@ -32,7 +32,6 @@ namespace cgogn /*! * \brief The CMap0TopoTest class implements topological tests on CMap0 - * It derives from CMap0 to allow the test of protected methods */ class CMap0TopoTest: public ::testing::Test { @@ -78,7 +77,7 @@ TEST_F(CMap0TopoTest, testCMap0Constructor) } /*! - * \brief Adding vertices add one dart per vertex + * \brief Adding vertices adds one dart per vertex * and the map integrity is preserved */ TEST_F(CMap0TopoTest, testAddVertex) @@ -103,7 +102,7 @@ TEST_F(CMap0TopoTest, testRemoveVertex) for (int i = 0; i < n; ++i) { Vertex d = tdarts_[i]; if (std::rand()%3 == 1) { - cmap_.remove_vertex(Vertex(d)); + cmap_.remove_vertex(d); --countVertices; EXPECT_EQ(cmap_.nb_darts(), countVertices); EXPECT_EQ(cmap_.nb_cells(), countVertices); diff --git a/cgogn/core/tests/cmap/cmap1_topo_test.cpp b/cgogn/core/tests/cmap/cmap1_topo_test.cpp index d8ee46d2..a367551c 100644 --- a/cgogn/core/tests/cmap/cmap1_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_topo_test.cpp @@ -31,9 +31,10 @@ namespace cgogn #define NB_MAX 1000 /*! - * \brief The CMap1TopoTest class implements tests - */ -class CMap1TopoTest: public CMap1, public ::testing::Test +* \brief The CMap1TopoTest class implements topological tests on CMap1 +* It derives from CMap1 to allow the test of protected methods +*/ +class CMap1TopoTest : public CMap1, public ::testing::Test { public: @@ -44,30 +45,36 @@ class CMap1TopoTest: public CMap1, public ::testing::Test protected: /*! - * \brief An array of randomly generated darts on which the methods are tested. + * \brief An array of darts on which the methods are tested. */ std::array tdarts_; - /*! - * \brief Generate a random set of faces. - */ CMap1TopoTest() { std::srand(static_cast(std::time(0))); } - int randomDarts() { - int n = 1 + std::rand() % (NB_MAX-1); - for (int i = 0; i < n; ++i) + /*! + * \brief Initialize the darts in tdarts_ + * \return The number of added darts or vertices + */ + unsigned int addVertices() { + for (unsigned int i = 0; i < NB_MAX; ++i) tdarts_[i] = add_dart(); - return n; + return NB_MAX; } - int randomFaces() { - int count = 0; - for (int i = 0; i < NB_MAX; ++i) { - int n = 1 + std::rand() % 100; + /*! + * \brief Generate a random set of faces and put them in tdarts_ + * \return The number of added darts or vertices in all faces. + * The face size ranges from 1 to 100. + * A random dart of each face is put in the tdarts_ array. + */ + unsigned int addFaces() { + unsigned int count = 0; + for (unsigned int i = 0; i < NB_MAX; ++i) { + unsigned int n = 1 + std::rand() % 100; Dart d = add_face_topo(n); count += n; @@ -80,6 +87,9 @@ class CMap1TopoTest: public CMap1, public ::testing::Test } }; +/*! + * \brief An empty CMap1 contains no dart, no vertex and no face. + */ TEST_F(CMap1TopoTest, testCMap1Constructor) { EXPECT_EQ(nb_darts(), 0u); @@ -87,35 +97,54 @@ TEST_F(CMap1TopoTest, testCMap1Constructor) EXPECT_EQ(this->template nb_cells(), 0u); } +/*! + * \brief Adding darts adds one vertex and one face per dart. + * The test adds NB_MAX darts. + * The number of cells correctly increases and the map integrity is preserved. + */ TEST_F(CMap1TopoTest, testAddDart) { - int n = randomDarts(); - - EXPECT_EQ(nb_darts(), n); + for (unsigned int i = 1; i< NB_MAX; ++i) { + add_dart(); + EXPECT_EQ(nb_darts(), i); + EXPECT_EQ(nb_cells(), i); + EXPECT_EQ(nb_cells(), i); + } EXPECT_TRUE(check_map_integrity()); } -TEST_F(CMap1TopoTest, testDeleteDart) +/*! + * \brief Removing unsewn darts removes one vertex and on face per dart. + * The test randomly removes 1/3 of the initial vertices. + * The number of cells correctly decreases and the map integrity is preserved. + */ +TEST_F(CMap1TopoTest, testRemoveDart) { - int n = randomDarts(); + unsigned int n = addVertices(); - int count = n; - for (int i = 0; i < n; ++i) { + unsigned int count = n; + for (unsigned int i = 0; i < n; ++i) { if (std::rand() % 3 == 1) { remove_dart(tdarts_[i]); --count; + EXPECT_EQ(nb_darts(), count); + EXPECT_EQ(nb_cells(), count); + EXPECT_EQ(nb_cells(), count); } } - - EXPECT_EQ(nb_darts(), count); EXPECT_TRUE(check_map_integrity()); } +/*! + * \brief Sewing and unsewing darts correctly changes the topological relations. + * The test perfoms NB_MAX sewing and unsewing on randomly chosen dart of tdarts_. + * The number of vertices is unchanged and the map integrity is preserved. + */ TEST_F(CMap1TopoTest, testPhi1SewUnSew) { - int n = randomDarts(); + unsigned int n = addVertices(); - for (int i = 0; i < 1000; ++i) { + for (unsigned int i = 0; i < NB_MAX; ++i) { Dart d = tdarts_[std::rand() % n]; Dart e = tdarts_[std::rand() % n]; Dart f = tdarts_[std::rand() % n]; @@ -132,83 +161,102 @@ TEST_F(CMap1TopoTest, testPhi1SewUnSew) } EXPECT_EQ(nb_darts(), n); + EXPECT_EQ(nb_cells(), n); EXPECT_TRUE(check_map_integrity()); } +/*! + * \brief Adding a face of size n adds n darts, n vertices and 1 face. + * The test performs NB_MAX additions of randomly sized faces. + * The number of generated cells is correct and the map integrity is preserved. + */ TEST_F(CMap1TopoTest, testAddFace) { - int n = randomFaces(); - - EXPECT_EQ(this->template nb_cells(), n); - EXPECT_EQ(this->template nb_cells(), NB_MAX); + unsigned int count = 0; + + for (unsigned int i = 0; i < NB_MAX; ++i) { + unsigned int n = 1 + std::rand() % 100; + Dart d = add_face_topo(n); + count += n; + EXPECT_EQ(nb_darts(), count); + EXPECT_EQ(nb_cells(), count); + EXPECT_EQ(nb_cells(), i+1); + } EXPECT_TRUE(check_map_integrity()); } +/*! \brief Spliting a vertex increases the size of its face. + * The test performs NB_MAX vertex spliting on vertices of randomly generated faces. + * The number of generated cells is correct and the map integrity is preserved. + */ TEST_F(CMap1TopoTest, testSplitVertex) { - int n = randomFaces(); + unsigned int n = addFaces(); - for (int i = 0; i < NB_MAX; ++i) { + for (unsigned int i = 0; i < NB_MAX; ++i) { Face d = tdarts_[i]; unsigned int k = degree(Face(d)); split_vertex_topo(d); EXPECT_EQ(degree(Face(d)), k+1); + EXPECT_EQ(nb_cells(), n+i+1); + EXPECT_EQ(nb_cells(), NB_MAX); } - - EXPECT_EQ(this->template nb_cells(), n+NB_MAX); - EXPECT_EQ(this->template nb_cells(), NB_MAX); EXPECT_TRUE(check_map_integrity()); } +/*! \brief Removing a vertex decreases the size of its face and removes the face if its size is 1. +* The test performs NB_MAX vertex spliting on vertices of randomly generated faces. +* The number of generated cells is correct and the map integrity is preserved. +*/ TEST_F(CMap1TopoTest, testRemoveVertex) { - int n = randomFaces(); + unsigned int n = addFaces(); - int countVertex = n; - int countFace = NB_MAX; - for (int i = 0; i < NB_MAX; ++i) { + unsigned int countVertices = n; + unsigned int countFaces = NB_MAX; + for (unsigned int i = 0; i < NB_MAX; ++i) { Face d = tdarts_[i]; unsigned int k = degree(Face(d)); if (k > 1) { Dart e = phi1(d); remove_vertex(Vertex(d)); - --countVertex; + --countVertices; EXPECT_EQ(degree(Face(e)), k-1); } else { remove_vertex(Vertex(d)); - --countFace; - --countVertex; + --countFaces; + --countVertices; } } - EXPECT_EQ(this->template nb_cells(), countVertex); - EXPECT_EQ(this->template nb_cells(), countFace); + EXPECT_EQ(this->template nb_cells(), countVertices); + EXPECT_EQ(this->template nb_cells(), countFaces); EXPECT_TRUE(check_map_integrity()); } TEST_F(CMap1TopoTest, testRemoveFace) { - int n = randomFaces(); + int n = addFaces(); - int countVertex = n; - int countFace = NB_MAX; + int countVertices = n; + int countFaces = NB_MAX; for (int i = 0; i < NB_MAX; ++i) { Face d = tdarts_[i]; unsigned int k = degree(Face(d)); remove_face(d); - countVertex -= k; - --countFace; + countVertices -= k; + --countFaces; } - EXPECT_EQ(this->template nb_cells(), countVertex); - EXPECT_EQ(this->template nb_cells(), countFace); + EXPECT_EQ(this->template nb_cells(), countVertices); + EXPECT_EQ(this->template nb_cells(), countFaces); EXPECT_TRUE(check_map_integrity()); } TEST_F(CMap1TopoTest, testReverseFace) { - int n = randomFaces(); + int n = addFaces(); for (int i = 0; i < NB_MAX; ++i) { Face f = tdarts_[i]; From 5ad73048eb6f763dbff8455d485c9fef7c441af8 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Wed, 2 Mar 2016 14:40:42 +0100 Subject: [PATCH 229/402] remove BB wrong function --- .../tests/types/bounding_box_test.cpp | 9 -- cgogn/geometry/types/bounding_box.h | 82 ------------------- 2 files changed, 91 deletions(-) diff --git a/cgogn/geometry/tests/types/bounding_box_test.cpp b/cgogn/geometry/tests/types/bounding_box_test.cpp index a0769e19..226af15d 100644 --- a/cgogn/geometry/tests/types/bounding_box_test.cpp +++ b/cgogn/geometry/tests/types/bounding_box_test.cpp @@ -93,14 +93,5 @@ TYPED_TEST(BoundingBox_TEST, testing) EXPECT_TRUE(this->bb_.ray_intersect(TypeParam({ Scalar(-9), Scalar(-9), Scalar(-9) }), TypeParam({ Scalar(1), Scalar(1), Scalar(1) }))); EXPECT_FALSE(this->bb_.ray_intersect(TypeParam({ Scalar(-9), Scalar(-9), Scalar(-9) }), TypeParam({ Scalar(1), Scalar(-1), Scalar(0) }))); - EXPECT_TRUE(bb3.intersects(TypeParam({ Scalar(0.2), Scalar(0.2), Scalar(0.2) }), TypeParam({ Scalar(0.5), Scalar(0.5), Scalar(0.5) }))); - EXPECT_TRUE(bb3.intersects(TypeParam({ Scalar(-1.0), Scalar(-1.0), Scalar(-1.0) }), TypeParam({ Scalar(2.0), Scalar(2.2), Scalar(2.5) }))); - EXPECT_TRUE(bb3.intersects(TypeParam({ Scalar(0.5), Scalar(-0.2), Scalar(0.5) }), TypeParam({ Scalar(-0.2), Scalar(0.5), Scalar(0.5) }))); - - - EXPECT_FALSE(bb3.intersects(TypeParam({ Scalar(3.0), Scalar(2.5), Scalar(1.5) }), TypeParam({ Scalar(1.5), Scalar(2.5), Scalar(3.5) }))); - EXPECT_FALSE(bb3.intersects(TypeParam({ Scalar(0.5), Scalar(-0.6), Scalar(0.5) }), TypeParam({ Scalar(-0.6), Scalar(0.5), Scalar(0.5) }))); - - } diff --git a/cgogn/geometry/types/bounding_box.h b/cgogn/geometry/types/bounding_box.h index 73f9df8f..3b4ab475 100644 --- a/cgogn/geometry/types/bounding_box.h +++ b/cgogn/geometry/types/bounding_box.h @@ -230,88 +230,6 @@ class BoundingBox } - // return true if the segment intersect the bounding box - bool intersects(const Vec& a, const Vec& b) const - { - cgogn_message_assert(initialized_, "Bounding box not initialized"); - - #define LEFT 'l' - #define RIGHT 'r' - #define MIDDLE 'm' - - // Algorithm from Graphic Gems - // modified to test segment - Vec dir(b - a); // ray - - bool inside = true; -// std::vector quadrant(p_min_.dimension()); - char quadrant[dim_]; - - Vec candidatePlane; - - // Find candidate planes; this loop can be avoided if - // rays cast all from the eye(assume perpsective view) - for (unsigned int i = 0; i < dim_; i++) - { - if (a[i] < p_min_[i]) - { - quadrant[i] = LEFT; - candidatePlane[i] = p_min_[i]; - inside = false; - } - else if (a[i] > p_max_[i]) - { - quadrant[i] = RIGHT; - candidatePlane[i] = p_max_[i]; - inside = false; - } - else - quadrant[i] = MIDDLE; - } - - // Ray origin inside bounding box - if (inside) - return true; - - Vec maxT; - Vec coord; /* hit point */ - /* Calculate T distances to candidate planes */ - for(unsigned int i = 0u; i < dim_; i++) - { - if (quadrant[i] != MIDDLE && dir[i] != 0) - maxT[i] = (candidatePlane[i] - a[i]) / dir[i]; - else - maxT[i] = -1; - } - - #undef LEFT - #undef RIGHT - #undef MIDDLE - - // Get largest of the maxT's for final choice of intersection - unsigned int whichPlane = 0u; - for(unsigned int i = 1u; i < dim_; i++) - if (maxT[whichPlane] < maxT[i]) - whichPlane = i; - - /* Check final candidate actually inside box */ - if (maxT[whichPlane] < 0.) - return false; - for (unsigned int i = 0u; i < dim_; i++) - { - if (whichPlane != i) - { - coord[i] = a[i] + maxT[whichPlane] * dir[i]; - if (coord[i] < p_min_[i] || coord[i] > p_max_[i]) - return false; - else - coord[i] = candidatePlane[i]; - } - } - - return (coord - b).dot(a - b) > 0.0; // intersection in segment ? - } - // return true if the bounding box belongs strictly to a bounding box bool contains(const BoundingBox& bb) const { From f1518af23844b592a3bccf2290ec74ea965a6c1f Mon Sep 17 00:00:00 2001 From: David Cazier Date: Wed, 2 Mar 2016 14:46:16 +0100 Subject: [PATCH 230/402] is_well_embedded() + code style --- cgogn/core/cmap/map_base.h | 33 ++++++++++++++----- .../libQGLViewer/QOGLViewer/CMakeLists.txt | 2 +- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index a7b044f6..ffd612fa 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -427,19 +427,27 @@ class MapBase : public MapBaseData cgogn_message_assert(this->template is_embedded(), "Invalid parameter: orbit not embedded"); const ConcreteMap* cmap = to_concrete(); - CellMarker marker(*cmap); + AttributeHandler marker = add_attribute("__tmp_marker"); bool result = true; + const Self* const_map = static_cast(this); + const typename Inherit::template ChunkArrayContainer& container = + const_map->template get_attribute_container(); + + // a marker is initialized to false for each "used" index of the container + for (unsigned int i = container.begin(), end = container.end(); i != end; container.next(i)) + marker[i] = 0; + // Check that the indexation of cells is correct foreach_cell_until_dart_marking([&] (CellType c) { // insure that two cells do not share the same index - if (marker.is_marked(c)) + if (marker[this->template get_embedding(c.dart)] > 0) { result = false; return false; } - marker.mark(c); + marker[this->template get_embedding(c.dart)] = 1; // check used indices are valid unsigned int idx = this->get_embedding(c); if (idx == EMBNULL) @@ -458,10 +466,15 @@ class MapBase : public MapBaseData }); // check that all cells present in the attribute handler are used if (result) - cmap->foreach_cell_until([&] (CellType c) { - if (!marker.is_marked(c)) result = false; - return result; - }); + { + for (unsigned int i = container.begin(), end = container.end(); i != end; container.next(i)) + { + if (marker[i] == 0) { + result = false; + break; + } + } + } return result; } @@ -475,14 +488,16 @@ class MapBase : public MapBaseData if (!cmap->check_integrity(d)) result = false; return result; }); - if (!result) { + if (!result) + { std::cerr << "Integrity of the topology is broken" << std::endl; return false; } // check the embedding indexation for the concrete map result = cmap->check_embedding_integrity(); - if (!result) { + if (!result) + { std::cerr << "Integrity of the embeddings is broken" << std::endl; return false; } diff --git a/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt b/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt index 64f3c40e..3a439b5a 100644 --- a/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt +++ b/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt @@ -3,7 +3,7 @@ set(CGOGN_THIRDPARTY_QOGLVIEWER_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE PROJECT(QOGLViewer) FIND_PACKAGE(OpenGL REQUIRED) -find_package(Qt5Widgets 5.4.0 REQUIRED) +find_package(Qt5Widgets 5.3.2 REQUIRED) set(CMAKE_AUTOMOC ON) From a0e50058a47d735344c6c6cde453d29faee6e8e0 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Wed, 2 Mar 2016 16:06:15 +0100 Subject: [PATCH 231/402] vbo update --- cgogn/rendering/map_render.h | 2 ++ cgogn/rendering/shaders/vbo.h | 21 +++++++++------------ 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/cgogn/rendering/map_render.h b/cgogn/rendering/map_render.h index 97c5fc6b..40f11356 100644 --- a/cgogn/rendering/map_render.h +++ b/cgogn/rendering/map_render.h @@ -190,6 +190,8 @@ void create_indices_vertices_faces(MAP& m, const typename MAP::template VertexAt indices2.reserve(m.nb_darts()); indices1.clear(); indices2.clear(); + + //local vector for ear triangulation std::vector local_vert_indices; local_vert_indices.reserve(256); diff --git a/cgogn/rendering/shaders/vbo.h b/cgogn/rendering/shaders/vbo.h index 3c36afbe..18019122 100644 --- a/cgogn/rendering/shaders/vbo.h +++ b/cgogn/rendering/shaders/vbo.h @@ -149,25 +149,23 @@ void update_vbo(const ATTR& attr, VBO& vbo) std::vector chunk_addr; unsigned int byte_chunk_size; unsigned int nb_chunks = ca->get_chunks_pointers(chunk_addr, byte_chunk_size); - unsigned int vec_dim = geometry::vector_traits::SIZE; + const unsigned int vec_dim = geometry::vector_traits::SIZE; vbo.allocate(nb_chunks * ATTR::CHUNKSIZE, vec_dim); + const unsigned int vbo_blk_bytes = ATTR::CHUNKSIZE * vec_dim * sizeof(float); + if (std::is_same::Scalar, float>::value) { // copy - char* dst = reinterpret_cast(vbo.lock_pointer()); + vbo.bind(); for (unsigned int i = 0; i < nb_chunks; ++i) - { - memcpy(dst, chunk_addr[i], byte_chunk_size); - dst += byte_chunk_size; - } - vbo.release_pointer(); + vbo.copy_data(i* vbo_blk_bytes, vbo_blk_bytes, chunk_addr[i]); + vbo.release(); } else if (std::is_same::Scalar, double>::value) { // copy (after conversion to float) - char* dst = reinterpret_cast(vbo.lock_pointer()); float* float_buffer = new float[ATTR::CHUNKSIZE * vec_dim]; for (unsigned int i = 0; i < nb_chunks; ++i) { @@ -176,11 +174,10 @@ void update_vbo(const ATTR& attr, VBO& vbo) double* src = reinterpret_cast(chunk_addr[i]); for (unsigned int j = 0; j < ATTR::CHUNKSIZE * vec_dim; ++j) *fit++ = *src++; - // copy - memcpy(dst, float_buffer, ATTR::CHUNKSIZE * vec_dim * sizeof(float)); - dst += ATTR::CHUNKSIZE * vec_dim * sizeof(float); + vbo.bind(); + vbo.copy_data(i* ATTR::CHUNKSIZE * vec_dim * sizeof(float), ATTR::CHUNKSIZE * vec_dim * sizeof(float),float_buffer); + vbo.release(); } - vbo.release_pointer(); delete[] float_buffer; } } From 5acc76bc3b5ddce0066918a16bdb80169dc03cbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 2 Mar 2016 16:26:31 +0100 Subject: [PATCH 232/402] do {...} while(false) macro hack MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/utils/assert.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/cgogn/core/utils/assert.h b/cgogn/core/utils/assert.h index 2e61394d..20983b69 100644 --- a/cgogn/core/utils/assert.h +++ b/cgogn/core/utils/assert.h @@ -87,12 +87,12 @@ CGOGN_UTILS_API CGOGN_NORETURN void should_not_have_reached( * \see assertion_failed() */ #define _internal_cgogn_assert(x) \ -{ \ +do { \ if(!(x)) \ { \ cgogn::assertion_failed(#x, "", __FILE__, __func__, __LINE__); \ } \ -} +} while (false) /** * \brief Verifies that a condition is met and take a specific message. @@ -102,12 +102,12 @@ CGOGN_UTILS_API CGOGN_NORETURN void should_not_have_reached( * \see assertion_failed() */ #define _internal_cgogn_message_assert(x, msg) \ -{ \ +do { \ if(!(x)) \ { \ cgogn::assertion_failed(#x, msg, __FILE__, __func__, __LINE__); \ } \ -} +} while (false) /** * \brief Sets a non reachable point in the program @@ -115,9 +115,9 @@ CGOGN_UTILS_API CGOGN_NORETURN void should_not_have_reached( * \param[in] msg the specific information message */ #define _internal_cgogn_assert_not_reached(msg) \ -{ \ +do { \ cgogn::should_not_have_reached(msg, __FILE__, __func__, __LINE__);\ -} +} while (false) /** * \brief Verifies that the required contract condition is met. @@ -127,12 +127,12 @@ CGOGN_UTILS_API CGOGN_NORETURN void should_not_have_reached( * \see assertion_failed() */ #define _internal_cgogn_require(x) \ -{ \ +do { \ if(!(x)) \ { \ cgogn::assertion_failed(#x, "", __FILE__, __func__, __LINE__); \ } \ -} +} while (false) /** * \brief Verifies that the ensured contract condition is met. @@ -142,12 +142,12 @@ CGOGN_UTILS_API CGOGN_NORETURN void should_not_have_reached( * \see assertion_failed() */ #define _internal_cgogn_ensure(x) \ -{ \ +do { \ if(!(x)) \ { \ cgogn::assertion_failed(#x, "", __FILE__, __func__, __LINE__); \ } \ -} +} while (false) /** * \brief Verifies that the invariant contract condition is met. @@ -157,12 +157,12 @@ CGOGN_UTILS_API CGOGN_NORETURN void should_not_have_reached( * \see assertion_failed() */ #define _internal_cgogn_invariant(x) \ -{ \ +do { \ if(!(x)) \ { \ cgogn::assertion_failed(#x, "", __FILE__, __func__, __LINE__); \ } \ -} +} while (false) /** * \def cgogn_assert(x) From ff6a5b4f35a0c552766b6b4dacd2795e9285e96d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 2 Mar 2016 16:27:45 +0100 Subject: [PATCH 233/402] some work on reading files (mostly used for loading vtk legacy files for the moment, see polydata.vtk file) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/geometry/types/geometry_traits.h | 26 +- cgogn/io/CMakeLists.txt | 2 + cgogn/io/data_io.h | 241 +++++++++++++++ cgogn/io/io_utils.h | 76 +++++ cgogn/io/surface_import.h | 391 +++++++++++-------------- cgogn/io/vtk_cell_types.h | 33 +++ data/meshes/polydata.vtk | 61 ++++ 7 files changed, 606 insertions(+), 224 deletions(-) create mode 100644 cgogn/io/data_io.h create mode 100644 cgogn/io/io_utils.h create mode 100644 data/meshes/polydata.vtk diff --git a/cgogn/geometry/types/geometry_traits.h b/cgogn/geometry/types/geometry_traits.h index 4a080d40..7f5f1d7c 100644 --- a/cgogn/geometry/types/geometry_traits.h +++ b/cgogn/geometry/types/geometry_traits.h @@ -24,6 +24,7 @@ #ifndef GEOMETRY_TYPES_GEOMETRY_TRAITS_H_ #define GEOMETRY_TYPES_GEOMETRY_TRAITS_H_ +#include #include #include @@ -37,8 +38,7 @@ namespace geometry template struct vector_traits -{ -}; +{}; // specialization 1 : cgogn::geometry::Vec_T with a fixed-size array template @@ -56,6 +56,28 @@ struct vector_traits> using Scalar = Scalar_; }; +template +struct nb_components_traits +{}; + +template +struct nb_components_traits::value || std::is_floating_point::value >::type > +{ + const static unsigned int value = 1u; +}; + +template +struct nb_components_traits>> +{ + const static unsigned int value = size; +}; + +template +struct nb_components_traits> +{ + const static unsigned int value = Rows; +}; + } // namespace geometry } // namespace cgogn diff --git a/cgogn/io/CMakeLists.txt b/cgogn/io/CMakeLists.txt index 8a8cc6d2..36d2e3cc 100644 --- a/cgogn/io/CMakeLists.txt +++ b/cgogn/io/CMakeLists.txt @@ -9,6 +9,8 @@ set(HEADER_FILES map_export.h import_ply_data.h vtk_cell_types.h + io_utils.h + data_io.h dll.h ) diff --git a/cgogn/io/data_io.h b/cgogn/io/data_io.h new file mode 100644 index 00000000..eb35654c --- /dev/null +++ b/cgogn/io/data_io.h @@ -0,0 +1,241 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef IO_DATA_IO_H_ +#define IO_DATA_IO_H_ + +#include +#include + +#include +#include + +#include + +namespace cgogn +{ + +namespace io +{ + +/** + * @brief The BaseDataIO class : used to read numerical values (scalar & vectors) in mesh files + */ +template +class DataIOGen +{ +public: + using ChunkArrayGen = cgogn::ChunkArrayGen; + using ChunkArrayContainer = typename MAP::template ChunkArrayContainer; + + virtual void read_n(std::ifstream& fp, std::size_t n, bool binary, bool big_endian) = 0; + virtual void* get_data() = 0; + + virtual void to_chunk_array(ChunkArrayGen* ca_gen) const = 0; + virtual ChunkArrayGen* add_attribute(ChunkArrayContainer& cac, const std::string& att_name) = 0; + + virtual unsigned int nb_components() const = 0; + virtual ~DataIOGen() {} + + inline static std::unique_ptr newDataIO(const std::string type_name); + inline static std::unique_ptr newDataIO(const std::string type_name, unsigned int nb_components); +}; + + +template +class DataIO : public DataIOGen +{ +public: + using Inherit = DataIOGen; + using Self = DataIO; + using ChunkArrayGen = typename Inherit::ChunkArrayGen; + using ChunkArray = cgogn::ChunkArray; + using ChunkArrayContainer = typename Inherit::ChunkArrayContainer; + + inline DataIO() + { + data_ = make_unique>(); + } + + virtual void read_n(std::ifstream& fp, std::size_t n, bool binary, bool big_endian) override + { + data_ = make_unique>(n); + + if (binary) + { + fp.read(reinterpret_cast(std::addressof(data_->operator[](0))), n * sizeof(T)); + if (big_endian != ::cgogn::internal::cgogn_is_little_endian) + { + for (auto & x : *data_) + x = cgogn::io::internal::swap_endianness(x); + } + if (fp.eof() || fp.bad()) + data_->clear(); + } else { + std::string line; + line.reserve(256); + std::size_t i = 0ul; + for (; i < n && (!fp.eof()) && (!fp.bad()); ) + { + bool no_error = true; + std::getline(fp,line); + std::istringstream line_stream(line); + while (i < n && (no_error = static_cast(internal::parse(line_stream, data_->operator[](i))))) + ++i; + if (!no_error && (!line_stream.eof())) + break; + } + if (i < n) + { + std::cerr << "read_n : An eccor occured while reading the line \n\"" << line << "\"" << std::endl; + data_->clear(); + } + } + } + + virtual ChunkArray* add_attribute(ChunkArrayContainer& cac, const std::string& att_name) override + { + for (unsigned i = cac.capacity(), end = data_->size(); i < end; ++i) + cac.template insert_lines(); + return cac.template add_attribute(att_name); + } + + virtual void to_chunk_array(ChunkArrayGen* ca_gen) const override + { + ChunkArray* ca = dynamic_cast(ca_gen); + unsigned int i = 0u; + for (auto& x : *data_) + ca->operator[](i++) = x; + } + + virtual void* get_data() override + { + return data_.get(); + } + + virtual unsigned int nb_components() const override + { + return geometry::nb_components_traits::value; + } + +private: + std::unique_ptr> data_; +}; + +template +std::unique_ptr> DataIOGen::newDataIO(const std::string type_name) +{ + if (type_name == name_of_type(float())) + return make_unique>(); + else { + if (type_name == name_of_type(double())) + return make_unique>(); + else { + if (type_name == name_of_type(char())) + return make_unique>(); + else + { + if (type_name == name_of_type(std::int8_t())) + return make_unique>(); + else + { + if (type_name == name_of_type(std::uint8_t())) + return make_unique>(); + else + { + if (type_name == name_of_type(std::int16_t())) + return make_unique>(); + else + { + if (type_name == name_of_type(std::uint16_t())) + return make_unique>(); + else + { + if (type_name == name_of_type(std::uint32_t())) + return make_unique>(); + else + { + if (type_name == name_of_type(std::int32_t())) + return make_unique>(); + else + { + if (type_name == name_of_type(std::uint64_t())) + return make_unique>(); + else + { + if (type_name == name_of_type(std::int64_t())) + return make_unique>(); + } + } + } + } + } + } + } + } + } + } + return std::unique_ptr>(); +} + +template +std::unique_ptr> DataIOGen::newDataIO(const std::string type_name, unsigned int nb_components) +{ + cgogn_assert(nb_components >=1u && nb_components <= 4u); + if (nb_components == 1u) + return DataIOGen::newDataIO(type_name); + + if (type_name == name_of_type(std::int32_t())) + { + switch (nb_components) { + case 2u: return make_unique>(); break; + case 3u: return make_unique>(); break; + case 4u: return make_unique>(); break; + default:break; + } + } + if (type_name == name_of_type(float())) + { + switch (nb_components) { + case 2u: return make_unique>(); break; + case 3u: return make_unique>(); break; + case 4u: return make_unique>(); break; + default:break; + } + } + if (type_name == name_of_type(double())) + { + switch (nb_components) { + case 2u: return make_unique>(); break; + case 3u: return make_unique>(); break; + case 4u: return make_unique>(); break; + default:break; + } + } + return std::unique_ptr>(); +} + +} // namespace io +} // namespace cgogn + +#endif // IO_DATA_IO_H_ diff --git a/cgogn/io/io_utils.h b/cgogn/io/io_utils.h new file mode 100644 index 00000000..472ede69 --- /dev/null +++ b/cgogn/io/io_utils.h @@ -0,0 +1,76 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef IO_IO_UTILS_H_ +#define IO_IO_UTILS_H_ + +#include +#include + +#include + +#include + +namespace cgogn +{ + +namespace io +{ + +namespace internal +{ + +template +inline typename std::enable_if::value || std::is_floating_point::value, T>::type swap_endianness(const T& x) +{ + return ::cgogn::swap_endianness(x); +} + +template +inline typename std::enable_if<(!std::is_arithmetic::value) && !std::is_floating_point::value, T>::type swap_endianness(T& x) +{ + for (std::size_t i = 0u ; i < geometry::vector_traits::SIZE; ++i) + x[i] = ::cgogn::swap_endianness(x[i]); + return x; +} + +template +inline typename std::enable_if::value || std::is_floating_point::value, std::istringstream&>::type parse(std::istringstream& iss, T& x) +{ + iss >> x; + return iss; +} + +template +inline typename std::enable_if::value && !std::is_floating_point::value, std::istringstream&>::type parse(std::istringstream& iss, T& x) +{ + for (std::size_t i = 0u ; i < geometry::vector_traits::SIZE; ++i) + iss >> x[i]; + return iss; +} + +} // namespace internal +} // namespace io +} // namespace cgogn + +#endif // IO_IO_UTILS_H_ diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index 6cd30cc1..ffdc8d72 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -26,8 +26,6 @@ #include #include -#include -#include #include #include @@ -36,12 +34,11 @@ #include #include -#include - #include #include #include +#include namespace cgogn { @@ -49,178 +46,6 @@ namespace cgogn namespace io { -/** - * @brief vtk_data_type_to_cgogn_name_of_type : convert the type names we can find in VTK files to the one we use in cgogn. - * @param vtk_type_str a typename extracted from a vtk file - * @return a typename string that can be match with some cgogn::name_of_type - */ -inline std::string vtk_data_type_to_cgogn_name_of_type(const std::string& vtk_type_str) -{ - const std::string& data_type = to_lower(vtk_type_str); - if (data_type == "char" || data_type == "int8") - return name_of_type(std::int8_t()); - if (data_type == "unsigned_char" || data_type == "uint8") - return name_of_type(std::uint8_t()); - if (data_type == "short" || data_type == "int16") - return name_of_type(std::int16_t()); - if (data_type == "unsigned_short" || data_type == "uint16") - return name_of_type(std::uint16_t()); - if (data_type == "int" || data_type == "int32") - return name_of_type(std::int32_t()); - if (data_type == "unsigned_int" || data_type == "uint32") - return name_of_type(std::uint32_t()); - if (data_type == "long" || data_type == "int64") - return name_of_type(std::int64_t()); - if (data_type == "unsigned_long" || data_type == "uint64") - return name_of_type(std::uint64_t()); - if (data_type == "float" || data_type == "float32") - return name_of_type(float()); - if (data_type == "double" || data_type == "float64") - return name_of_type(double()); - - std::cerr << "vtk_data_type_to_cgogn_name_of_type : unknown vtk type : " << vtk_type_str << std::endl; - return std::string(); -} - -/** - * @brief read_n_scalars, read N scalars of type BUFFER_T in an ifstream (binary or ascii mode, little or big endian) - * @param fp, an ifstream - * @param n, the number of scalars to read - * @param binary, true if the scalars are encoded in binary - * @param big_endian, true if the scalars are encoded in binary and big endian - * @return n scalars of type T (converted if necessary from type BUFFER_T) if successful, nullptr otherwith - */ -template -inline std::unique_ptr> read_n_scalars(std::ifstream& fp, std::size_t n, bool binary, bool big_endian) -{ - using VecT = std::vector; - using VecBufferT = std::vector; - - std::cerr << "read_n_scalars called with T = " << name_of_type(T()) << " and U = " << name_of_type(BUFFER_T()) << std::endl; - std::unique_ptr res = make_unique(); - res->reserve(n); - - std::unique_ptr buffer = make_unique(n); - - if (binary) - { - fp.read(reinterpret_cast(std::addressof(buffer->operator[](0))), n * sizeof(BUFFER_T)); - - if (big_endian != internal::cgogn_is_little_endian) - { - for (auto & x : *buffer) - x = swap_endianness(x); - } - if (fp.eof() || fp.bad()) - buffer->clear(); - - } else { - std::string line; - line.reserve(256); - std::size_t i = 0ul; - for (; i < n && (!fp.eof()) && (!fp.bad()); ) - { - std::getline(fp,line); - std::istringstream line_stream(line); - while (i < n && (line_stream >> buffer->operator[](i))) - ++i; - } - - if (i < n) - buffer->clear(); - } - - if (std::is_same::value) - res.reset(reinterpret_cast(buffer.release())); - else - { - for (auto buffer_it = buffer->begin(), end = buffer->end(); buffer_it != end; ++buffer_it) - res->push_back(*buffer_it); - } - - return res; -} - -/** - * @brief read_n_scalars, read n scalars of type given by the STRING type_name in the ifstream fp, and convert them to the template type T - * @param fp, the file we want to read - * @param type_name, the type_name (CAUTION : consistent with cgogn name_of_type method) - * @param n, number of scalars to read - * @param binary, true if the scalars are encoded in binary - * @param big_endian, ignored if !binary. True if the file we read chose to encod the scalars in big endian - * @return - */ -template -inline std::unique_ptr> read_n_scalars(std::ifstream& fp, const std::string& type_name, std::size_t n, bool binary, bool big_endian) -{ - using VecT = std::vector; - - if (type_name == name_of_type(float())) - return std::move(read_n_scalars(fp,n,binary,big_endian)); - else { - if (type_name == name_of_type(double())) - return std::move(read_n_scalars(fp,n,binary,big_endian)); - else { - if (type_name == name_of_type(char())) - return std::move(read_n_scalars(fp,n,binary,big_endian)); - else - { - if (type_name == name_of_type(std::int8_t())) - return std::move(read_n_scalars(fp,n,binary,big_endian)); - else - { - if (type_name == name_of_type(std::uint8_t())) - return std::move(read_n_scalars(fp,n,binary,big_endian)); - else - { - if (type_name == name_of_type(std::int16_t())) - return std::move(read_n_scalars(fp,n,binary,big_endian)); - else - { - if (type_name == name_of_type(std::uint32_t())) - return std::move(read_n_scalars(fp,n,binary,big_endian)); - else - { - if (type_name == name_of_type(std::int32_t())) - return std::move(read_n_scalars(fp,n,binary,big_endian)); - else - { - if (type_name == name_of_type(std::uint64_t())) - return std::move(read_n_scalars(fp,n,binary,big_endian)); - else - { - if (type_name == name_of_type(std::int64_t())) - return std::move(read_n_scalars(fp,n,binary,big_endian)); - } - } - } - } - } - } - } - } - } - return std::unique_ptr>(); -} - -//template -//inline std::unique_ptr> read_n_vec(std::ifstream& fp, const std::string& type_name, std::size_t n, bool binary, bool big_endian) -//{ -// using Scalar = typename geometry::vector_traits::Scalar; -// const std::size_t size = geometry::vector_traits::SIZE; -// std::unique_ptr> scalars(std::move(read_n_scalars(fp, type_name,n*size,binary,big_endian))); -// std::unique_ptr> res = make_unique>(); -// res->reserve(n); -// for (auto it = scalars->begin(), end = scalars->end() ; it != end;) -// { -// res->emplace_back(Scalar(*it), Scalar(*(it+ 1)), Scalar(*(it+2))); -// it+=3; -// } - -// return res; -//} - - enum SurfaceFileType { SurfaceFileType_UNKNOWN = 0, @@ -252,6 +77,8 @@ class SurfaceImport using Self = SurfaceImport; using Map = CMap2; using Vertex = typename Map::Vertex; + using Edge = typename Map::Edge; + using Face = typename Map::Face; static const unsigned int CHUNK_SIZE = MAP_TRAITS::CHUNK_SIZE; @@ -273,6 +100,11 @@ class SurfaceImport std::vector faces_vertex_indices_; ChunkArrayContainer vertex_attributes_; + ChunkArrayContainer face_attributes_; + + using DataIOGen = cgogn::io::DataIOGen; + template + using DataIO = cgogn::io::DataIO; SurfaceImport() : nb_vertices_(0u) @@ -298,6 +130,7 @@ class SurfaceImport faces_nb_edges_.clear(); faces_vertex_indices_.clear(); vertex_attributes_.remove_attributes(); + face_attributes_.remove_attributes(); } template @@ -314,7 +147,7 @@ class SurfaceImport std::ifstream fp(filename.c_str(), std::ios::in); if (!fp.good()) { - std::cout << "Unable to open file " << filename << std::endl; + std::cerr << "Unable to open file " << filename << std::endl; return false; } @@ -322,7 +155,7 @@ class SurfaceImport switch (type) { case SurfaceFileType_UNKNOWN : - std::cout << "Unknown file type " << filename << std::endl; + std::cerr << "Unknown file type " << filename << std::endl; result = false; break; case SurfaceFileType_OFF : @@ -489,8 +322,8 @@ class SurfaceImport std::getline(fp, line); if (line.rfind("OFF") == std::string::npos) { - std::cout << "Problem reading off file: not an off file" << std::endl; - std::cout << line << std::endl; + std::cerr << "Problem reading off file: not an off file" << std::endl; + std::cerr << line << std::endl; return false; } @@ -775,7 +608,7 @@ class SurfaceImport nb_vertices_ = pid.nb_vertices(); nb_faces_ = pid.nb_faces(); - + // read vertices position std::vector vertices_id; vertices_id.reserve(nb_vertices_); @@ -829,7 +662,7 @@ class SurfaceImport VTK_TYPE vtk_type(VTK_TYPE::UNKNOWN); - std::cerr << "Opening a vtk file" << std::endl; + std::cout << "Opening a legacy vtk file" << std::endl; using Scalar = typename VEC3::Scalar; std::string line; @@ -858,12 +691,12 @@ class SurfaceImport vtk_type = VTK_TYPE::POLYDATA; } - std::unique_ptr> cells; - std::unique_ptr> cell_types; - ChunkArray* position = vertex_attributes_.template add_attribute("position"); - std::vector verticesID; + DataIO cells; + DataIO cell_types; + + ChunkArray* position_arr = vertex_attributes_.template add_attribute("position"); - if (vtk_type == VTK_TYPE::UNSTRUCTURED_GRID) + if (vtk_type == VTK_TYPE::UNSTRUCTURED_GRID || vtk_type == VTK_TYPE::POLYDATA) { while(!fp.eof()) { @@ -871,64 +704,178 @@ class SurfaceImport word.clear(); std::istringstream sstream(line); sstream >> word; - if (to_upper(word) == "POINTS") + word = to_upper(word); + + if (word == "POINTS") { std::string type_str; sstream >> this->nb_vertices_ >> type_str; type_str = to_lower(type_str); - std::cout << nb_vertices_ << " points" << " of type " << type_str << std::endl; - verticesID.reserve(nb_vertices_); - std::unique_ptr> pos(std::move(read_n_scalars(fp, vtk_data_type_to_cgogn_name_of_type(type_str), 3*nb_vertices_, !ascii_file, false /*don't deal with endianness yet*/))); - cgogn_assert(pos); - for (std::size_t i = 0ul ; i < 3ul*nb_vertices_ ; i+=3ul) + DataIO positions; + positions.read_n(fp, nb_vertices_, !ascii_file, false); + for (std::size_t i = 0ul ; i < nb_vertices_ ; ++i) + vertex_attributes_.template insert_lines<1>(); + positions.to_chunk_array(position_arr); + } else { + if (word == "CELLS" || word == "POLYGONS" || word == "TRIANGLE_STRIPS") { - VEC3 P(Scalar(pos->operator[](i)), Scalar((*pos)[i+1ul]), Scalar((*pos)[i+2ul])); - std::cout << P[0] << " " << P[1] << " " << P[2] << std::endl; - unsigned int id = vertex_attributes_.template insert_lines<1>(); - position->operator [](id) = P; - verticesID.push_back(id); - } - } + unsigned int size; + sstream >> this->nb_faces_ >> size; + cells.read_n(fp, size, !ascii_file, false); - if (to_upper(word) == "CELLS") - { - std::cerr << line << std::endl; - unsigned int size; - sstream >> this->nb_faces_ >> size; - std::cerr << "nb cells " << nb_faces_ << " and size " << size << std::endl; - cells = std::move(read_n_scalars(fp, name_of_type(std::uint32_t()), size, !ascii_file, false)); - std::size_t i = 0ul; - } + std::vector* cell_types_vec = static_cast*>(cell_types.get_data()); + cgogn_assert(cell_types_vec != nullptr); + if (word == "POLYGONS") + { + cell_types_vec->reserve(nb_faces_); + for (unsigned i = 0u; i < nb_faces_ ;++i) + { + cell_types_vec->push_back(VTK_CELL_TYPES::VTK_POLYGON); + } + } else if (word == "TRIANGLE_STRIPS") + { + cell_types_vec->reserve(nb_faces_); + for (unsigned i = 0u; i < nb_faces_ ;++i) + { + cell_types_vec->push_back(VTK_CELL_TYPES::VTK_TRIANGLE_STRIP); + } + } - if (to_upper(word) == "CELL_TYPES") - { - std::cerr << line << std::endl; - unsigned int nbc; - sstream >> nbc; - std::cerr << "nb cells " << nbc << std::endl; - cell_types = std::move(read_n_scalars(fp, name_of_type(std::uint32_t()), nbc, !ascii_file, false)); + } else { + if (word == "CELL_TYPES") + { + unsigned int nbc; + sstream >> nbc; + cell_types.read_n(fp, nbc, !ascii_file, false); + } else { + if (word == "POINT_DATA" || word == "CELL_DATA") + { + const bool cell_data = (word == "CELL_DATA"); + unsigned int nb_data; + sstream >> nb_data; + + if (!cell_data) + { + cgogn_assert(this->nb_vertices_ == 0u || nb_data == this->nb_vertices_); + } + std::ifstream::pos_type previous_pos; + do { + previous_pos = fp.tellg(); + std::getline(fp, line); + sstream.str(line); + sstream.clear(); + word.clear(); + sstream >> word; + word = to_upper(word); + if (word == "SCALARS" || word == "VECTOR" || word == "NORMALS") + { + const bool is_vector = !(word == "SCALARS"); + std::string att_name; + std::string att_type; + unsigned int num_comp = is_vector? 3u : 1u; + sstream >> att_name >> att_type >> num_comp; + std::cout << "reading attribute \"" << att_name << "\" of type " << att_type << " (" << num_comp << " components)." << std::endl; + + const auto pos_before_lookup_table = fp.tellg(); // the lookup table might (or might not) be defined + std::getline(fp,line); + sstream.str(line); + sstream.clear(); + std::string lookup_table; + std::string lookup_table_name; + sstream >> lookup_table >> lookup_table_name; + if (to_upper(lookup_table) == "LOOKUP_TABLE") + { + std::cout << "VTK import : ignoring lookup table named \"" << lookup_table_name << "\"" << std::endl; + } else { + fp.seekg(pos_before_lookup_table); // if there wasn't a lookup table we go back and start reading the numerical values + } + + std::unique_ptr att(DataIOGen::newDataIO(att_type, num_comp)); + att->read_n(fp, nb_data, !ascii_file, false); + if (cell_data) + att->to_chunk_array(att->add_attribute(face_attributes_, att_name)); + else + att->to_chunk_array(att->add_attribute(vertex_attributes_, att_name)); + } else { + if (word == "FIELD") + { + std::string field_name; + unsigned int num_arrays = 0u; + sstream >> field_name >> num_arrays; + for (unsigned int i = 0u ; i< num_arrays; ++i) + { + std::getline(fp,line); + sstream.str(line); + sstream.clear(); + std::string data_name; + unsigned int nb_comp; + unsigned int nb_data; + std::string data_type; + sstream >> data_name >> nb_comp >> nb_data >> data_type; + std::cout << "reading field \"" << data_name << "\" of type " << data_type << " (" << nb_comp << " components)." << std::endl; + std::unique_ptr att(DataIOGen::newDataIO(data_type, nb_comp)); + att->read_n(fp, nb_data, !ascii_file, false); + if (cell_data) + att->to_chunk_array(att->add_attribute(face_attributes_, data_name)); + else + att->to_chunk_array(att->add_attribute(vertex_attributes_, data_name)); + } + } else + if (word == "LOOKUP_TABLE") + { + std::string table_name; + unsigned int nb_data = 0u; + sstream >> table_name >> nb_data; + std::cout << "ignoring the definition of the lookuptable named \"" << table_name << "\"" << std::endl; + if (ascii_file) + { + DataIO trash; + trash.read_n(fp, nb_data, false, false); + } else + { + DataIO trash; + trash.read_n(fp, nb_data, true, false); + } + } + } + } while (word != "POINT_DATA" && word != "CELL_DATA" && (!fp.eof())); + if (!fp.eof()) + { + fp.seekg(previous_pos); + word.clear(); + } else + break; + } else + { + if (!word.empty()) + std::cerr << "VTK keyword \"" << word << "\" is not supported." << std::endl; + } + } + } } } } - auto cell_type_it = cell_types->begin(); - for (auto cell_it = cells->begin(), end = cells->end(); cell_it != end ; ++cell_type_it) + auto cells_it = static_cast*>(cells.get_data())->begin(); + const std::vector* cell_types_vec = static_cast*>(cell_types.get_data()); + for(auto cell_types_it = cell_types_vec->begin(); cell_types_it != cell_types_vec->end() ; ) { - const std::size_t nb_vert = *cell_it++; + const std::size_t nb_vert = *(cells_it++); + const int cell_type = *(cell_types_it++); - if ((*cell_type_it) != VTK_CELL_TYPES::VTK_TRIANGLE_STRIP) + if (cell_type != VTK_CELL_TYPES::VTK_TRIANGLE_STRIP) { faces_nb_edges_.push_back(nb_vert); for (std::size_t i = 0ul ; i < nb_vert;++i) { - faces_vertex_indices_.push_back(*cell_it++); + faces_vertex_indices_.push_back(*cells_it++); } } else { std::vector vertexIDS; vertexIDS.reserve(nb_vert); for (std::size_t i = 0ul ; i < nb_vert;++i) { - vertexIDS.push_back(*cell_it++); + vertexIDS.push_back(*cells_it++); } for (unsigned int i = 0u ; i < nb_vert -2u; ++i) diff --git a/cgogn/io/vtk_cell_types.h b/cgogn/io/vtk_cell_types.h index 3cacbff3..f9e39f98 100644 --- a/cgogn/io/vtk_cell_types.h +++ b/cgogn/io/vtk_cell_types.h @@ -52,5 +52,38 @@ enum VTK_CELL_TYPES VTK_QUADRATIC_HEXAHEDRON = 25 }; +/** + * @brief vtk_data_type_to_cgogn_name_of_type : convert the type names we can find in VTK files to the one we use in cgogn. + * @param vtk_type_str a typename extracted from a vtk file + * @return a typename string that can be match with some cgogn::name_of_type + */ +inline std::string vtk_data_type_to_cgogn_name_of_type(const std::string& vtk_type_str) +{ + const std::string& data_type = to_lower(vtk_type_str); + if (data_type == "char" || data_type == "int8") + return name_of_type(std::int8_t()); + if (data_type == "unsigned_char" || data_type == "uint8") + return name_of_type(std::uint8_t()); + if (data_type == "short" || data_type == "int16") + return name_of_type(std::int16_t()); + if (data_type == "unsigned_short" || data_type == "uint16") + return name_of_type(std::uint16_t()); + if (data_type == "int" || data_type == "int32") + return name_of_type(std::int32_t()); + if (data_type == "unsigned_int" || data_type == "uint32") + return name_of_type(std::uint32_t()); + if (data_type == "long" || data_type == "int64") + return name_of_type(std::int64_t()); + if (data_type == "unsigned_long" || data_type == "uint64") + return name_of_type(std::uint64_t()); + if (data_type == "float" || data_type == "float32") + return name_of_type(float()); + if (data_type == "double" || data_type == "float64") + return name_of_type(double()); + + std::cerr << "vtk_data_type_to_cgogn_name_of_type : unknown vtk type : " << vtk_type_str << std::endl; + return std::string(); +} + } // namespace cgogn #endif // IO_VTK_CELL_TYPES_H_ diff --git a/data/meshes/polydata.vtk b/data/meshes/polydata.vtk new file mode 100644 index 00000000..0c7dbbd0 --- /dev/null +++ b/data/meshes/polydata.vtk @@ -0,0 +1,61 @@ +# vtk DataFile Version 2.0 +Cube example +ASCII +DATASET POLYDATA +POINTS 8 float +0.0 0.0 0.0 +1.0 0.0 0.0 +1.0 1.0 0.0 +0.0 1.0 0.0 +0.0 0.0 1.0 +1.0 0.0 1.0 +1.0 1.0 1.0 +0.0 1.0 1.0 +POLYGONS 6 30 +4 0 1 2 3 +4 4 5 6 7 +4 0 1 5 4 +4 2 3 7 6 +4 0 4 7 3 +4 1 2 6 5 +CELL_DATA 6 +SCALARS cell_scalars int 1 +LOOKUP_TABLE default +0 +1 +2 +3 +4 +5 +NORMALS cell_normals float +0 0 -1 +0 0 1 +0 -1 0 +0 1 0 +-1 0 0 +1 0 0 +FIELD FieldData 2 +cellIds 1 6 int +0 1 2 3 4 5 +faceAttributes 2 6 float +0.0 1.0 1.0 2.0 2.0 3.0 3.0 4.0 4.0 5.0 5.0 6.0 +POINT_DATA 8 +SCALARS sample_scalars float 1 +LOOKUP_TABLE my_table +0.0 +1.0 +2.0 +3.0 +4.0 +5.0 +6.0 +7.0 +LOOKUP_TABLE my_table 8 +0.0 0.0 0.0 1.0 +1.0 0.0 0.0 1.0 +0.0 1.0 0.0 1.0 +1.0 1.0 0.0 1.0 +0.0 0.0 1.0 1.0 +1.0 0.0 1.0 1.0 +0.0 1.0 1.0 1.0 +1.0 1.0 1.0 1.0 \ No newline at end of file From 9b6eb7e2c501c77b76a1d6ae50c7d3bd1ad82805 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Wed, 2 Mar 2016 17:47:01 +0100 Subject: [PATCH 234/402] add shader round point --- cgogn/rendering/CMakeLists.txt | 2 + cgogn/rendering/drawer.cpp | 40 +++- cgogn/rendering/drawer.h | 36 ++- cgogn/rendering/examples/CMakeLists.txt | 2 + .../rendering/shaders/shader_round_point.cpp | 218 ++++++++++++++++++ cgogn/rendering/shaders/shader_round_point.h | 87 +++++++ 6 files changed, 373 insertions(+), 12 deletions(-) create mode 100644 cgogn/rendering/shaders/shader_round_point.cpp create mode 100644 cgogn/rendering/shaders/shader_round_point.h diff --git a/cgogn/rendering/CMakeLists.txt b/cgogn/rendering/CMakeLists.txt index 6ad1c210..077bae38 100644 --- a/cgogn/rendering/CMakeLists.txt +++ b/cgogn/rendering/CMakeLists.txt @@ -16,6 +16,7 @@ set(HEADER_FILES shaders/shader_vector_per_vertex.h shaders/shader_phong.h shaders/shader_bold_line.h + shaders/shader_round_point.h drawer.h ) @@ -27,6 +28,7 @@ set(SOURCE_FILES shaders/shader_vector_per_vertex.cpp shaders/shader_phong.cpp shaders/shader_bold_line.cpp + shaders/shader_round_point.cpp drawer.cpp ) diff --git a/cgogn/rendering/drawer.cpp b/cgogn/rendering/drawer.cpp index f431862d..c080b74e 100644 --- a/cgogn/rendering/drawer.cpp +++ b/cgogn/rendering/drawer.cpp @@ -37,6 +37,7 @@ namespace rendering ShaderColorPerVertex* Drawer::shader_cpv_= NULL; ShaderBoldLine* Drawer::shader_bl_= NULL; +ShaderRoundPoint* Drawer::shader_rp_= NULL; Drawer::Drawer(QOpenGLFunctions_3_3_Core* ogl33): current_size_(1.0f), @@ -57,9 +58,18 @@ Drawer::Drawer(QOpenGLFunctions_3_3_Core* ogl33): vao_bl_ = shader_bl_->add_vao(); shader_bl_->bind(); - shader_bl_->set_color(QColor(255,255,0,255)); shader_bl_->release(); shader_bl_->set_vao(vao_bl_,vbo_pos_,vbo_col_); + + + if (shader_rp_ == NULL) + shader_rp_ = new ShaderRoundPoint(true); + vao_rp_ = shader_rp_->add_vao(); + shader_rp_->bind(); + shader_rp_->release(); + shader_rp_->set_vao(vao_rp_,vbo_pos_,vbo_col_); + + } Drawer::~Drawer() @@ -162,14 +172,31 @@ void Drawer::end_list() void Drawer::callList(const QMatrix4x4& projection, const QMatrix4x4& modelview) { - shader_cpv_->bind(); - shader_cpv_->set_matrices(projection,modelview); - shader_cpv_->bind_vao(vao_cpv_); + + shader_rp_->bind(); + shader_rp_->set_matrices(projection,modelview); + shader_rp_->bind_vao(vao_bl_); + for (auto& pp : begins_point_) { - ogl33_->glPointSize(pp.width); + shader_rp_->set_width(pp.width); ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); } + shader_rp_->release_vao(vao_bl_); + shader_rp_->release(); + + + shader_cpv_->bind(); + shader_cpv_->set_matrices(projection,modelview); + shader_cpv_->bind_vao(vao_cpv_); + +// for (auto& pp : begins_point_) +// { +// ogl33_->glPointSize(pp.width); +// ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); +// } + + for (auto& pp : begins_line_) { @@ -190,8 +217,6 @@ void Drawer::callList(const QMatrix4x4& projection, const QMatrix4x4& modelview) shader_bl_->set_matrices(projection,modelview); shader_bl_->bind_vao(vao_bl_); - - for (auto& pp : begins_bold_line_) { shader_bl_->set_width(pp.width); @@ -210,7 +235,6 @@ void Drawer::callList(const QMatrix4x4& projection, const QMatrix4x4& modelview) } - shader_bl_->release_vao(vao_bl_); shader_bl_->release(); diff --git a/cgogn/rendering/drawer.h b/cgogn/rendering/drawer.h index d1483883..e8f611a0 100644 --- a/cgogn/rendering/drawer.h +++ b/cgogn/rendering/drawer.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -56,8 +57,6 @@ class CGOGN_RENDERING_API Drawer//: protected QOpenGLFunctions_3_3_Core protected: VBO* vbo_pos_; VBO* vbo_col_; - unsigned int vao_cpv_; - unsigned int vao_bl_; std::vector data_pos_; std::vector data_col_; @@ -68,10 +67,15 @@ class CGOGN_RENDERING_API Drawer//: protected QOpenGLFunctions_3_3_Core std::vector* current_begin_; - float current_size_; static ShaderColorPerVertex* shader_cpv_; static ShaderBoldLine* shader_bl_; + static ShaderRoundPoint* shader_rp_; + + unsigned int vao_cpv_; + unsigned int vao_bl_; + unsigned int vao_rp_; + float current_size_; bool current_aa_; QOpenGLFunctions_3_3_Core* ogl33_; @@ -123,6 +127,17 @@ class CGOGN_RENDERING_API Drawer//: protected QOpenGLFunctions_3_3_Core */ void color3f(float r, float g, float b); + + inline void vertex3fv(const std::array& xyz) + { + vertex3f(xyz[0],xyz[1],xyz[2]); + } + + inline void color3fv(const std::array& rgb) + { + color3f(rgb[0],rgb[1],rgb[2]); + } + template inline void vertex3fv(SCAL* xyz) { @@ -135,8 +150,21 @@ class CGOGN_RENDERING_API Drawer//: protected QOpenGLFunctions_3_3_Core color3f(float(rgb[0]),float(rgb[1]),float(rgb[2])); } + template + inline void vertex3fv(const VEC3& xyz) + { + vertex3f(float(xyz[0]),float(xyz[1]),float(xyz[2])); + } + + template + inline void color3fv(const VEC3& rgb) + { + color3f(float(rgb[0]),float(rgb[1]),float(rgb[2])); + } + + /** - * use as a glCallList + * use as a glCallList (draw the compiled drawing list) * @param projection projection matrix * @param modelview modelview matrix */ diff --git a/cgogn/rendering/examples/CMakeLists.txt b/cgogn/rendering/examples/CMakeLists.txt index 3e214ff2..408dee64 100644 --- a/cgogn/rendering/examples/CMakeLists.txt +++ b/cgogn/rendering/examples/CMakeLists.txt @@ -18,6 +18,8 @@ target_link_libraries(simple_viewer cgogn_core cgogn_io cgogn_rendering QOGLView add_executable(viewer_per_face viewer_per_face.cpp) target_link_libraries(viewer_per_face cgogn_core cgogn_io cgogn_rendering QOGLViewer) +add_executable(drawing drawing.cpp) +target_link_libraries(drawing cgogn_rendering QOGLViewer) diff --git a/cgogn/rendering/shaders/shader_round_point.cpp b/cgogn/rendering/shaders/shader_round_point.cpp new file mode 100644 index 00000000..5e05868e --- /dev/null +++ b/cgogn/rendering/shaders/shader_round_point.cpp @@ -0,0 +1,218 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#define CGOGN_RENDERING_DLL_EXPORT + +#include + +#include +#include + +namespace cgogn +{ + +namespace rendering +{ + +const char* ShaderRoundPoint::vertex_shader_source_ = +"#version 150\n" +"in vec3 vertex_pos;\n" +"void main() {\n" +" gl_Position = vec4(vertex_pos,1.0);\n" +"}\n"; + + +const char* ShaderRoundPoint::geometry_shader_source_ = +"#version 150\n" +"layout (points) in;\n" +"layout (triangle_strip, max_vertices=4) out;\n" +"uniform mat4 projection_matrix;\n" +"uniform mat4 model_view_matrix;\n" +"uniform vec2 pointSizes;\n" +"out vec2 local;\n" +"void main()\n" +"{\n" +" vec4 A = projection_matrix*model_view_matrix * gl_in[0].gl_Position;\n" +" A = A/A.w;\n" +" local = vec2(-1.0,-1.0);\n" +" gl_Position = vec4(A.xyz-vec3(-pointSizes[0],-pointSizes[1],0.0), 1.0);\n" +" EmitVertex();\n" +" local = vec2(1.0,-1.0);\n" +" gl_Position = vec4(A.xyz-vec3(pointSizes[0],-pointSizes[1],0.0), 1.0);\n" +" EmitVertex();\n" +" local = vec2(-1.0,1.0);\n" +" gl_Position = vec4(A.xyz-vec3(-pointSizes[0],pointSizes[1],0.0), 1.0);\n" +" EmitVertex();\n" +" local = vec2(1.0,1.0);\n" +" gl_Position = vec4(A.xyz-vec3(pointSizes[0],pointSizes[1],0.0), 1.0);\n" +" EmitVertex();\n" +" EndPrimitive();\n" +"}\n"; + + +const char* ShaderRoundPoint::fragment_shader_source_ = +"#version 150\n" +"uniform vec4 color;\n" +"in vec2 local;\n" +"out vec4 fragColor;\n" +"void main() {\n" +" if (dot(local,local)>1.0) discard;\n" +" fragColor = color;\n" +"}\n"; + + + + +const char* ShaderRoundPoint::vertex_shader_source2_ = +"#version 150\n" +"in vec3 vertex_pos;\n" +"in vec3 vertex_color;\n" +"out vec3 color_v;\n" +"void main() {\n" +" color_v = vertex_color;\n" +" gl_Position = vec4(vertex_pos,1.0);\n" +"}\n"; + + +const char* ShaderRoundPoint::geometry_shader_source2_ = +"#version 150\n" +"layout (points) in;\n" +"layout (triangle_strip, max_vertices=4) out;\n" +"uniform mat4 projection_matrix;\n" +"uniform mat4 model_view_matrix;\n" +"uniform vec2 pointSizes;\n" +"in vec3 color_v[];\n" +"out vec2 local;\n" +"out vec3 color_f;\n" +"void main()\n" +"{\n" +" vec4 A = projection_matrix*model_view_matrix * gl_in[0].gl_Position;\n" +" A = A/A.w;\n" +" color_f = color_v[0];\n" +" local = vec2(-1.0,-1.0);\n" +" gl_Position = vec4(A.xyz-vec3(-pointSizes[0],-pointSizes[1],0.0), 1.0);\n" +" EmitVertex();\n" +" local = vec2(1.0,-1.0);\n" +" gl_Position = vec4(A.xyz-vec3(pointSizes[0],-pointSizes[1],0.0), 1.0);\n" +" EmitVertex();\n" +" local = vec2(-1.0,1.0);\n" +" gl_Position = vec4(A.xyz-vec3(-pointSizes[0],pointSizes[1],0.0), 1.0);\n" +" EmitVertex();\n" +" local = vec2(1.0,1.0);\n" +" gl_Position = vec4(A.xyz-vec3(pointSizes[0],pointSizes[1],0.0), 1.0);\n" +" EmitVertex();\n" +" EndPrimitive();\n" +"}\n"; + +const char* ShaderRoundPoint::fragment_shader_source2_ = +"#version 150\n" +"in vec2 local;\n" +"in vec3 color_f;\n" +"out vec3 fragColor;\n" +"void main() {\n" +" if (dot(local,local)>1.0) discard;\n" +" fragColor = color_f;\n" +"}\n"; + + +ShaderRoundPoint::ShaderRoundPoint(bool color_per_vertex) +{ + if (color_per_vertex) + { + prg_.addShaderFromSourceCode(QOpenGLShader::Vertex, vertex_shader_source2_); + prg_.addShaderFromSourceCode(QOpenGLShader::Geometry, geometry_shader_source2_); + prg_.addShaderFromSourceCode(QOpenGLShader::Fragment, fragment_shader_source2_); + prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); + prg_.bindAttributeLocation("vertex_color", ATTRIB_COLOR); + prg_.link(); + + get_matrices_uniforms(); + unif_width_ = prg_.uniformLocation("pointSizes"); + } + else + { + prg_.addShaderFromSourceCode(QOpenGLShader::Vertex, vertex_shader_source_); + prg_.addShaderFromSourceCode(QOpenGLShader::Geometry, geometry_shader_source_); + prg_.addShaderFromSourceCode(QOpenGLShader::Fragment, fragment_shader_source_); + prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); + prg_.link(); + + get_matrices_uniforms(); + unif_color_ = prg_.uniformLocation("color"); + unif_width_ = prg_.uniformLocation("pointSizes"); + } +} + + + +void ShaderRoundPoint::set_color(const QColor& rgb) +{ + prg_.setUniformValue(unif_color_, rgb); +} + +void ShaderRoundPoint::set_width(float wpix) +{ + QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); + int viewport[4]; + ogl->glGetIntegerv(GL_VIEWPORT, viewport); + QSizeF wd(wpix / float(viewport[2]), wpix / float(viewport[3])); + prg_.setUniformValue(unif_width_, wd); +} + +bool ShaderRoundPoint::set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color) +{ + if (i >= vaos_.size()) + { + std::cerr << "VAO number " << i << " does not exist" << std::endl; + return false; + } + + QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); + + prg_.bind(); + vaos_[i]->bind(); + + // position vbo + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ATTRIB_POS); + ogl->glVertexAttribPointer(ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + + if (vbo_color) + { + // color vbo + vbo_color->bind(); + ogl->glEnableVertexAttribArray(ATTRIB_COLOR); + ogl->glVertexAttribPointer(ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_color->release(); + } + + vaos_[i]->release(); + prg_.release(); + + return true; +} + +} // namespace rendering + +} // namespace cgogn diff --git a/cgogn/rendering/shaders/shader_round_point.h b/cgogn/rendering/shaders/shader_round_point.h new file mode 100644 index 00000000..1590ec54 --- /dev/null +++ b/cgogn/rendering/shaders/shader_round_point.h @@ -0,0 +1,87 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef RENDERING_SHADERS_ROUND_POINT_H_ +#define RENDERING_SHADERS_ROUND_POINT_H_ + +#include +#include +#include + +namespace cgogn +{ + +namespace rendering +{ + +class CGOGN_RENDERING_API ShaderRoundPoint : public ShaderProgram +{ + static const char* vertex_shader_source_; + static const char* geometry_shader_source_; + static const char* fragment_shader_source_; + + static const char* vertex_shader_source2_; + static const char* geometry_shader_source2_; + static const char* fragment_shader_source2_; + + enum + { + ATTRIB_POS = 0, + ATTRIB_COLOR + }; + + // uniform ids + int unif_color_; + int unif_width_; + +public: + + ShaderRoundPoint(bool color_per_vertex = false); + + /** + * @brief set current color + * @param rgb + */ + void set_color(const QColor& rgb); + + /** + * @brief set the width of lines (call before each draw) + * @param w width in pixel + */ + void set_width(float w); + + /** + * @brief set a vao configuration + * @param i vao id (0,1,...) + * @param vbo_pos pointer on position vbo (XYZ) + * @param vbo_color pointer on color vbo + * @return true if ok + */ + bool set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color=NULL); +}; + +} // namespace rendering + +} // namespace cgogn + +#endif // RENDERING_SHADERS_ROUND_POINT_H_ From a666c578c15606693b0eb151d60e88a925d83298 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Wed, 2 Mar 2016 18:32:16 +0100 Subject: [PATCH 235/402] Cleaning and documentation of CMap1 tests --- cgogn/core/cmap/cmap1.h | 4 +- cgogn/core/cmap/map_base.h | 26 --- cgogn/core/tests/cmap/cmap0_test.cpp | 65 +++---- cgogn/core/tests/cmap/cmap0_topo_test.cpp | 58 ++++--- cgogn/core/tests/cmap/cmap1_topo_test.cpp | 200 +++++++++++++--------- 5 files changed, 178 insertions(+), 175 deletions(-) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 4357056a..221580b0 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -265,10 +265,12 @@ class CMap1_T : public CMap0_T { cgogn_message_assert(size > 0u, "Cannot create an empty face"); + if (size == 0) { + std::cerr << "Warning: attempt to create an empty face results in a single dart" << std::endl; + } Dart d = this->add_dart(); for (unsigned int i = 1u; i < size; ++i) split_vertex_topo(d); - return d; } diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index ffd612fa..e260da3e 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -385,32 +385,6 @@ class MapBase : public MapBaseData remove_attribute(counter); } - template - bool is_well_embedded(Cell c) const - { - const ConcreteMap* cmap = to_concrete(); - bool result = true; - - std::map emb_set; - cmap->foreach_dart_of_orbit(c, [&] (Dart d) - { - emb_set.insert(std::pair(this->template get_embedding(d), d)); - }); - - if(emb_set.size() > 1) - { - std::cout << "Orbit is not well embedded: " << std::endl; - - result = false; - std::map::iterator it; - for (auto const& de : emb_set) - std::cout << "\t dart #" << de.second << " has embed index #" << de.first << std::endl; - std::cout << std::endl; - } - - return result; - } - /** * \brief Tests if all \p ORBIT orbits are well embedded * \details An orbit is well embedded if all its darts diff --git a/cgogn/core/tests/cmap/cmap0_test.cpp b/cgogn/core/tests/cmap/cmap0_test.cpp index 0e7edc03..7bdeb2ca 100644 --- a/cgogn/core/tests/cmap/cmap0_test.cpp +++ b/cgogn/core/tests/cmap/cmap0_test.cpp @@ -34,7 +34,10 @@ namespace cgogn /*! * \brief The CMap0Test class implements tests on embedded CMap0 * It contains a CMap0 to which a vertex attribute is added - * to enforce the indexation mecanism + * to enforce the indexation mecanism in cell traversals. + * Note that pure topological operations have already been tested, + * thus only the indexation mecanism used for the embedding of cells + * is tested here. */ class CMap0Test: public ::testing::Test { @@ -50,70 +53,50 @@ class CMap0Test: public ::testing::Test testCMap0 cmap_; VertexAttributeHandler vertices_; + /*! + * \brief A vector of darts on which the methods are tested. + */ + std::vector darts_; + /*! * \brief Add a vertex attribute to the testing configuration */ CMap0Test() { + std::srand(static_cast(std::time(0))); vertices_ = cmap_.add_attribute("vertices"); } /*! - * \brief An array of darts on which the methods are tested. + * \brief Initialize the darts in darts_ with added vertices + * \param n : the number of added darts or vertices */ - std::array tdarts_; - - /*! - * \brief Initialize the darts in tdarts_ - * \return The number of added darts or vertices - */ - int addVertices() { - for (int i = 0; i < NB_MAX; ++i) - tdarts_[i] = cmap_.add_vertex(); - - return NB_MAX; + void addVertices(unsigned int n) + { + for (unsigned int i = 0; i < n; ++i) + darts_.push_back(cmap_.add_vertex()); } }; /*! - * \brief An empty CMap0 contains no vertex (the attribute is used) - */ -TEST_F(CMap0Test, testCMap0Constructor) -{ - EXPECT_EQ(cmap_.nb_cells(), 0u); -} - -/*! - * \brief Adding vertices add one cell in the vertex attribute - * and the cell indexation is preserved + * \brief Adding vertices preserves the cell indexation */ TEST_F(CMap0Test, testAddVertex) { - for (int i = 1; i< NB_MAX; ++i) { - Dart d = cmap_.add_vertex(); - vertices_[d] = i; - EXPECT_EQ(cmap_.nb_cells(), i); - } + addVertices(NB_MAX); EXPECT_TRUE(cmap_.check_map_integrity()); } /*! - * \brief Removing vertices remove one cell in the vertex attribute - * and the cell indexation is preserved + * \brief Removing vertices preserves the cell indexation */ TEST_F(CMap0Test, testRemoveVertex) { - int n = addVertices(); - - int countVertices = n; - for (int i = 0; i < n; ++i) { - Vertex d = tdarts_[i]; - if (std::rand()%3 == 1) { - cmap_.remove_vertex(Vertex(d)); - --countVertices; - EXPECT_EQ(cmap_.nb_cells(), countVertices); - } - } + addVertices(NB_MAX); + + for (Dart d: darts_) + if (std::rand()%3 == 1) cmap_.remove_vertex(Vertex(d)); + EXPECT_TRUE(cmap_.check_map_integrity()); } diff --git a/cgogn/core/tests/cmap/cmap0_topo_test.cpp b/cgogn/core/tests/cmap/cmap0_topo_test.cpp index c4089228..5375d612 100644 --- a/cgogn/core/tests/cmap/cmap0_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap0_topo_test.cpp @@ -32,6 +32,7 @@ namespace cgogn /*! * \brief The CMap0TopoTest class implements topological tests on CMap0 + * It contains a CMap0 with no attribute avoiding the indexation mecanism. */ class CMap0TopoTest: public ::testing::Test { @@ -45,25 +46,24 @@ class CMap0TopoTest: public ::testing::Test testCMap0 cmap_; + /*! + * \brief A vector of darts on which the methods are tested. + */ + std::vector darts_; + CMap0TopoTest() { std::srand(static_cast(std::time(0))); } /*! - * \brief An array of darts on which the methods are tested. + * \brief Initialize the darts in darts_ with added vertices + * \param n : the number of added darts or vertices */ - std::array tdarts_; - - /*! - * \brief Initialize the darts in tdarts_ - * \return The number of added darts or vertices - */ - unsigned int addVertices() { - for (unsigned int i = 0; i < NB_MAX; ++i) - tdarts_[i] = cmap_.add_vertex(); - - return NB_MAX; + void addVertices(unsigned int n) + { + for (unsigned int i = 0; i < n; ++i) + darts_.push_back(cmap_.add_vertex()); } }; @@ -82,11 +82,14 @@ TEST_F(CMap0TopoTest, testCMap0Constructor) */ TEST_F(CMap0TopoTest, testAddVertex) { - for (unsigned int i = 1; i< NB_MAX; ++i) { - cmap_.add_vertex(); - EXPECT_EQ(cmap_.nb_darts(), i); - EXPECT_EQ(cmap_.nb_cells(), i); - } + addVertices(NB_MAX); + EXPECT_EQ(cmap_.nb_darts(), NB_MAX); + EXPECT_EQ(cmap_.nb_cells(), NB_MAX); + + cmap_.add_vertex(); + EXPECT_EQ(cmap_.nb_darts(), NB_MAX+1); + EXPECT_EQ(cmap_.nb_cells(), NB_MAX+1); + EXPECT_TRUE(cmap_.check_map_integrity()); } @@ -96,18 +99,25 @@ TEST_F(CMap0TopoTest, testAddVertex) */ TEST_F(CMap0TopoTest, testRemoveVertex) { - int n = addVertices(); + addVertices(NB_MAX); + int countVertices = NB_MAX; + + cmap_.remove_vertex(darts_.back()); + --countVertices; + EXPECT_EQ(cmap_.nb_darts(), countVertices); + EXPECT_EQ(cmap_.nb_cells(), countVertices); - int countVertices = n; - for (int i = 0; i < n; ++i) { - Vertex d = tdarts_[i]; - if (std::rand()%3 == 1) { + darts_.pop_back(); + for (Dart d: darts_) + { + if (std::rand()%3 == 1) + { cmap_.remove_vertex(d); --countVertices; - EXPECT_EQ(cmap_.nb_darts(), countVertices); - EXPECT_EQ(cmap_.nb_cells(), countVertices); } } + EXPECT_EQ(cmap_.nb_darts(), countVertices); + EXPECT_EQ(cmap_.nb_cells(), countVertices); EXPECT_TRUE(cmap_.check_map_integrity()); } diff --git a/cgogn/core/tests/cmap/cmap1_topo_test.cpp b/cgogn/core/tests/cmap/cmap1_topo_test.cpp index a367551c..accf2adb 100644 --- a/cgogn/core/tests/cmap/cmap1_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_topo_test.cpp @@ -28,7 +28,7 @@ namespace cgogn { -#define NB_MAX 1000 +#define NB_MAX 100 /*! * \brief The CMap1TopoTest class implements topological tests on CMap1 @@ -45,9 +45,9 @@ class CMap1TopoTest : public CMap1, public ::testing::Test protected: /*! - * \brief An array of darts on which the methods are tested. + * \brief A vector of darts on which the methods are tested. */ - std::array tdarts_; + std::vector darts_; CMap1TopoTest() { @@ -55,33 +55,34 @@ class CMap1TopoTest : public CMap1, public ::testing::Test } /*! - * \brief Initialize the darts in tdarts_ - * \return The number of added darts or vertices + * \brief Initialize the darts in darts_ with added vertices + * \param n : the number of added darts or vertices */ - unsigned int addVertices() { - for (unsigned int i = 0; i < NB_MAX; ++i) - tdarts_[i] = add_dart(); - - return NB_MAX; + void addVertices(unsigned int n) + { + for (unsigned int i = 0; i < n; ++i) + darts_.push_back(add_dart()); } /*! - * \brief Generate a random set of faces and put them in tdarts_ - * \return The number of added darts or vertices in all faces. - * The face size ranges from 1 to 100. - * A random dart of each face is put in the tdarts_ array. + * \brief Generate a random set of faces and put them in darts_ + * \return The total number of added darts or vertices. + * The face size ranges from 1 to 10. + * A random dart of each face is put in the darts_ array. */ - unsigned int addFaces() { + unsigned int addFaces(unsigned int n) + { unsigned int count = 0; - for (unsigned int i = 0; i < NB_MAX; ++i) { - unsigned int n = 1 + std::rand() % 100; + for (unsigned int i = 0; i < n; ++i) + { + unsigned int n = 1 + std::rand() % 10; Dart d = add_face_topo(n); count += n; while (std::rand()%10 != 1) d = phi1(d); - tdarts_[i] = d; + darts_.push_back(d); } return count; } @@ -99,17 +100,21 @@ TEST_F(CMap1TopoTest, testCMap1Constructor) /*! * \brief Adding darts adds one vertex and one face per dart. - * The test adds NB_MAX darts. - * The number of cells correctly increases and the map integrity is preserved. + * The test adds darts and check that the number of cells correctly + * increases and that the map integrity is preserved. */ TEST_F(CMap1TopoTest, testAddDart) { - for (unsigned int i = 1; i< NB_MAX; ++i) { - add_dart(); - EXPECT_EQ(nb_darts(), i); - EXPECT_EQ(nb_cells(), i); - EXPECT_EQ(nb_cells(), i); - } + add_dart(); + EXPECT_EQ(nb_darts(), 1); + EXPECT_EQ(nb_cells(), 1); + EXPECT_EQ(nb_cells(), 1); + + addVertices(NB_MAX); + EXPECT_EQ(nb_darts(), NB_MAX+1); + EXPECT_EQ(nb_cells(), NB_MAX+1); + EXPECT_EQ(nb_cells(), NB_MAX+1); + EXPECT_TRUE(check_map_integrity()); } @@ -120,18 +125,27 @@ TEST_F(CMap1TopoTest, testAddDart) */ TEST_F(CMap1TopoTest, testRemoveDart) { - unsigned int n = addVertices(); - - unsigned int count = n; - for (unsigned int i = 0; i < n; ++i) { - if (std::rand() % 3 == 1) { - remove_dart(tdarts_[i]); - --count; - EXPECT_EQ(nb_darts(), count); - EXPECT_EQ(nb_cells(), count); - EXPECT_EQ(nb_cells(), count); + addVertices(NB_MAX); + int countVertices = NB_MAX; + + remove_dart(darts_.back()); + --countVertices; + EXPECT_EQ(nb_darts(), countVertices); + EXPECT_EQ(nb_cells(), countVertices); + EXPECT_EQ(nb_cells(), countVertices); + + darts_.pop_back(); + for (Dart d: darts_) + { + if (std::rand()%3 == 1) + { + remove_dart(d); + --countVertices; } } + EXPECT_EQ(nb_darts(), countVertices); + EXPECT_EQ(nb_cells(), countVertices); + EXPECT_EQ(nb_cells(), countVertices); EXPECT_TRUE(check_map_integrity()); } @@ -142,46 +156,60 @@ TEST_F(CMap1TopoTest, testRemoveDart) */ TEST_F(CMap1TopoTest, testPhi1SewUnSew) { - unsigned int n = addVertices(); + addVertices(NB_MAX); + int countFaces = NB_MAX; for (unsigned int i = 0; i < NB_MAX; ++i) { - Dart d = tdarts_[std::rand() % n]; - Dart e = tdarts_[std::rand() % n]; - Dart f = tdarts_[std::rand() % n]; + Dart d = darts_[std::rand() % NB_MAX]; + Dart e = darts_[std::rand() % NB_MAX]; + Dart f = darts_[std::rand() % NB_MAX]; Dart nd = phi1(d); Dart ne = phi1(e); + if (d != e) { + if (same_cell(Face(d),Face(e))) + ++countFaces; + else + --countFaces; + } phi1_sew(d, e); EXPECT_TRUE(phi1(d) == ne); EXPECT_TRUE(phi1(e) == nd); Dart nf1 = phi1(f); Dart nf2 = phi1(nf1); phi1_unsew(f); + if (f != nf1) ++countFaces; EXPECT_TRUE(phi1(nf1) == nf1); EXPECT_TRUE(phi1(f) == nf2); } - EXPECT_EQ(nb_darts(), n); - EXPECT_EQ(nb_cells(), n); + EXPECT_EQ(nb_darts(), NB_MAX); + EXPECT_EQ(nb_cells(), NB_MAX); + EXPECT_EQ(nb_cells(), countFaces); EXPECT_TRUE(check_map_integrity()); } /*! * \brief Adding a face of size n adds n darts, n vertices and 1 face. - * The test performs NB_MAX additions of randomly sized faces. - * The number of generated cells is correct and the map integrity is preserved. + * The test adds some faces and check that the number of generated cells is correct + * and that the map integrity is preserved. */ TEST_F(CMap1TopoTest, testAddFace) { - unsigned int count = 0; + add_face_topo(1); + EXPECT_EQ(nb_darts(), 1); + EXPECT_EQ(nb_cells(), 1); + EXPECT_EQ(nb_cells(), 1); - for (unsigned int i = 0; i < NB_MAX; ++i) { - unsigned int n = 1 + std::rand() % 100; - Dart d = add_face_topo(n); - count += n; - EXPECT_EQ(nb_darts(), count); - EXPECT_EQ(nb_cells(), count); - EXPECT_EQ(nb_cells(), i+1); - } + add_face_topo(10); + EXPECT_EQ(nb_darts(), 11); + EXPECT_EQ(nb_cells(), 11); + EXPECT_EQ(nb_cells(), 2); + + unsigned int countVertices = 11 + addFaces(NB_MAX); + + EXPECT_EQ(nb_darts(), countVertices); + EXPECT_EQ(nb_cells(), countVertices); + EXPECT_EQ(nb_cells(), NB_MAX+2); EXPECT_TRUE(check_map_integrity()); } @@ -191,16 +219,16 @@ TEST_F(CMap1TopoTest, testAddFace) */ TEST_F(CMap1TopoTest, testSplitVertex) { - unsigned int n = addFaces(); + unsigned int countVertices = addFaces(NB_MAX); - for (unsigned int i = 0; i < NB_MAX; ++i) { - Face d = tdarts_[i]; + for (Dart d: darts_) + { unsigned int k = degree(Face(d)); split_vertex_topo(d); EXPECT_EQ(degree(Face(d)), k+1); - EXPECT_EQ(nb_cells(), n+i+1); - EXPECT_EQ(nb_cells(), NB_MAX); } + EXPECT_EQ(nb_cells(), countVertices+NB_MAX); + EXPECT_EQ(nb_cells(), NB_MAX); EXPECT_TRUE(check_map_integrity()); } @@ -210,12 +238,11 @@ TEST_F(CMap1TopoTest, testSplitVertex) */ TEST_F(CMap1TopoTest, testRemoveVertex) { - unsigned int n = addFaces(); - - unsigned int countVertices = n; + unsigned int countVertices = addFaces(NB_MAX); unsigned int countFaces = NB_MAX; - for (unsigned int i = 0; i < NB_MAX; ++i) { - Face d = tdarts_[i]; + + for (Dart d: darts_) + { unsigned int k = degree(Face(d)); if (k > 1) { Dart e = phi1(d); @@ -230,49 +257,56 @@ TEST_F(CMap1TopoTest, testRemoveVertex) } } - EXPECT_EQ(this->template nb_cells(), countVertices); - EXPECT_EQ(this->template nb_cells(), countFaces); + EXPECT_EQ(nb_cells(), countVertices); + EXPECT_EQ(nb_cells(), countFaces); EXPECT_TRUE(check_map_integrity()); } +/*! \brief Removing a face removes all its vertices. + * The test randomly removes 1/3 of the initial faces. + * The number of cells correctly decreases and the map integrity is preserved. + */ TEST_F(CMap1TopoTest, testRemoveFace) { - int n = addFaces(); + unsigned int countVertices = addFaces(NB_MAX); + unsigned int countFaces = NB_MAX; - int countVertices = n; - int countFaces = NB_MAX; - for (int i = 0; i < NB_MAX; ++i) { - Face d = tdarts_[i]; + for (Dart d: darts_) + { unsigned int k = degree(Face(d)); remove_face(d); countVertices -= k; --countFaces; } - EXPECT_EQ(this->template nb_cells(), countVertices); - EXPECT_EQ(this->template nb_cells(), countFaces); + EXPECT_EQ(nb_cells(), countVertices); + EXPECT_EQ(nb_cells(), countFaces); EXPECT_TRUE(check_map_integrity()); } +/*! \brief Reversing a face reverses the order of its vertices. + * The test reverses randomly generated faces. + * The number of faces and their degrees do not change and the map integrity is preserved. + */ TEST_F(CMap1TopoTest, testReverseFace) { - int n = addFaces(); + unsigned int countVertices = addFaces(NB_MAX); - for (int i = 0; i < NB_MAX; ++i) { - Face f = tdarts_[i]; - unsigned int k = degree(f); + for (Dart d: darts_) + { + unsigned int k = degree(Face(d)); std::vector face_darts; - foreach_dart_of_orbit(f, [&] (Dart d) { - face_darts.push_back(d); + foreach_dart_of_orbit(Face(d), [&] (Dart e) { + face_darts.push_back(e); }); - reverse_face_topo(tdarts_[i]); - EXPECT_EQ(degree(Face(tdarts_[i])), k); + reverse_face_topo(d); + EXPECT_EQ(degree(Face(d)), k); - f = phi1(f); - foreach_dart_of_orbit(f, [&] (Dart d) { - EXPECT_TRUE(face_darts.back() == d); + d = phi1(d); + foreach_dart_of_orbit(Face(d), [&] (Dart e) { + EXPECT_TRUE(face_darts.back() == e); face_darts.pop_back(); }); EXPECT_TRUE(face_darts.empty()); From 3af67ff4703e11e820a71ca4d1d38f62dcf26b48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 2 Mar 2016 18:32:47 +0100 Subject: [PATCH 236/402] added skip_n and reset methods. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/data_io.h | 94 ++++++++++++++++++++++++++++----------- cgogn/io/surface_import.h | 4 +- 2 files changed, 71 insertions(+), 27 deletions(-) diff --git a/cgogn/io/data_io.h b/cgogn/io/data_io.h index eb35654c..e3bbdfb7 100644 --- a/cgogn/io/data_io.h +++ b/cgogn/io/data_io.h @@ -49,7 +49,9 @@ class DataIOGen using ChunkArrayContainer = typename MAP::template ChunkArrayContainer; virtual void read_n(std::ifstream& fp, std::size_t n, bool binary, bool big_endian) = 0; + virtual void skip_n(std::ifstream& fp, std::size_t n, bool binary) = 0; virtual void* get_data() = 0; + virtual void reset() = 0; virtual void to_chunk_array(ChunkArrayGen* ca_gen) const = 0; virtual ChunkArrayGen* add_attribute(ChunkArrayContainer& cac, const std::string& att_name) = 0; @@ -72,25 +74,29 @@ class DataIO : public DataIOGen using ChunkArray = cgogn::ChunkArray; using ChunkArrayContainer = typename Inherit::ChunkArrayContainer; - inline DataIO() + DataIO() { data_ = make_unique>(); } + DataIO(const Self&) = delete; + DataIO& operator =(const Self&) = delete; + DataIO(Self&&) = default; + virtual void read_n(std::ifstream& fp, std::size_t n, bool binary, bool big_endian) override { - data_ = make_unique>(n); - + const std::size_t old_size = data_->size(); + data_->resize(old_size + n); if (binary) { - fp.read(reinterpret_cast(std::addressof(data_->operator[](0))), n * sizeof(T)); + fp.read(reinterpret_cast(std::addressof(data_->operator[](old_size))), n * sizeof(T)); if (big_endian != ::cgogn::internal::cgogn_is_little_endian) { for (auto & x : *data_) x = cgogn::io::internal::swap_endianness(x); } if (fp.eof() || fp.bad()) - data_->clear(); + this->reset(); } else { std::string line; line.reserve(256); @@ -100,7 +106,7 @@ class DataIO : public DataIOGen bool no_error = true; std::getline(fp,line); std::istringstream line_stream(line); - while (i < n && (no_error = static_cast(internal::parse(line_stream, data_->operator[](i))))) + while (i < n && (no_error = static_cast(internal::parse(line_stream, data_->operator[](i+old_size))))) ++i; if (!no_error && (!line_stream.eof())) break; @@ -108,11 +114,41 @@ class DataIO : public DataIOGen if (i < n) { std::cerr << "read_n : An eccor occured while reading the line \n\"" << line << "\"" << std::endl; - data_->clear(); + this->reset(); } } } + virtual void skip_n(std::ifstream& fp, std::size_t n, bool binary) override + { + if (binary) + { + fp.ignore(n * sizeof(T)); + } else { + std::string line; + line.reserve(256); + std::size_t i = 0ul; + for (; i < n && (!fp.eof()) && (!fp.bad()); ) + { + bool no_error = true; + std::getline(fp,line); + std::istringstream line_stream(line); + while (i < n && (no_error = static_cast(line_stream.ignore(1, ' ')))) + ++i; + if (!no_error && (!line_stream.eof())) + break; + } + if (i < n) + { + std::cerr << "skip_n : An eccor occured while skipping the line \n\"" << line << "\"" << std::endl; + } + } + } + virtual void reset() override + { + data_ = make_unique>(); + } + virtual ChunkArray* add_attribute(ChunkArrayContainer& cac, const std::string& att_name) override { for (unsigned i = cac.capacity(), end = data_->size(); i < end; ++i) @@ -195,6 +231,7 @@ std::unique_ptr> DataIOGen::newDataIO(const std::string type } } } + std::cerr << "DataIOGen::newDataIO : couldn't create a DataIO of type \"" << type_name << "\"." << std::endl; return std::unique_ptr>(); } @@ -207,31 +244,38 @@ std::unique_ptr> DataIOGen::newDataIO(const std::string type if (type_name == name_of_type(std::int32_t())) { - switch (nb_components) { + switch (nb_components) + { case 2u: return make_unique>(); break; case 3u: return make_unique>(); break; case 4u: return make_unique>(); break; default:break; } - } - if (type_name == name_of_type(float())) - { - switch (nb_components) { - case 2u: return make_unique>(); break; - case 3u: return make_unique>(); break; - case 4u: return make_unique>(); break; - default:break; - } - } - if (type_name == name_of_type(double())) - { - switch (nb_components) { - case 2u: return make_unique>(); break; - case 3u: return make_unique>(); break; - case 4u: return make_unique>(); break; - default:break; + } else { + if (type_name == name_of_type(float())) + { + switch (nb_components) + { + case 2u: return make_unique>(); break; + case 3u: return make_unique>(); break; + case 4u: return make_unique>(); break; + default:break; + } + } else { + if (type_name == name_of_type(double())) + { + switch (nb_components) + { + case 2u: return make_unique>(); break; + case 3u: return make_unique>(); break; + case 4u: return make_unique>(); break; + default:break; + } + } } } + + std::cerr << "DataIOGen::newDataIO : couldn't create a DataIO of type \"" << type_name << "\" with " << nb_components << " components." << std::endl; return std::unique_ptr>(); } diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index d9dac0e1..361fbb10 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -834,11 +834,11 @@ class SurfaceImport if (ascii_file) { DataIO trash; - trash.read_n(fp, nb_data, false, false); + trash.skip_n(fp, nb_data, false); } else { DataIO trash; - trash.read_n(fp, nb_data, true, false); + trash.skip_n(fp, nb_data, true); } } } From f80406387585eedc685d2840203ad7a631756830 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Wed, 2 Mar 2016 18:36:37 +0100 Subject: [PATCH 237/402] typo --- cgogn/core/tests/cmap/cmap1_topo_test.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cgogn/core/tests/cmap/cmap1_topo_test.cpp b/cgogn/core/tests/cmap/cmap1_topo_test.cpp index accf2adb..2dee29d8 100644 --- a/cgogn/core/tests/cmap/cmap1_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_topo_test.cpp @@ -152,7 +152,8 @@ TEST_F(CMap1TopoTest, testRemoveDart) /*! * \brief Sewing and unsewing darts correctly changes the topological relations. * The test perfoms NB_MAX sewing and unsewing on randomly chosen dart of tdarts_. - * The number of vertices is unchanged and the map integrity is preserved. + * The number of vertices is unchanged, the number of faces changes correctly + * and the map integrity is preserved. */ TEST_F(CMap1TopoTest, testPhi1SewUnSew) { @@ -331,6 +332,4 @@ TEST_F(CMap1TopoTest, testHasDegree) EXPECT_FALSE(has_degree(f,11)); } -// The traversal methods are tested through the nb_cells calls and wihtin other methods - } // namespace cgogn From 6d35c2291c884eb227c8039f3f150732e9c9627a Mon Sep 17 00:00:00 2001 From: David Cazier Date: Wed, 2 Mar 2016 18:38:56 +0100 Subject: [PATCH 238/402] typo --- thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt b/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt index 3a439b5a..64f3c40e 100644 --- a/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt +++ b/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt @@ -3,7 +3,7 @@ set(CGOGN_THIRDPARTY_QOGLVIEWER_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE PROJECT(QOGLViewer) FIND_PACKAGE(OpenGL REQUIRED) -find_package(Qt5Widgets 5.3.2 REQUIRED) +find_package(Qt5Widgets 5.4.0 REQUIRED) set(CMAKE_AUTOMOC ON) From e0ecaf7d10ee20f60b8cb5adba6c761e601d3d03 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Wed, 2 Mar 2016 18:41:12 +0100 Subject: [PATCH 239/402] typo --- cgogn/core/cmap/map_base.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index e260da3e..87565373 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -443,7 +443,8 @@ class MapBase : public MapBaseData { for (unsigned int i = container.begin(), end = container.end(); i != end; container.next(i)) { - if (marker[i] == 0) { + if (marker[i] == 0) + { result = false; break; } From d8c7aa47abe3e45468c144ab707adcf99e517e75 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Wed, 2 Mar 2016 18:50:31 +0100 Subject: [PATCH 240/402] typo --- cgogn/core/cmap/map_base.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 87565373..ad47df28 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -444,7 +444,7 @@ class MapBase : public MapBaseData for (unsigned int i = container.begin(), end = container.end(); i != end; container.next(i)) { if (marker[i] == 0) - { + result = false; break; } From a70fbd759f9f064920b1fe6b0976b857bcb5cd94 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Thu, 3 Mar 2016 10:56:10 +0100 Subject: [PATCH 241/402] merge --- cgogn/core/cmap/map_base.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index b5290438..16f47425 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -444,7 +444,7 @@ class MapBase : public MapBaseData for (unsigned int i = container.begin(), end = container.end(); i != end; container.next(i)) { if (marker[i] == 0) - + { result = false; break; } From 0251a18557d2c6ffc9b7a9cb0e1b3601aac65dc0 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Thu, 3 Mar 2016 14:24:10 +0100 Subject: [PATCH 242/402] comments --- cgogn/core/cmap/cmap1.h | 4 ++-- cgogn/core/tests/cmap/cmap0_test.cpp | 6 +++--- cgogn/core/tests/cmap/cmap0_topo_test.cpp | 4 ++++ cgogn/core/tests/cmap/cmap1_test.cpp | 13 +++++++++---- cgogn/core/tests/cmap/cmap1_topo_test.cpp | 10 +++++++--- cgogn/core/tests/cmap/cmap2_test.cpp | 15 +++++++++++---- cgogn/core/tests/cmap/cmap2_topo_test.cpp | 11 ++++++++--- 7 files changed, 44 insertions(+), 19 deletions(-) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 221580b0..90e84849 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -265,9 +265,9 @@ class CMap1_T : public CMap0_T { cgogn_message_assert(size > 0u, "Cannot create an empty face"); - if (size == 0) { + if (size == 0) std::cerr << "Warning: attempt to create an empty face results in a single dart" << std::endl; - } + Dart d = this->add_dart(); for (unsigned int i = 1u; i < size; ++i) split_vertex_topo(d); diff --git a/cgogn/core/tests/cmap/cmap0_test.cpp b/cgogn/core/tests/cmap/cmap0_test.cpp index 7bdeb2ca..9dfa4c9d 100644 --- a/cgogn/core/tests/cmap/cmap0_test.cpp +++ b/cgogn/core/tests/cmap/cmap0_test.cpp @@ -24,7 +24,6 @@ #include #include -#include namespace cgogn { @@ -35,9 +34,10 @@ namespace cgogn * \brief The CMap0Test class implements tests on embedded CMap0 * It contains a CMap0 to which a vertex attribute is added * to enforce the indexation mecanism in cell traversals. + * * Note that pure topological operations have already been tested, - * thus only the indexation mecanism used for the embedding of cells - * is tested here. + * in CMap0TopoTest, thus only the indexation mecanism used for the + * embedding of cells is tested here. */ class CMap0Test: public ::testing::Test { diff --git a/cgogn/core/tests/cmap/cmap0_topo_test.cpp b/cgogn/core/tests/cmap/cmap0_topo_test.cpp index 5375d612..8ecc8a23 100644 --- a/cgogn/core/tests/cmap/cmap0_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap0_topo_test.cpp @@ -33,6 +33,10 @@ namespace cgogn /*! * \brief The CMap0TopoTest class implements topological tests on CMap0 * It contains a CMap0 with no attribute avoiding the indexation mecanism. + * + * Note that these tests, check that the topological operators perform as wanted + * but do neither tests the containers (refs_, used_, etc.) or the iterators. + * These last tests are implemented in another test suite. */ class CMap0TopoTest: public ::testing::Test { diff --git a/cgogn/core/tests/cmap/cmap1_test.cpp b/cgogn/core/tests/cmap/cmap1_test.cpp index bc7697b9..ad7e781d 100644 --- a/cgogn/core/tests/cmap/cmap1_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_test.cpp @@ -21,19 +21,24 @@ * * *******************************************************************************/ -#include -#include - #include #include -#include namespace cgogn { #define NB_MAX 1000 +/*! + * \brief The CMap1Test class implements tests on embedded CMap1 + * It contains a CMap1 to which vertex and face attribute are added + * to enforce the indexation mecanism in cell traversals. + * + * Note that pure topological operations have already been tested, + * in CMap1TopoTest, thus only the indexation mecanism used for the + * embedding of cells is tested here. + */ class CMap1Test: public ::testing::Test { diff --git a/cgogn/core/tests/cmap/cmap1_topo_test.cpp b/cgogn/core/tests/cmap/cmap1_topo_test.cpp index 2dee29d8..e7f31b64 100644 --- a/cgogn/core/tests/cmap/cmap1_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_topo_test.cpp @@ -31,9 +31,13 @@ namespace cgogn #define NB_MAX 100 /*! -* \brief The CMap1TopoTest class implements topological tests on CMap1 -* It derives from CMap1 to allow the test of protected methods -*/ + * \brief The CMap1TopoTest class implements topological tests on CMap1 + * It derives from CMap1 to allow the test of protected methods + * + * Note that these tests, check that the topological operators perform as wanted + * but do neither tests the containers (refs_, used_, etc.) or the iterators. + * These last tests are implemented in another test suite. + */ class CMap1TopoTest : public CMap1, public ::testing::Test { diff --git a/cgogn/core/tests/cmap/cmap2_test.cpp b/cgogn/core/tests/cmap/cmap2_test.cpp index e199268f..029ddbc1 100644 --- a/cgogn/core/tests/cmap/cmap2_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_test.cpp @@ -21,19 +21,24 @@ * * *******************************************************************************/ -#include -#include - #include #include -#include namespace cgogn { #define NB_MAX 1000 +/*! + * \brief The CMap2Test class implements tests on embedded CMap2 + * It contains a CMap2 to which vertex, edge, face and volume attribute + * are added to enforce the indexation mecanism in cell traversals. + * + * Note that pure topological operations have already been tested, + * in CMap2TopoTest, thus only the indexation mecanism used for the + * embedding of cells is tested here. + */ class CMap2Test: public ::testing::Test { @@ -54,7 +59,9 @@ class CMap2Test: public ::testing::Test std::srand(static_cast(std::time(0))); cmap_.add_attribute("vertices"); + cmap_.add_attribute("edges"); cmap_.add_attribute("faces"); + cmap_.add_attribute("volumes"); } int randomFaces() { diff --git a/cgogn/core/tests/cmap/cmap2_topo_test.cpp b/cgogn/core/tests/cmap/cmap2_topo_test.cpp index 00b886a2..71abd126 100644 --- a/cgogn/core/tests/cmap/cmap2_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_topo_test.cpp @@ -21,9 +21,6 @@ * * *******************************************************************************/ -#include -#include - #include #include @@ -33,6 +30,14 @@ namespace cgogn #define NB_MAX 1000 +/*! + * \brief The CMap2TopoTest class implements topological tests on CMap2 + * It derives from CMap2 to allow the test of protected methods + * + * Note that these tests, check that the topological operators perform as wanted + * but do neither tests the containers (refs_, used_, etc.) or the iterators. + * These last tests are implemented in another test suite. + */ class CMap2TopoTest: public CMap2, public ::testing::Test { From 936956b21ea4630ddf7f6e1e915b5bb99e2a6cf0 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Thu, 3 Mar 2016 16:14:04 +0100 Subject: [PATCH 243/402] final touch for CMap0 and CMap1 tests --- cgogn/core/cmap/cmap1.h | 110 +++++++++--------- cgogn/core/tests/CMakeLists.txt | 2 +- cgogn/core/tests/cmap/cmap0_test.cpp | 6 +- cgogn/core/tests/cmap/cmap0_topo_test.cpp | 20 ++-- cgogn/core/tests/cmap/cmap1_test.cpp | 51 ++++---- cgogn/core/tests/cmap/cmap1_topo_test.cpp | 135 ++++++++-------------- 6 files changed, 147 insertions(+), 177 deletions(-) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 90e84849..318a69bf 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -200,60 +200,6 @@ class CMap1_T : public CMap0_T * High-level embedded and topological operations *******************************************************************************/ -protected: - - /** - * \brief Split a vertex. - * \param d : a dart of the vertex - * \return A dart of inserted vertex - * A new vertex is inserted after v in the PHI1 orbit. - */ - inline Dart split_vertex_topo(Dart d) - { - Dart e = this->add_dart(); // Create a new dart e - phi1_sew(d, e); // Insert e between d and phi1(d) - return e; - } - -public: - - /** - * \brief Split a vertex. - * \param d : a vertex - * \return The inserted vertex - * A new vertex is inserted after v in the PHI1 orbit. - * If the map has Vertex or Face attributes, the inserted cells - * are automatically embedded on new attribute elements. - */ - inline Vertex split_vertex(Vertex v) - { - CGOGN_CHECK_CONCRETE_TYPE; - - Vertex nv = split_vertex_topo(v); - - if (this->template is_embedded()) - this->new_orbit_embedding(nv); - - if (this->template is_embedded()) - this->template copy_embedding(nv.dart, v.dart); - - return nv; - } - - /** - * \brief Remove a vertex from its face and delete it. - * @param v : a vertex - * The vertex that preceeds v in the face is linked to the successor of v. - */ - inline void remove_vertex(Vertex v) - { - CGOGN_CHECK_CONCRETE_TYPE; - - Dart e = phi_1(v); - if (e != v.dart) phi1_unsew(e); - this->remove_dart(v.dart); - } - protected: /*! @@ -308,6 +254,8 @@ class CMap1_T : public CMap0_T */ inline void remove_face(Face f) { + CGOGN_CHECK_CONCRETE_TYPE; + Dart d = f.dart; Dart it = phi1(d); while(it != d) @@ -320,6 +268,60 @@ class CMap1_T : public CMap0_T this->remove_dart(d); } +protected: + + /** + * \brief Split a vertex. + * \param d : a dart of the vertex + * \return A dart of inserted vertex + * A new vertex is inserted after v in the PHI1 orbit. + */ + inline Dart split_vertex_topo(Dart d) + { + Dart e = this->add_dart(); // Create a new dart e + phi1_sew(d, e); // Insert e between d and phi1(d) + return e; + } + +public: + + /** + * \brief Split a vertex. + * \param d : a vertex + * \return The inserted vertex + * A new vertex is inserted after v in the PHI1 orbit. + * If the map has Vertex or Face attributes, the inserted cells + * are automatically embedded on new attribute elements. + */ + inline Vertex split_vertex(Vertex v) + { + CGOGN_CHECK_CONCRETE_TYPE; + + Vertex nv = split_vertex_topo(v); + + if (this->template is_embedded()) + this->new_orbit_embedding(nv); + + if (this->template is_embedded()) + this->template copy_embedding(nv.dart, v.dart); + + return nv; + } + + /** + * \brief Remove a vertex from its face and delete it. + * @param v : a vertex + * The vertex that preceeds v in the face is linked to the successor of v. + */ + inline void remove_vertex(Vertex v) + { + CGOGN_CHECK_CONCRETE_TYPE; + + Dart e = phi_1(v); + if (e != v.dart) phi1_unsew(e); + this->remove_dart(v.dart); + } + protected: inline void reverse_face_topo(Dart d) diff --git a/cgogn/core/tests/CMakeLists.txt b/cgogn/core/tests/CMakeLists.txt index 971c783a..e01abc95 100644 --- a/cgogn/core/tests/CMakeLists.txt +++ b/cgogn/core/tests/CMakeLists.txt @@ -8,7 +8,7 @@ set(SOURCE_FILES container/chunk_array_container_test.cpp -# cmap/cmap0_topo_test.cpp + cmap/cmap0_topo_test.cpp cmap/cmap0_test.cpp cmap/cmap1_topo_test.cpp cmap/cmap1_test.cpp diff --git a/cgogn/core/tests/cmap/cmap0_test.cpp b/cgogn/core/tests/cmap/cmap0_test.cpp index 9dfa4c9d..6af55def 100644 --- a/cgogn/core/tests/cmap/cmap0_test.cpp +++ b/cgogn/core/tests/cmap/cmap0_test.cpp @@ -81,7 +81,7 @@ class CMap0Test: public ::testing::Test /*! * \brief Adding vertices preserves the cell indexation */ -TEST_F(CMap0Test, testAddVertex) +TEST_F(CMap0Test, add_vertex) { addVertices(NB_MAX); EXPECT_TRUE(cmap_.check_map_integrity()); @@ -90,7 +90,7 @@ TEST_F(CMap0Test, testAddVertex) /*! * \brief Removing vertices preserves the cell indexation */ -TEST_F(CMap0Test, testRemoveVertex) +TEST_F(CMap0Test, remove_vertex) { addVertices(NB_MAX); @@ -100,4 +100,6 @@ TEST_F(CMap0Test, testRemoveVertex) EXPECT_TRUE(cmap_.check_map_integrity()); } +#undef NB_MAX + } // namespace cgogn diff --git a/cgogn/core/tests/cmap/cmap0_topo_test.cpp b/cgogn/core/tests/cmap/cmap0_topo_test.cpp index 8ecc8a23..d13081ab 100644 --- a/cgogn/core/tests/cmap/cmap0_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap0_topo_test.cpp @@ -74,7 +74,7 @@ class CMap0TopoTest: public ::testing::Test /*! * \brief An empty CMap0 contains no dart and no vertex */ -TEST_F(CMap0TopoTest, testCMap0Constructor) +TEST_F(CMap0TopoTest, Constructor) { EXPECT_EQ(cmap_.nb_darts(), 0u); EXPECT_EQ(cmap_.nb_cells(), 0u); @@ -84,15 +84,15 @@ TEST_F(CMap0TopoTest, testCMap0Constructor) * \brief Adding vertices adds one dart per vertex * and the map integrity is preserved */ -TEST_F(CMap0TopoTest, testAddVertex) +TEST_F(CMap0TopoTest, add_vertex) { - addVertices(NB_MAX); - EXPECT_EQ(cmap_.nb_darts(), NB_MAX); - EXPECT_EQ(cmap_.nb_cells(), NB_MAX); - cmap_.add_vertex(); - EXPECT_EQ(cmap_.nb_darts(), NB_MAX+1); - EXPECT_EQ(cmap_.nb_cells(), NB_MAX+1); + EXPECT_EQ(cmap_.nb_darts(), 1u); + EXPECT_EQ(cmap_.nb_cells(), 1u); + + addVertices(NB_MAX); + EXPECT_EQ(cmap_.nb_darts(), NB_MAX+1u); + EXPECT_EQ(cmap_.nb_cells(), NB_MAX+1u); EXPECT_TRUE(cmap_.check_map_integrity()); } @@ -101,7 +101,7 @@ TEST_F(CMap0TopoTest, testAddVertex) * \brief Removing vertices remove one dart per vertex * and the map integrity is preserved */ -TEST_F(CMap0TopoTest, testRemoveVertex) +TEST_F(CMap0TopoTest, remove_vertex) { addVertices(NB_MAX); int countVertices = NB_MAX; @@ -125,4 +125,6 @@ TEST_F(CMap0TopoTest, testRemoveVertex) EXPECT_TRUE(cmap_.check_map_integrity()); } +#undef NB_MAX + } // namespace cgogn diff --git a/cgogn/core/tests/cmap/cmap1_test.cpp b/cgogn/core/tests/cmap/cmap1_test.cpp index ad7e781d..391ea1a6 100644 --- a/cgogn/core/tests/cmap/cmap1_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_test.cpp @@ -28,7 +28,7 @@ namespace cgogn { -#define NB_MAX 1000 +#define NB_MAX 100 /*! * \brief The CMap1Test class implements tests on embedded CMap1 @@ -82,13 +82,10 @@ class CMap1Test: public ::testing::Test std::array tdarts_; }; -TEST_F(CMap1Test, testCMap1Constructor) -{ - EXPECT_EQ(cmap_.nb_cells(), 0u); - EXPECT_EQ(cmap_.nb_cells(), 0u); -} - -TEST_F(CMap1Test, addFace) +/*! + * \brief Adding vertices preserves the cell indexation + */ +TEST_F(CMap1Test, add_face) { int n = randomFaces(); @@ -97,41 +94,41 @@ TEST_F(CMap1Test, addFace) EXPECT_TRUE(cmap_.check_map_integrity()); } -TEST_F(CMap1Test, testSplitVertex) +TEST_F(CMap1Test, remove_face) { int n = randomFaces(); + int countVertex = n; + int countFace = NB_MAX; for (int i = 0; i < NB_MAX; ++i) { Face d = tdarts_[i]; - unsigned int k = cmap_.degree(Face(d)); - cmap_.split_vertex(Vertex(d)); + unsigned int k = cmap_.degree(d); + cmap_.remove_face(d); + countVertex -= k; + --countFace; } - EXPECT_EQ(cmap_.nb_cells(), n+NB_MAX); - EXPECT_EQ(cmap_.nb_cells(), NB_MAX); + EXPECT_EQ(cmap_.nb_cells(), countVertex); + EXPECT_EQ(cmap_.nb_cells(), countFace); EXPECT_TRUE(cmap_.check_map_integrity()); } -TEST_F(CMap1Test, testRemoveVertex) +TEST_F(CMap1Test, split_vertex) { int n = randomFaces(); - int countVertex = n; - int countFace = NB_MAX; for (int i = 0; i < NB_MAX; ++i) { Face d = tdarts_[i]; - unsigned int k = cmap_.degree(d); - cmap_.remove_vertex(Vertex(d)); - --countVertex; - if (k == 1u) --countFace; + unsigned int k = cmap_.degree(Face(d)); + cmap_.split_vertex(Vertex(d)); } - EXPECT_EQ(cmap_.nb_cells(), countVertex); - EXPECT_EQ(cmap_.nb_cells(), countFace); + EXPECT_EQ(cmap_.nb_cells(), n+NB_MAX); + EXPECT_EQ(cmap_.nb_cells(), NB_MAX); EXPECT_TRUE(cmap_.check_map_integrity()); } -TEST_F(CMap1Test, testRemoveFace) +TEST_F(CMap1Test, remove_vertex) { int n = randomFaces(); @@ -140,9 +137,9 @@ TEST_F(CMap1Test, testRemoveFace) for (int i = 0; i < NB_MAX; ++i) { Face d = tdarts_[i]; unsigned int k = cmap_.degree(d); - cmap_.remove_face(d); - countVertex -= k; - --countFace; + cmap_.remove_vertex(Vertex(d)); + --countVertex; + if (k == 1u) --countFace; } EXPECT_EQ(cmap_.nb_cells(), countVertex); @@ -150,4 +147,6 @@ TEST_F(CMap1Test, testRemoveFace) EXPECT_TRUE(cmap_.check_map_integrity()); } +#undef NB_MAX + } // namespace cgogn diff --git a/cgogn/core/tests/cmap/cmap1_topo_test.cpp b/cgogn/core/tests/cmap/cmap1_topo_test.cpp index e7f31b64..33a13b57 100644 --- a/cgogn/core/tests/cmap/cmap1_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_topo_test.cpp @@ -95,71 +95,20 @@ class CMap1TopoTest : public CMap1, public ::testing::Test /*! * \brief An empty CMap1 contains no dart, no vertex and no face. */ -TEST_F(CMap1TopoTest, testCMap1Constructor) +TEST_F(CMap1TopoTest, Constructor) { EXPECT_EQ(nb_darts(), 0u); EXPECT_EQ(this->template nb_cells(), 0u); EXPECT_EQ(this->template nb_cells(), 0u); } -/*! - * \brief Adding darts adds one vertex and one face per dart. - * The test adds darts and check that the number of cells correctly - * increases and that the map integrity is preserved. - */ -TEST_F(CMap1TopoTest, testAddDart) -{ - add_dart(); - EXPECT_EQ(nb_darts(), 1); - EXPECT_EQ(nb_cells(), 1); - EXPECT_EQ(nb_cells(), 1); - - addVertices(NB_MAX); - EXPECT_EQ(nb_darts(), NB_MAX+1); - EXPECT_EQ(nb_cells(), NB_MAX+1); - EXPECT_EQ(nb_cells(), NB_MAX+1); - - EXPECT_TRUE(check_map_integrity()); -} - -/*! - * \brief Removing unsewn darts removes one vertex and on face per dart. - * The test randomly removes 1/3 of the initial vertices. - * The number of cells correctly decreases and the map integrity is preserved. - */ -TEST_F(CMap1TopoTest, testRemoveDart) -{ - addVertices(NB_MAX); - int countVertices = NB_MAX; - - remove_dart(darts_.back()); - --countVertices; - EXPECT_EQ(nb_darts(), countVertices); - EXPECT_EQ(nb_cells(), countVertices); - EXPECT_EQ(nb_cells(), countVertices); - - darts_.pop_back(); - for (Dart d: darts_) - { - if (std::rand()%3 == 1) - { - remove_dart(d); - --countVertices; - } - } - EXPECT_EQ(nb_darts(), countVertices); - EXPECT_EQ(nb_cells(), countVertices); - EXPECT_EQ(nb_cells(), countVertices); - EXPECT_TRUE(check_map_integrity()); -} - /*! * \brief Sewing and unsewing darts correctly changes the topological relations. - * The test perfoms NB_MAX sewing and unsewing on randomly chosen dart of tdarts_. + * The test perfoms NB_MAX sewing and unsewing on randomly chosen dart of darts_. * The number of vertices is unchanged, the number of faces changes correctly * and the map integrity is preserved. */ -TEST_F(CMap1TopoTest, testPhi1SewUnSew) +TEST_F(CMap1TopoTest, phi1_sew_unsew) { addVertices(NB_MAX); int countFaces = NB_MAX; @@ -198,7 +147,7 @@ TEST_F(CMap1TopoTest, testPhi1SewUnSew) * The test adds some faces and check that the number of generated cells is correct * and that the map integrity is preserved. */ -TEST_F(CMap1TopoTest, testAddFace) +TEST_F(CMap1TopoTest, add_face_topo) { add_face_topo(1); EXPECT_EQ(nb_darts(), 1); @@ -218,11 +167,36 @@ TEST_F(CMap1TopoTest, testAddFace) EXPECT_TRUE(check_map_integrity()); } +/*! \brief Removing a face removes all its vertices. + * The test randomly removes 1/3 of the initial faces. + * The number of cells correctly decreases and the map integrity is preserved. + */ +TEST_F(CMap1TopoTest, remove_face) +{ + unsigned int countVertices = addFaces(NB_MAX); + unsigned int countFaces = NB_MAX; + + for (Dart d: darts_) + { + if (std::rand()%3 == 1) { + unsigned int k = degree(Face(d)); + remove_face(d); + countVertices -= k; + --countFaces; + } + } + + EXPECT_EQ(nb_darts(), countVertices); + EXPECT_EQ(nb_cells(), countVertices); + EXPECT_EQ(nb_cells(), countFaces); + EXPECT_TRUE(check_map_integrity()); +} + /*! \brief Spliting a vertex increases the size of its face. * The test performs NB_MAX vertex spliting on vertices of randomly generated faces. * The number of generated cells is correct and the map integrity is preserved. */ -TEST_F(CMap1TopoTest, testSplitVertex) +TEST_F(CMap1TopoTest, split_vertex_topo) { unsigned int countVertices = addFaces(NB_MAX); @@ -232,16 +206,17 @@ TEST_F(CMap1TopoTest, testSplitVertex) split_vertex_topo(d); EXPECT_EQ(degree(Face(d)), k+1); } + EXPECT_EQ(nb_darts(), countVertices+NB_MAX); EXPECT_EQ(nb_cells(), countVertices+NB_MAX); EXPECT_EQ(nb_cells(), NB_MAX); EXPECT_TRUE(check_map_integrity()); } -/*! \brief Removing a vertex decreases the size of its face and removes the face if its size is 1. -* The test performs NB_MAX vertex spliting on vertices of randomly generated faces. -* The number of generated cells is correct and the map integrity is preserved. +/*! \brief Removing a vertex decreases the size of its face and removes its if its degree is 1. +* The test performs NB_MAX vertex removing on vertices of randomly generated faces. +* The number of removed cells is correct and the map integrity is preserved. */ -TEST_F(CMap1TopoTest, testRemoveVertex) +TEST_F(CMap1TopoTest, remove_vertex) { unsigned int countVertices = addFaces(NB_MAX); unsigned int countFaces = NB_MAX; @@ -262,28 +237,7 @@ TEST_F(CMap1TopoTest, testRemoveVertex) } } - EXPECT_EQ(nb_cells(), countVertices); - EXPECT_EQ(nb_cells(), countFaces); - EXPECT_TRUE(check_map_integrity()); -} - -/*! \brief Removing a face removes all its vertices. - * The test randomly removes 1/3 of the initial faces. - * The number of cells correctly decreases and the map integrity is preserved. - */ -TEST_F(CMap1TopoTest, testRemoveFace) -{ - unsigned int countVertices = addFaces(NB_MAX); - unsigned int countFaces = NB_MAX; - - for (Dart d: darts_) - { - unsigned int k = degree(Face(d)); - remove_face(d); - countVertices -= k; - --countFaces; - } - + EXPECT_EQ(nb_darts(), countVertices); EXPECT_EQ(nb_cells(), countVertices); EXPECT_EQ(nb_cells(), countFaces); EXPECT_TRUE(check_map_integrity()); @@ -293,7 +247,7 @@ TEST_F(CMap1TopoTest, testRemoveFace) * The test reverses randomly generated faces. * The number of faces and their degrees do not change and the map integrity is preserved. */ -TEST_F(CMap1TopoTest, testReverseFace) +TEST_F(CMap1TopoTest, reverse_face_topo) { unsigned int countVertices = addFaces(NB_MAX); @@ -302,6 +256,7 @@ TEST_F(CMap1TopoTest, testReverseFace) unsigned int k = degree(Face(d)); std::vector face_darts; + face_darts.reserve(k); foreach_dart_of_orbit(Face(d), [&] (Dart e) { face_darts.push_back(e); }); @@ -316,17 +271,25 @@ TEST_F(CMap1TopoTest, testReverseFace) }); EXPECT_TRUE(face_darts.empty()); } + + EXPECT_EQ(nb_darts(), countVertices); + EXPECT_EQ(nb_cells(), countVertices); + EXPECT_EQ(nb_cells(), NB_MAX); EXPECT_TRUE(check_map_integrity()); } -TEST_F(CMap1TopoTest, testDegree) +/*! \brief The degree of a face is correctly computed. + */ +TEST_F(CMap1TopoTest, degree) { Face f = this->add_face_topo(10); EXPECT_EQ(degree(f),10); } -TEST_F(CMap1TopoTest, testHasDegree) +/*! \brief The degree of a face is correctly tested. + */ +TEST_F(CMap1TopoTest, has_degree) { Face f = this->add_face_topo(10); @@ -336,4 +299,6 @@ TEST_F(CMap1TopoTest, testHasDegree) EXPECT_FALSE(has_degree(f,11)); } +#undef NB_MAX + } // namespace cgogn From b13e49675e4f72d5cbf606218c4861bc9e97d428 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Thu, 3 Mar 2016 16:51:53 +0100 Subject: [PATCH 244/402] add point sprite shader, cleaning shaders & small drawer example --- cgogn/rendering/CMakeLists.txt | 2 + cgogn/rendering/drawer.cpp | 83 ++-- cgogn/rendering/drawer.h | 16 +- cgogn/rendering/examples/simple_viewer.cpp | 86 ++-- cgogn/rendering/shaders/shader_bold_line.cpp | 11 +- cgogn/rendering/shaders/shader_flat.cpp | 50 ++- cgogn/rendering/shaders/shader_flat.h | 15 + cgogn/rendering/shaders/shader_phong.cpp | 43 +- cgogn/rendering/shaders/shader_phong.h | 13 + .../rendering/shaders/shader_point_sprite.cpp | 389 ++++++++++++++++++ cgogn/rendering/shaders/shader_point_sprite.h | 112 +++++ .../rendering/shaders/shader_round_point.cpp | 26 +- .../rendering/shaders/shader_simple_color.cpp | 3 + .../shaders/shader_vector_per_vertex.cpp | 5 + 14 files changed, 734 insertions(+), 120 deletions(-) create mode 100644 cgogn/rendering/shaders/shader_point_sprite.cpp create mode 100644 cgogn/rendering/shaders/shader_point_sprite.h diff --git a/cgogn/rendering/CMakeLists.txt b/cgogn/rendering/CMakeLists.txt index 077bae38..5ecb840b 100644 --- a/cgogn/rendering/CMakeLists.txt +++ b/cgogn/rendering/CMakeLists.txt @@ -17,6 +17,7 @@ set(HEADER_FILES shaders/shader_phong.h shaders/shader_bold_line.h shaders/shader_round_point.h + shaders/shader_point_sprite.h drawer.h ) @@ -29,6 +30,7 @@ set(SOURCE_FILES shaders/shader_phong.cpp shaders/shader_bold_line.cpp shaders/shader_round_point.cpp + shaders/shader_point_sprite.cpp drawer.cpp ) diff --git a/cgogn/rendering/drawer.cpp b/cgogn/rendering/drawer.cpp index c080b74e..6987dc1e 100644 --- a/cgogn/rendering/drawer.cpp +++ b/cgogn/rendering/drawer.cpp @@ -35,9 +35,9 @@ namespace cgogn namespace rendering { -ShaderColorPerVertex* Drawer::shader_cpv_= NULL; -ShaderBoldLine* Drawer::shader_bl_= NULL; -ShaderRoundPoint* Drawer::shader_rp_= NULL; +std::unique_ptr Drawer::shader_cpv_ = nullptr; +std::unique_ptr Drawer::shader_bl_ = nullptr; +std::unique_ptr Drawer::shader_rp_ = nullptr; Drawer::Drawer(QOpenGLFunctions_3_3_Core* ogl33): current_size_(1.0f), @@ -47,14 +47,14 @@ Drawer::Drawer(QOpenGLFunctions_3_3_Core* ogl33): vbo_pos_ = new VBO(3); vbo_col_ = new VBO(3); - if (shader_cpv_ == NULL) - shader_cpv_ = new ShaderColorPerVertex(); + if (!shader_cpv_) + shader_cpv_ = std::unique_ptr(new ShaderColorPerVertex()); vao_cpv_ = shader_cpv_->add_vao(); shader_cpv_->set_vao(vao_cpv_,vbo_pos_,vbo_col_); - if (shader_bl_ == NULL) - shader_bl_ = new ShaderBoldLine(true); + if (!shader_bl_) + shader_bl_ = std::unique_ptr(new ShaderBoldLine(true)); vao_bl_ = shader_bl_->add_vao(); shader_bl_->bind(); @@ -62,8 +62,9 @@ Drawer::Drawer(QOpenGLFunctions_3_3_Core* ogl33): shader_bl_->set_vao(vao_bl_,vbo_pos_,vbo_col_); - if (shader_rp_ == NULL) - shader_rp_ = new ShaderRoundPoint(true); + if (!shader_rp_) + shader_rp_ = std::unique_ptr(new ShaderRoundPoint(true)); + vao_rp_ = shader_rp_->add_vao(); shader_rp_->bind(); shader_rp_->release(); @@ -92,9 +93,17 @@ void Drawer::begin(GLenum mode) switch (mode) { case GL_POINTS: - begins_point_.push_back(PrimParam(data_pos_.size(), mode, current_size_,false)); - current_begin_ = &begins_point_; - break; + if (current_size_ > 2.0) + { + begins_round_point_.push_back(PrimParam(data_pos_.size(), mode, current_size_,current_aa_)); + current_begin_ = &begins_round_point_; + } + else + { + begins_point_.push_back(PrimParam(data_pos_.size(), mode, current_size_,false)); + current_begin_ = &begins_point_; + } + break; case GL_LINES: case GL_LINE_STRIP: case GL_LINE_LOOP: @@ -173,30 +182,16 @@ void Drawer::end_list() void Drawer::callList(const QMatrix4x4& projection, const QMatrix4x4& modelview) { - shader_rp_->bind(); - shader_rp_->set_matrices(projection,modelview); - shader_rp_->bind_vao(vao_bl_); + //classic rendering + shader_cpv_->bind(); + shader_cpv_->set_matrices(projection,modelview); + shader_cpv_->bind_vao(vao_cpv_); for (auto& pp : begins_point_) { - shader_rp_->set_width(pp.width); + ogl33_->glPointSize(pp.width); ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); } - shader_rp_->release_vao(vao_bl_); - shader_rp_->release(); - - - shader_cpv_->bind(); - shader_cpv_->set_matrices(projection,modelview); - shader_cpv_->bind_vao(vao_cpv_); - -// for (auto& pp : begins_point_) -// { -// ogl33_->glPointSize(pp.width); -// ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); -// } - - for (auto& pp : begins_line_) { @@ -212,6 +207,32 @@ void Drawer::callList(const QMatrix4x4& projection, const QMatrix4x4& modelview) shader_cpv_->release(); + // round points + + shader_rp_->bind(); + shader_rp_->set_matrices(projection,modelview); + shader_rp_->bind_vao(vao_bl_); + + for (auto& pp : begins_round_point_) + { + if (pp.aa) + { + ogl33_->glEnable(GL_BLEND); + ogl33_->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + shader_rp_->set_width(pp.width); + ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); + + if (pp.aa) + ogl33_->glDisable(GL_BLEND); + + } + shader_rp_->release_vao(vao_bl_); + shader_rp_->release(); + + + // bold lines shader_bl_->bind(); shader_bl_->set_matrices(projection,modelview); diff --git a/cgogn/rendering/drawer.h b/cgogn/rendering/drawer.h index e8f611a0..f97c6932 100644 --- a/cgogn/rendering/drawer.h +++ b/cgogn/rendering/drawer.h @@ -61,15 +61,18 @@ class CGOGN_RENDERING_API Drawer//: protected QOpenGLFunctions_3_3_Core std::vector data_pos_; std::vector data_col_; std::vector begins_point_; + + std::vector begins_round_point_; + std::vector begins_line_; std::vector begins_bold_line_; std::vector begins_face_; std::vector* current_begin_; - static ShaderColorPerVertex* shader_cpv_; - static ShaderBoldLine* shader_bl_; - static ShaderRoundPoint* shader_rp_; + static std::unique_ptr shader_cpv_; + static std::unique_ptr shader_bl_; + static std::unique_ptr shader_rp_; unsigned int vao_cpv_; unsigned int vao_bl_; @@ -175,6 +178,13 @@ class CGOGN_RENDERING_API Drawer//: protected QOpenGLFunctions_3_3_Core */ inline void pointSize(float ps) { + current_aa_ = false; + current_size_ = ps; + } + + inline void pointSizeAA(float ps) + { + current_aa_ = true; current_size_ = ps; } diff --git a/cgogn/rendering/examples/simple_viewer.cpp b/cgogn/rendering/examples/simple_viewer.cpp index f11052cd..3da38100 100644 --- a/cgogn/rendering/examples/simple_viewer.cpp +++ b/cgogn/rendering/examples/simple_viewer.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include @@ -83,16 +84,16 @@ class Viewer : public QOGLViewer cgogn::rendering::VBO* vbo_pos_; cgogn::rendering::VBO* vbo_norm_; cgogn::rendering::VBO* vbo_color_; - + cgogn::rendering::VBO* vbo_sphere_sz_; cgogn::rendering::ShaderSimpleColor* shader_vertex_; cgogn::rendering::ShaderBoldLine* shader_edge_; cgogn::rendering::ShaderFlat* shader_flat_; cgogn::rendering::ShaderVectorPerVertex* shader_normal_; cgogn::rendering::ShaderPhong* shader_phong_; + cgogn::rendering::ShaderPointSprite* shader_point_sprite_; cgogn::rendering::Drawer* drawer_; -// cgogn::rendering::Drawer* drawer2_; bool phong_rendering_; bool flat_rendering_; @@ -131,10 +132,13 @@ Viewer::~Viewer() delete vbo_pos_; delete vbo_norm_; delete vbo_color_; + delete vbo_sphere_sz_; delete shader_vertex_; delete shader_flat_; delete shader_normal_; delete shader_phong_; + delete shader_point_sprite_; + delete drawer_; } Viewer::Viewer() : @@ -145,9 +149,14 @@ Viewer::Viewer() : render_(nullptr), vbo_pos_(nullptr), vbo_norm_(nullptr), + vbo_color_(nullptr), + vbo_sphere_sz_(nullptr), shader_vertex_(nullptr), shader_flat_(nullptr), shader_normal_(nullptr), + shader_phong_(nullptr), + shader_point_sprite_(nullptr), + drawer_(nullptr), phong_rendering_(true), flat_rendering_(false), vertices_rendering_(false), @@ -196,12 +205,13 @@ void Viewer::draw() camera()->getModelViewMatrix(view); glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(1.0f, 1.0f); + glPolygonOffset(1.0f, 2.0f); if (flat_rendering_) { shader_flat_->bind(); shader_flat_->set_matrices(proj,view); +// shader_flat_->set_local_light_position(QVector3D(bb_.max()[0],bb_.max()[1],bb_.max()[2]), view); shader_flat_->bind_vao(0); render_->draw(cgogn::rendering::TRIANGLES); shader_flat_->release_vao(0); @@ -222,16 +232,12 @@ void Viewer::draw() if (vertices_rendering_) { - shader_vertex_->bind(); - shader_vertex_->set_matrices(proj,view); - shader_vertex_->bind_vao(0); - - glPointSize(3.0f); - shader_vertex_->set_color(QColor(255,0,0)); + shader_point_sprite_->bind(); + shader_point_sprite_->set_matrices(proj,view); + shader_point_sprite_->bind_vao(0); render_->draw(cgogn::rendering::POINTS); - - shader_vertex_->release_vao(0); - shader_vertex_->release(); + shader_point_sprite_->release_vao(0); + shader_point_sprite_->release(); } @@ -247,7 +253,6 @@ void Viewer::draw() glDisable(GL_BLEND); shader_edge_->release_vao(0); shader_edge_->release(); - } if (normal_rendering_) @@ -281,6 +286,13 @@ void Viewer::init() return {float(std::abs(n[0])), float(std::abs(n[1])), float(std::abs(n[2]))}; }); + // fill a sphere size vbo + vbo_sphere_sz_ = new cgogn::rendering::VBO(1); + cgogn::rendering::update_vbo(vertex_normal_, *vbo_sphere_sz_,[&] (const Vec3& n) -> float + { + return bb_.diag_size()/1000.0 * (1.0 + 2.0*std::abs(n[2])); + }); + render_ = new cgogn::rendering::MapRender(); @@ -288,9 +300,18 @@ void Viewer::init() render_->init_primitives(map_, cgogn::rendering::LINES, vertex_position_); render_->init_primitives(map_, cgogn::rendering::TRIANGLES, vertex_position_); - shader_vertex_ = new cgogn::rendering::ShaderSimpleColor; - shader_vertex_->add_vao(); - shader_vertex_->set_vao(0, vbo_pos_); +// shader_vertex_ = new cgogn::rendering::ShaderSimpleColor; +// shader_vertex_->add_vao(); +// shader_vertex_->set_vao(0, vbo_pos_); + + shader_point_sprite_ = new cgogn::rendering::ShaderPointSprite(true,true); + shader_point_sprite_->add_vao(); + shader_point_sprite_->set_vao(0, vbo_pos_,vbo_color_,vbo_sphere_sz_); + shader_point_sprite_->bind(); + shader_point_sprite_->set_size(bb_.diag_size()/1000.0); + shader_point_sprite_->set_color(QColor(255,0,0)); + shader_point_sprite_->release(); + shader_edge_ = new cgogn::rendering::ShaderBoldLine() ; shader_edge_->add_vao(); @@ -302,7 +323,6 @@ void Viewer::init() shader_flat_ = new cgogn::rendering::ShaderFlat; shader_flat_->add_vao(); shader_flat_->set_vao(0, vbo_pos_); - shader_flat_->bind(); shader_flat_->set_front_color(QColor(0,200,0)); shader_flat_->set_back_color(QColor(0,0,200)); @@ -312,7 +332,6 @@ void Viewer::init() shader_normal_ = new cgogn::rendering::ShaderVectorPerVertex; shader_normal_->add_vao(); shader_normal_->set_vao(0, vbo_pos_, vbo_norm_); - shader_normal_->bind(); shader_normal_->set_color(QColor(200,0,200)); shader_normal_->set_length(bb_.diag_size()/50); @@ -322,52 +341,35 @@ void Viewer::init() shader_phong_ = new cgogn::rendering::ShaderPhong(true); shader_phong_->add_vao(); shader_phong_->set_vao(0, vbo_pos_, vbo_norm_, vbo_color_); - shader_phong_->bind(); -// shader_phong_->set_front_color(QColor(0,200,0)); -// shader_phong_->set_back_color(QColor(0,0,200)); - shader_phong_->set_ambiant_color(QColor(5,5,5)); - shader_phong_->set_double_side(true); - shader_phong_->set_specular_color(QColor(255,255,255)); - shader_phong_->set_specular_coef(10.0); +// shader_phong_->set_ambiant_color(QColor(5,5,5)); +// shader_phong_->set_double_side(true); +// shader_phong_->set_specular_color(QColor(255,255,255)); +// shader_phong_->set_specular_coef(10.0); shader_phong_->release(); // drawer for simple old-school g1 rendering drawer_ = new cgogn::rendering::Drawer(this); drawer_->new_list(); -// drawer_->begin(GL_LINES); -// drawer_->color3f(0.5,0.5,0.5); -// drawer_->vertex3fv(bb_.min().data()); // fv work with float & double -// drawer_->vertex3fv(bb_.max().data()); -// drawer_->end(); - drawer_->lineWidth(2.0); + drawer_->lineWidthAA(2.0); drawer_->begin(GL_LINE_LOOP); - drawer_->color3f(1.0,0.0,0.0); + drawer_->color3f(1.0,1.0,1.0); drawer_->vertex3f(bb_.min()[0],bb_.min()[1],bb_.min()[2]); - drawer_->color3f(0.0,1.0,1.0); drawer_->vertex3f(bb_.max()[0],bb_.min()[1],bb_.min()[2]); - drawer_->color3f(1.0,0.0,1.0); drawer_->vertex3f(bb_.max()[0],bb_.max()[1],bb_.min()[2]); - drawer_->color3f(1.0,1.0,0.0); drawer_->vertex3f(bb_.min()[0],bb_.max()[1],bb_.min()[2]); drawer_->vertex3f(bb_.min()[0],bb_.max()[1],bb_.max()[2]); drawer_->vertex3f(bb_.max()[0],bb_.max()[1],bb_.max()[2]); drawer_->vertex3f(bb_.max()[0],bb_.min()[1],bb_.max()[2]); drawer_->vertex3f(bb_.min()[0],bb_.min()[1],bb_.max()[2]); drawer_->end(); -// drawer_->pointSize(10.0); - drawer_->lineWidthAA(1.2); drawer_->begin(GL_LINES); - drawer_->color3f(1.0,1.0,1.0); + drawer_->color3f(1.0,1.0,1.0); drawer_->vertex3f(bb_.min()[0],bb_.min()[1],bb_.min()[2]); drawer_->vertex3f(bb_.min()[0],bb_.max()[1],bb_.min()[2]); drawer_->vertex3f(bb_.min()[0],bb_.min()[1],bb_.max()[2]); drawer_->vertex3f(bb_.min()[0],bb_.max()[1],bb_.max()[2]); - drawer_->end(); - drawer_->lineWidthAA(2.0); - drawer_->begin(GL_LINES); - drawer_->color3f(0.0,1.0,0.0); drawer_->vertex3f(bb_.max()[0],bb_.min()[1],bb_.min()[2]); drawer_->vertex3f(bb_.max()[0],bb_.min()[1],bb_.max()[2]); drawer_->vertex3f(bb_.max()[0],bb_.max()[1],bb_.min()[2]); diff --git a/cgogn/rendering/shaders/shader_bold_line.cpp b/cgogn/rendering/shaders/shader_bold_line.cpp index 1a292cbb..007d61e6 100644 --- a/cgogn/rendering/shaders/shader_bold_line.cpp +++ b/cgogn/rendering/shaders/shader_bold_line.cpp @@ -191,9 +191,7 @@ ShaderBoldLine::ShaderBoldLine(bool color_per_vertex) prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); prg_.bindAttributeLocation("vertex_color", ATTRIB_COLOR); prg_.link(); - get_matrices_uniforms(); - unif_width_ = prg_.uniformLocation("lineWidths"); } else { @@ -202,18 +200,19 @@ ShaderBoldLine::ShaderBoldLine(bool color_per_vertex) prg_.addShaderFromSourceCode(QOpenGLShader::Fragment, fragment_shader_source_); prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); prg_.link(); - get_matrices_uniforms(); - unif_color_ = prg_.uniformLocation("lineColor"); - unif_width_ = prg_.uniformLocation("lineWidths"); } + unif_color_ = prg_.uniformLocation("lineColor"); + unif_width_ = prg_.uniformLocation("lineWidths"); + } void ShaderBoldLine::set_color(const QColor& rgb) { - prg_.setUniformValue(unif_color_, rgb); + if (unif_color_ >= 0) + prg_.setUniformValue(unif_color_, rgb); } void ShaderBoldLine::set_width(float wpix) diff --git a/cgogn/rendering/shaders/shader_flat.cpp b/cgogn/rendering/shaders/shader_flat.cpp index 4c5a8acf..6bc481b5 100644 --- a/cgogn/rendering/shaders/shader_flat.cpp +++ b/cgogn/rendering/shaders/shader_flat.cpp @@ -53,12 +53,12 @@ const char* ShaderFlat::fragment_shader_source_ = "uniform vec4 front_color;\n" "uniform vec4 back_color;\n" "uniform vec4 ambiant_color;\n" - "vec3 light_pos = vec3(100,100,1000);\n" + "uniform vec3 lightPosition;\n" "in vec3 pos;\n" "void main() {\n" " vec3 N = normalize(cross(dFdx(pos),dFdy(pos)));\n" - " vec3 L = normalize(light_pos-pos);\n" - " float lambert = abs(dot(N,L));\n" + " vec3 L = normalize(lightPosition-pos);\n" + " float lambert = dot(N,L);\n" " if (gl_FrontFacing)\n" " fragColor = ambiant_color+lambert*front_color;\n" " else\n" @@ -87,14 +87,17 @@ const char* ShaderFlat::fragment_shader_source2_ = "uniform vec4 front_color;\n" "uniform vec4 back_color;\n" "uniform vec4 ambiant_color;\n" - "vec3 light_pos = vec3(100,100,1000);\n" + "uniform vec3 lightPosition;\n" "in vec3 pos;\n" "in vec3 col;\n" "void main() {\n" " vec3 N = normalize(cross(dFdx(pos),dFdy(pos)));\n" - " vec3 L = normalize(light_pos-pos);\n" - " float lambert = abs(dot(N,L));\n" - " fragColor = ambiant_color+vec4(lambert*col,1.0);\n" + " vec3 L = normalize(lightPosition-pos);\n" + " float lambert = dot(N,L);\n" + " if (gl_FrontFacing)\n" + " fragColor = ambiant_color+vec4(lambert*col,1.0);;\n" + " else\n" + " fragColor = ambiant_color-vec4(lambert*col,1.0);;\n" "}\n"; @@ -108,7 +111,6 @@ ShaderFlat::ShaderFlat(bool color_per_vertex) prg_.bindAttributeLocation("vertex_col", ATTRIB_COLOR); prg_.link(); get_matrices_uniforms(); - unif_ambiant_color_ = prg_.uniformLocation("ambiant_color"); } else { @@ -117,22 +119,42 @@ ShaderFlat::ShaderFlat(bool color_per_vertex) prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); prg_.link(); get_matrices_uniforms(); - unif_front_color_ = prg_.uniformLocation("front_color"); - unif_back_color_ = prg_.uniformLocation("back_color"); - unif_ambiant_color_ = prg_.uniformLocation("ambiant_color"); + } + unif_front_color_ = prg_.uniformLocation("front_color"); + unif_back_color_ = prg_.uniformLocation("back_color"); + unif_ambiant_color_ = prg_.uniformLocation("ambiant_color"); + unif_light_position_ = prg_.uniformLocation("lightPosition"); + + //default param + bind(); + set_light_position(QVector3D(10.0f,100.0f,1000.0f)); + set_front_color(QColor(250,0,0)); + set_back_color(QColor(0,250,5)); + set_ambiant_color(QColor(5,5,5)); + release(); +} +void ShaderFlat::set_light_position(const QVector3D& l) +{ + prg_.setUniformValue(unif_light_position_,l); +} - } +void ShaderFlat::set_local_light_position(const QVector3D& l, const QMatrix4x4& view_matrix) +{ + QVector4D loc4 = view_matrix.map(QVector4D(l,1.0)); + prg_.setUniformValue(unif_light_position_, QVector3D(loc4)/loc4.w()); } void ShaderFlat::set_front_color(const QColor& rgb) { - prg_.setUniformValue(unif_front_color_,rgb); + if (unif_front_color_>=0) + prg_.setUniformValue(unif_front_color_,rgb); } void ShaderFlat::set_back_color(const QColor& rgb) { - prg_.setUniformValue(unif_back_color_,rgb); + if (unif_back_color_>=0) + prg_.setUniformValue(unif_back_color_,rgb); } void ShaderFlat::set_ambiant_color(const QColor& rgb) diff --git a/cgogn/rendering/shaders/shader_flat.h b/cgogn/rendering/shaders/shader_flat.h index 2c1856c2..40cc11a0 100644 --- a/cgogn/rendering/shaders/shader_flat.h +++ b/cgogn/rendering/shaders/shader_flat.h @@ -54,6 +54,7 @@ class CGOGN_RENDERING_API ShaderFlat : public ShaderProgram int unif_front_color_; int unif_back_color_; int unif_ambiant_color_; + int unif_light_position_; public: @@ -77,6 +78,20 @@ class CGOGN_RENDERING_API ShaderFlat : public ShaderProgram */ void set_ambiant_color(const QColor& rgb); + /** + * @brief set light position relative to screen + * @param l light position + */ + void set_light_position(const QVector3D& l); + + + /** + * @brief set light position relative to world + * @param l light position + * @param view_matrix + */ + void set_local_light_position(const QVector3D& l, const QMatrix4x4& view_matrix); + /** * @brief set a vao configuration * @param i id of vao (0,1,....) diff --git a/cgogn/rendering/shaders/shader_phong.cpp b/cgogn/rendering/shaders/shader_phong.cpp index 5d8ee653..03d55343 100644 --- a/cgogn/rendering/shaders/shader_phong.cpp +++ b/cgogn/rendering/shaders/shader_phong.cpp @@ -156,13 +156,7 @@ ShaderPhong::ShaderPhong(bool color_per_vertex) prg_.bindAttributeLocation("vertex_normal", ATTRIB_NORM); prg_.bindAttributeLocation("vertex_color", ATTRIB_COLOR); prg_.link(); - get_matrices_uniforms(); - - unif_ambiant_color_ = prg_.uniformLocation("ambiant_color"); - unif_spec_color_ = prg_.uniformLocation("spec_color"); - unif_spec_coef_ = prg_.uniformLocation("spec_coef"); - unif_double_side_ = prg_.uniformLocation("double_side"); } else { @@ -171,16 +165,37 @@ ShaderPhong::ShaderPhong(bool color_per_vertex) prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); prg_.bindAttributeLocation("vertex_normal", ATTRIB_NORM); prg_.link(); - get_matrices_uniforms(); - - unif_front_color_ = prg_.uniformLocation("front_color"); - unif_back_color_ = prg_.uniformLocation("back_color"); - unif_ambiant_color_ = prg_.uniformLocation("ambiant_color"); - unif_spec_color_ = prg_.uniformLocation("spec_color"); - unif_spec_coef_ = prg_.uniformLocation("spec_coef"); - unif_double_side_ = prg_.uniformLocation("double_side"); } + unif_front_color_ = prg_.uniformLocation("front_color"); + unif_back_color_ = prg_.uniformLocation("back_color"); + unif_ambiant_color_ = prg_.uniformLocation("ambiant_color"); + unif_spec_color_ = prg_.uniformLocation("spec_color"); + unif_spec_coef_ = prg_.uniformLocation("spec_coef"); + unif_double_side_ = prg_.uniformLocation("double_side"); + unif_light_position_ = prg_.uniformLocation("lightPosition"); + + //default param + bind(); + set_light_position(QVector3D(10.0f,100.0f,1000.0f)); + set_front_color(QColor(250,0,0)); + set_back_color(QColor(0,250,5)); + set_ambiant_color(QColor(5,5,5)); + set_specular_color(QColor(100,100,100)); + set_specular_coef(50.0f); + set_double_side(true); + release(); +} + +void ShaderPhong::set_light_position(const QVector3D& l) +{ + prg_.setUniformValue(unif_light_position_,l); +} + +void ShaderPhong::set_local_light_position(const QVector3D& l, const QMatrix4x4& view_matrix) +{ + QVector4D loc4 = view_matrix.map(QVector4D(l,1.0)); + prg_.setUniformValue(unif_light_position_, QVector3D(loc4)/loc4.w()); } diff --git a/cgogn/rendering/shaders/shader_phong.h b/cgogn/rendering/shaders/shader_phong.h index 3fc5aa94..85eae2b1 100644 --- a/cgogn/rendering/shaders/shader_phong.h +++ b/cgogn/rendering/shaders/shader_phong.h @@ -59,6 +59,7 @@ class CGOGN_RENDERING_API ShaderPhong : public ShaderProgram int unif_spec_color_; int unif_spec_coef_; int unif_double_side_; + int unif_light_position_; public: @@ -100,6 +101,18 @@ class CGOGN_RENDERING_API ShaderPhong : public ShaderProgram */ void set_double_side(bool ts); + /** + * @brief set_light_position + * @param l + */ + void set_light_position(const QVector3D& l); + + /** + * @brief set light position relative to world + * @param l light position + * @param view_matrix + */ + void set_local_light_position(const QVector3D& l, const QMatrix4x4& view_matrix); /** * @brief set a vao configuration diff --git a/cgogn/rendering/shaders/shader_point_sprite.cpp b/cgogn/rendering/shaders/shader_point_sprite.cpp new file mode 100644 index 00000000..23f8b721 --- /dev/null +++ b/cgogn/rendering/shaders/shader_point_sprite.cpp @@ -0,0 +1,389 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#define CGOGN_RENDERING_DLL_EXPORT + +#include + +#include +#include +#include + +namespace cgogn +{ + +namespace rendering +{ + +const char* ShaderPointSprite::vertex_shader_source_ = +"#version 150\n" +"in vec3 vertex_pos;\n" +"void main() {\n" +" gl_Position = vec4(vertex_pos,1.0);\n" +"}\n"; + + +const char* ShaderPointSprite::geometry_shader_source_ = +"#version 150\n" +"layout (points) in;\n" +"layout (triangle_strip, max_vertices=4) out;\n" +"uniform mat4 projection_matrix;\n" +"uniform mat4 model_view_matrix;\n" +"uniform float pointSize;\n" +"out vec2 spriteCoord;\n" +"out vec3 sphereCenter;\n" +"void corner(vec4 center, float x, float y)\n" +"{\n" +" spriteCoord = vec2(x,y);\n" +" vec4 pos = center + vec4(pointSize*x, pointSize*y, 0.0, 0.0);\n" +" gl_Position = projection_matrix * pos;\n" +" EmitVertex();\n" +"}\n" +"void main()\n" +"{\n" + +" vec4 posCenter = model_view_matrix * gl_in[0].gl_Position;\n" +" sphereCenter = posCenter.xyz;\n" +" corner(posCenter, -1.4, 1.4);\n" +" corner(posCenter, -1.4,-1.4);\n" +" corner(posCenter, 1.4, 1.4);\n" +" corner(posCenter, 1.4,-1.4);\n" +" EndPrimitive();\n" +"}\n"; + + +const char* ShaderPointSprite::fragment_shader_source_ = +"#version 150\n" +"uniform mat4 projection_matrix;\n" +"uniform vec4 color;\n" +"uniform vec4 ambiant;\n" +"uniform vec3 lightPos;\n" +"uniform float pointSize;\n" +"in vec2 spriteCoord;\n" +"in vec3 sphereCenter;\n" +"out vec3 fragColor;\n" +"void main() {\n" +" vec3 billboard_frag_pos = sphereCenter + vec3(spriteCoord, 0.0) * pointSize;\n" +" vec3 ray_direction = normalize(billboard_frag_pos);\n" +" float TD = -dot(ray_direction,sphereCenter);\n" +" float c = dot(sphereCenter, sphereCenter) - pointSize * pointSize;\n" +" float arg = TD * TD - c;\n" +" if (arg < 0.0)\n" +" discard;\n" +" float t = -c / (TD - sqrt(arg));\n" +" vec3 frag_position_eye = ray_direction * t ;\n" +" vec4 pos = projection_matrix * vec4(frag_position_eye, 1.0);\n" +" gl_FragDepth = (pos.z / pos.w + 1.0) / 2.0;\n" +" vec3 N = normalize(frag_position_eye - sphereCenter);\n" +" vec3 L = normalize (lightPos - frag_position_eye);\n" +" float lambertTerm = dot(N,L);\n" +" vec4 result = color*lambertTerm;\n" +" result += ambiant;\n" +" fragColor = result.rgb;\n" +"}\n"; + + + +const char* ShaderPointSprite::vertex_shader_source2_ = +"in vec3 vertex_pos;\n" +"#if WITH_COLOR == 1\n" +"in vec3 vertex_col;\n" +"out vec3 color_v;\n" +"#endif\n" +"#if WITH_SIZE == 1\n" +"in float vertex_size;\n" +"out float size_v;\n" +"#endif\n" +"void main() {\n" +" #if WITH_COLOR == 1\n" +" color_v = vertex_col;\n" +" #endif\n" +" #if WITH_SIZE == 1\n" +" size_v = vertex_size;\n" +" #endif\n" +" gl_Position = vec4(vertex_pos,1.0);\n" +"}\n"; + + +const char* ShaderPointSprite::geometry_shader_source2_ = +"layout (points) in;\n" +"layout (triangle_strip, max_vertices=4) out;\n" +"uniform mat4 projection_matrix;\n" +"uniform mat4 model_view_matrix;\n" + +"#if WITH_COLOR == 1\n" +"in vec3 color_v[];\n" +"out vec3 color_f;\n" +"#endif\n" + +"#if WITH_SIZE == 1\n" +"in float size_v[];\n" +"out float size_f;\n" +"#else\n" +"uniform float pointSize;\n" +"#endif\n" + +"out vec2 spriteCoord;\n" +"out vec3 sphereCenter;\n" + +"#if ((WITH_COLOR == 1) && (WITH_SIZE == 1)) \n" +"void corner(vec4 center, float x, float y)\n" +"{\n" +" spriteCoord = vec2(x,y);\n" +" vec4 pos = center + vec4(size_v[0]*x, size_v[0]*y, 0.0, 0.0);\n" +" size_f = size_v[0];\n" +" color_f = color_v[0];\n" +" gl_Position = projection_matrix * pos;\n" +" EmitVertex();\n" +"}\n" +"#endif\n" +"#if ((WITH_COLOR == 1) && (WITH_SIZE == 0)) \n" +"void corner(vec4 center, float x, float y)\n" +"{\n" +" spriteCoord = vec2(x,y);\n" +" vec4 pos = center + vec4(pointSize*x, pointSize*y, 0.0, 0.0);\n" +" color_f = color_v[0];\n" +" gl_Position = projection_matrix * pos;\n" +" EmitVertex();\n" +"}\n" +"#endif\n" +"#if ((WITH_COLOR == 0) && (WITH_SIZE == 1)) \n" +"void corner(vec4 center, float x, float y)\n" +"{\n" +" spriteCoord = vec2(x,y);\n" +" vec4 pos = center + vec4(size_v[0]*x, size_v[0]*y, 0.0, 0.0);\n" +" size_f = size_v[0];\n" +" gl_Position = projection_matrix * pos;\n" +" EmitVertex();\n" +"}\n" +"#endif\n" +"#if ((WITH_COLOR == 0) && (WITH_SIZE == 0)) \n" +"void corner(vec4 center, float x, float y)\n" +"{\n" +" spriteCoord = vec2(x,y);\n" +" vec4 pos = center + vec4(pointSize*x, pointSize*y, 0.0, 0.0);\n" +" gl_Position = projection_matrix * pos;\n" +" EmitVertex();\n" +"}\n" +"#endif\n" +"void main()\n" +"{\n" + +" vec4 posCenter = model_view_matrix * gl_in[0].gl_Position;\n" +" sphereCenter = posCenter.xyz;\n" +" corner(posCenter, -1.4, 1.4);\n" +" corner(posCenter, -1.4,-1.4);\n" +" corner(posCenter, 1.4, 1.4);\n" +" corner(posCenter, 1.4,-1.4);\n" +" EndPrimitive();\n" +"}\n"; + + +const char* ShaderPointSprite::fragment_shader_source2_ = +"uniform mat4 projection_matrix;\n" +"uniform vec4 ambiant;\n" +"uniform vec3 lightPos;\n" +"#if WITH_SIZE == 1\n" +"in float size_f;\n" +"#else\n" +"uniform float pointSize;\n" +"#endif\n" +"#if WITH_COLOR == 1\n" +"in vec3 color_f;\n" +"#else\n" +"uniform vec4 color;\n" +"#endif\n" +"in vec2 spriteCoord;\n" +"in vec3 sphereCenter;\n" +"out vec3 fragColor;\n" + +"void main() {\n" +" #if WITH_SIZE == 1\n" +" float pointSize=size_f;\n" +" #endif\n" +" vec3 billboard_frag_pos = sphereCenter + vec3(spriteCoord, 0.0) * pointSize;\n" +" vec3 ray_direction = normalize(billboard_frag_pos);\n" +" float TD = -dot(ray_direction,sphereCenter);\n" +" float c = dot(sphereCenter, sphereCenter) - pointSize * pointSize;\n" +" float arg = TD * TD - c;\n" +" if (arg < 0.0)\n" +" discard;\n" +" float t = -c / (TD - sqrt(arg));\n" +" vec3 frag_position_eye = ray_direction * t ;\n" +" vec4 pos = projection_matrix * vec4(frag_position_eye, 1.0);\n" +" gl_FragDepth = (pos.z / pos.w + 1.0) / 2.0;\n" +" vec3 N = normalize(frag_position_eye - sphereCenter);\n" +" vec3 L = normalize (lightPos - frag_position_eye);\n" +" float lambertTerm = dot(N,L);\n" +" #if WITH_COLOR == 1\n" +" vec4 result = vec4(color_f*lambertTerm,1.0);\n" +" #else\n" +" vec4 result = color*lambertTerm;\n" +" #endif\n" +" result += ambiant;\n" +" fragColor = result.rgb;\n" +"}\n"; + + + + + +ShaderPointSprite::ShaderPointSprite(bool color_per_vertex, bool size_per_vertex) +{ + std::string vs("#version 150\n"); + std::string fs("#version 150\n"); + std::string gs("#version 150\n"); + if (color_per_vertex) + { + vs += std::string("#define WITH_COLOR 1\n"); + gs += std::string("#define WITH_COLOR 1\n"); + fs += std::string("#define WITH_COLOR 1\n"); + } + if (size_per_vertex) + { + vs += std::string("#define WITH_SIZE 1\n"); + gs += std::string("#define WITH_SIZE 1\n"); + fs += std::string("#define WITH_SIZE 1\n"); + } + vs += std::string(vertex_shader_source2_); + gs += std::string(geometry_shader_source2_); + fs += std::string(fragment_shader_source2_); + + + prg_.addShaderFromSourceCode(QOpenGLShader::Vertex, vs.c_str()); + prg_.addShaderFromSourceCode(QOpenGLShader::Geometry, gs.c_str()); + prg_.addShaderFromSourceCode(QOpenGLShader::Fragment, fs.c_str()); + prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); + + if (color_per_vertex) + prg_.bindAttributeLocation("vertex_color", ATTRIB_COLOR); + + if (size_per_vertex) + prg_.bindAttributeLocation("vertex_size", ATTRIB_SIZE); + + prg_.link(); + get_matrices_uniforms(); + +// } +// else +// { +// prg_.addShaderFromSourceCode(QOpenGLShader::Vertex, vertex_shader_source2_); +// prg_.addShaderFromSourceCode(QOpenGLShader::Geometry, geometry_shader_source2_); +// prg_.addShaderFromSourceCode(QOpenGLShader::Fragment, fragment_shader_source2_); +// prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); +// prg_.link(); + +// get_matrices_uniforms(); +// } + unif_color_ = prg_.uniformLocation("color"); + unif_ambiant_ = prg_.uniformLocation("ambiant"); + unif_light_pos_ = prg_.uniformLocation("lightPos"); + unif_size_ = prg_.uniformLocation("pointSize"); + + + set_color(QColor(250,0,0)); + set_ambiant(QColor(5,5,5)); + set_size(1.0f); + set_light_position(QVector3D(10,10,1000)); +} + + + +void ShaderPointSprite::set_color(const QColor& rgb) +{ + if (unif_color_>=0) + prg_.setUniformValue(unif_color_, rgb); +} + +void ShaderPointSprite::set_ambiant(const QColor& rgb) +{ + if (unif_ambiant_>=0) + prg_.setUniformValue(unif_ambiant_, rgb); +} + +void ShaderPointSprite::set_size(float w) +{ +// if (unif_size_>=0) + prg_.setUniformValue(unif_size_, w); +} + +void ShaderPointSprite::set_light_position(const QVector3D& l) +{ + prg_.setUniformValue(unif_light_pos_,l); +} + +void ShaderPointSprite::set_local_light_position(const QVector3D& l, const QMatrix4x4& view_matrix) +{ + QVector4D loc4 = view_matrix.map(QVector4D(l,1.0)); + prg_.setUniformValue(unif_light_pos_, QVector3D(loc4)/loc4.w()); +} + + + +bool ShaderPointSprite::set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color, VBO* vbo_size) +{ + if (i >= vaos_.size()) + { + std::cerr << "VAO number " << i << " does not exist" << std::endl; + return false; + } + + QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); + + prg_.bind(); + vaos_[i]->bind(); + + // position vbo + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ATTRIB_POS); + ogl->glVertexAttribPointer(ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + + if (vbo_color) + { + // color vbo + vbo_color->bind(); + ogl->glEnableVertexAttribArray(ATTRIB_COLOR); + ogl->glVertexAttribPointer(ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_color->release(); + } + + if (vbo_size) + { + // size vbo + vbo_size->bind(); + ogl->glEnableVertexAttribArray(ATTRIB_SIZE); + ogl->glVertexAttribPointer(ATTRIB_SIZE, vbo_size->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_size->release(); + } + + + vaos_[i]->release(); + prg_.release(); + + return true; +} + +} // namespace rendering + +} // namespace cgogn diff --git a/cgogn/rendering/shaders/shader_point_sprite.h b/cgogn/rendering/shaders/shader_point_sprite.h new file mode 100644 index 00000000..3a26eda4 --- /dev/null +++ b/cgogn/rendering/shaders/shader_point_sprite.h @@ -0,0 +1,112 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef RENDERING_SHADER_POINT_SPRITE_H_ +#define RENDERING_SHADER_POINT_SPRITE_H_ + +#include +#include +#include + +namespace cgogn +{ + +namespace rendering +{ + +class CGOGN_RENDERING_API ShaderPointSprite : public ShaderProgram +{ + static const char* vertex_shader_source_; + static const char* geometry_shader_source_; + static const char* fragment_shader_source_; + + static const char* vertex_shader_source2_; + static const char* geometry_shader_source2_; + static const char* fragment_shader_source2_; + + enum + { + ATTRIB_POS = 0, + ATTRIB_COLOR, + ATTRIB_SIZE + }; + + // uniform ids + int unif_color_; + int unif_size_; + int unif_ambiant_; + int unif_light_pos_; + +public: + + ShaderPointSprite(bool color_per_vertex = false, bool size_per_vertex = false); + + /** + * @brief set current color + * @param rgb + */ + void set_color(const QColor& rgb); + + /** + * @brief set ambiant color + * @param rgb + */ + void set_ambiant(const QColor& rgb); + + /** + * @brief set light position relative to screen + * @param l + */ + void set_light_position(const QVector3D& l); + + /** + * @brief set light position relative to world + * @param l + * @param view_matrix + */ + void set_local_light_position(const QVector3D& l, const QMatrix4x4& view_matrix); + + + + /** + * @brief set the size of sphere (call before each draw) + * @param w size ofs phere + */ + void set_size(float w); + + /** + * @brief set a vao configuration + * @param i vao id (0,1,...) + * @param vbo_pos pointer on position vbo (XYZ) + * @param vbo_color pointer on color vbo + * @param vbo_size pointer on size (diameters of spheres) vbo + * @return true if ok + */ + bool set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color=NULL, VBO* vbo_size=NULL); +}; + +} // namespace rendering + +} // namespace cgogn + +#endif // RENDERING_SHADER_POINT_SPRITE_H_ diff --git a/cgogn/rendering/shaders/shader_round_point.cpp b/cgogn/rendering/shaders/shader_round_point.cpp index 5e05868e..ab9f44d8 100644 --- a/cgogn/rendering/shaders/shader_round_point.cpp +++ b/cgogn/rendering/shaders/shader_round_point.cpp @@ -26,6 +26,7 @@ #include #include +#include #include namespace cgogn @@ -76,8 +77,10 @@ const char* ShaderRoundPoint::fragment_shader_source_ = "in vec2 local;\n" "out vec4 fragColor;\n" "void main() {\n" -" if (dot(local,local)>1.0) discard;\n" -" fragColor = color;\n" + +" float r2 = dot(local,local);\n" +" if (r2 > 1.0) discard;\n" +" fragColor = vec4(color.rgb,(1.0-r2*r2));\n" "}\n"; @@ -128,10 +131,11 @@ const char* ShaderRoundPoint::fragment_shader_source2_ = "#version 150\n" "in vec2 local;\n" "in vec3 color_f;\n" -"out vec3 fragColor;\n" +"out vec4 fragColor;\n" "void main() {\n" -" if (dot(local,local)>1.0) discard;\n" -" fragColor = color_f;\n" +" float r2 = dot(local,local);\n" +" if (r2 > 1.0) discard;\n" +" fragColor = vec4(color_f,(1.0-r2*r2));\n" "}\n"; @@ -145,9 +149,7 @@ ShaderRoundPoint::ShaderRoundPoint(bool color_per_vertex) prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); prg_.bindAttributeLocation("vertex_color", ATTRIB_COLOR); prg_.link(); - get_matrices_uniforms(); - unif_width_ = prg_.uniformLocation("pointSizes"); } else { @@ -158,16 +160,20 @@ ShaderRoundPoint::ShaderRoundPoint(bool color_per_vertex) prg_.link(); get_matrices_uniforms(); - unif_color_ = prg_.uniformLocation("color"); - unif_width_ = prg_.uniformLocation("pointSizes"); } + unif_color_ = prg_.uniformLocation("color"); + unif_width_ = prg_.uniformLocation("pointSizes"); + + set_width(3.0f); + set_color(QColor(255,255,255)); } void ShaderRoundPoint::set_color(const QColor& rgb) { - prg_.setUniformValue(unif_color_, rgb); + if (unif_color_) + prg_.setUniformValue(unif_color_, rgb); } void ShaderRoundPoint::set_width(float wpix) diff --git a/cgogn/rendering/shaders/shader_simple_color.cpp b/cgogn/rendering/shaders/shader_simple_color.cpp index 67fde08c..5f06f895 100644 --- a/cgogn/rendering/shaders/shader_simple_color.cpp +++ b/cgogn/rendering/shaders/shader_simple_color.cpp @@ -62,6 +62,9 @@ ShaderSimpleColor::ShaderSimpleColor() get_matrices_uniforms(); unif_color_ = prg_.uniformLocation("color"); + + //default param + set_color(QColor(255,255,255)); } void ShaderSimpleColor::set_color(const QColor& rgb) diff --git a/cgogn/rendering/shaders/shader_vector_per_vertex.cpp b/cgogn/rendering/shaders/shader_vector_per_vertex.cpp index c4539ec3..cb775e04 100644 --- a/cgogn/rendering/shaders/shader_vector_per_vertex.cpp +++ b/cgogn/rendering/shaders/shader_vector_per_vertex.cpp @@ -26,6 +26,7 @@ #include #include +#include #include namespace cgogn @@ -82,6 +83,10 @@ ShaderVectorPerVertex::ShaderVectorPerVertex() unif_color_ = prg_.uniformLocation("color"); unif_length_ = prg_.uniformLocation("length"); + + //default param + set_color(QColor(255,255,255)); + set_length(1.0); } void ShaderVectorPerVertex::set_color(const QColor& rgb) From bb3d0a07bd5cb22a078f9e0375d63ed9826cd948 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Thu, 3 Mar 2016 16:53:45 +0100 Subject: [PATCH 245/402] missing file --- cgogn/rendering/examples/drawing.cpp | 174 +++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 cgogn/rendering/examples/drawing.cpp diff --git a/cgogn/rendering/examples/drawing.cpp b/cgogn/rendering/examples/drawing.cpp new file mode 100644 index 00000000..64195418 --- /dev/null +++ b/cgogn/rendering/examples/drawing.cpp @@ -0,0 +1,174 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#include +#include + +#include +#include + +#include + +#define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) + +//using Vec3 = Eigen::Vector3d; +using Vec3 = cgogn::geometry::Vec_T>; + +class Drawing : public QOGLViewer +{ +public: + Drawing(); + Drawing(const Drawing&) = delete; + Drawing& operator=(const Drawing&) = delete; + + virtual void draw(); + virtual void init(); +// virtual void keyPressEvent(QKeyEvent *); + virtual ~Drawing(); + +private: + cgogn::rendering::Drawer* drawer_; + cgogn::rendering::Drawer* drawer2_; +}; + + + +Drawing::~Drawing() +{ + delete drawer_; + delete drawer2_; +} + +Drawing::Drawing() : + drawer_(nullptr), + drawer2_(nullptr) +{} + +//void Drawing::keyPressEvent(QKeyEvent *ev) +//{ +// switch (ev->key()) { +// case Qt::Key_P: +// phong_rendering_ = true; +// flat_rendering_ = false; +// break; +// case Qt::Key_Escape: +// exit(0); +// break; +// default: +// break; +// } +// update(); +//} + +void Drawing::draw() +{ + QMatrix4x4 proj; + QMatrix4x4 view; + camera()->getProjectionMatrix(proj); + camera()->getModelViewMatrix(view); + + drawer_->callList(proj,view); +// drawer2_->callList(proj,view); +} + +void Drawing::init() +{ + setSceneRadius(5.0); + setSceneCenter(qoglviewer::Vec(0.0,0.0,0.0)); + showEntireScene(); + + glClearColor(0.1f,0.1f,0.3f,0.0f); + + // drawer for simple old-school g1 rendering + drawer_ = new cgogn::rendering::Drawer(this); + drawer_->new_list(); + drawer_->lineWidth(2.0); + drawer_->begin(GL_LINE_LOOP); + drawer_->color3f(1.0,0.0,0.0); + drawer_->vertex3f(0,0,0); + drawer_->color3f(0.0,1.0,1.0); + drawer_->vertex3f(1,0,0); + drawer_->color3f(1.0,0.0,1.0); + drawer_->vertex3f(1,1,0); + drawer_->color3f(1.0,1.0,0.0); + drawer_->vertex3f(0,1,0); + drawer_->end(); +// drawer_->pointSize(10.0); + drawer_->lineWidthAA(3.0); + drawer_->begin(GL_LINES); + drawer_->color3f(1.0,1.0,1.0); + drawer_->vertex3fv(Vec3(-1,-1,0)); + drawer_->vertex3fv(Vec3(-1.2,-2,0)); + drawer_->vertex3fv(Vec3(-2,-2,0)); + drawer_->vertex3fv(Vec3(-2.2,1,0)); + drawer_->end(); + + drawer_->begin(GL_TRIANGLES); + drawer_->color3f(1.0,0.0,0.0); + drawer_->vertex3fv({{2,2,0}}); + drawer_->color3f(0.0,1.0,0.0); + drawer_->vertex3fv({{4,3,0}}); + drawer_->color3f(0.0,0.0,1.0); + drawer_->vertex3fv({{2.5,1,0}}); + drawer_->end(); + + drawer_->pointSizeAA(6.0); + drawer_->begin(GL_POINTS); + for (float a=0.0; a < 1.0; a+= 0.1) + { + Vec3 P(3.0+std::cos(6.28*a),-2.0+std::sin(6.28*a),0.0); + Vec3 C(a,0.5,1.0-a); + drawer_->color3fv(C); + drawer_->vertex3fv(P); + } + + drawer_->end(); + +// drawer_->pointSizeAA(7.0); +// drawer_->begin(GL_POINTS); +// drawer_->color3f(1.0,1.0,1.0); +// for (float z=-3.0; z < 3.0; z+= 0.2) +// for (float y=-3.0; y < 3.0; y+= 0.2) +// for (float x=-3.0; x < 3.0; x+= 0.2) +// { +// drawer_->vertex3f(x,y,z); +// } +// drawer_->end(); + drawer_->end_list(); + +} + +int main(int argc, char** argv) +{ + + QApplication application(argc, argv); + qoglviewer::init_ogl_context(); + + // Instantiate the viewer. + Drawing viewer; + viewer.setWindowTitle("Drawing"); + viewer.show(); + + // Run main loop. + return application.exec(); +} From 9c8a22deeb1542a83961b85cb6158cdb51cce66d Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Thu, 3 Mar 2016 17:48:07 +0100 Subject: [PATCH 246/402] added "base64" thirdparty It is necessary to decode/encode in base64. Used within vtk XML files. Signed-off-by: Etienne Schmitt --- thirdparty/CMakeLists.txt | 1 + thirdparty/base64/CMakeLists.txt | 16 ++++ thirdparty/base64/base64.cpp | 153 +++++++++++++++++++++++++++++++ thirdparty/base64/base64.h | 32 +++++++ 4 files changed, 202 insertions(+) create mode 100644 thirdparty/base64/CMakeLists.txt create mode 100644 thirdparty/base64/base64.cpp create mode 100644 thirdparty/base64/base64.h diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index c4a92db5..674f8700 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -19,4 +19,5 @@ if (CGOGN_BUILD_BENCHS) endif(CGOGN_BUILD_BENCHS) add_subdirectory(ply) +add_subdirectory(base64) add_subdirectory(OffBinConverter) diff --git a/thirdparty/base64/CMakeLists.txt b/thirdparty/base64/CMakeLists.txt new file mode 100644 index 00000000..8de90045 --- /dev/null +++ b/thirdparty/base64/CMakeLists.txt @@ -0,0 +1,16 @@ +set(CGOGN_THIRDPARTY_BASE64_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE PATH "base64 include directory") + +project(base64 + LANGUAGES CXX + ) + +set(HEADER_FILES + base64.h + ) + +set(SOURCE_FILES + base64.cpp + ) + +add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) +set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "_d") diff --git a/thirdparty/base64/base64.cpp b/thirdparty/base64/base64.cpp new file mode 100644 index 00000000..152edfb0 --- /dev/null +++ b/thirdparty/base64/base64.cpp @@ -0,0 +1,153 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +/* + base64.cpp and base64.h + + Copyright (C) 2004-2008 René Nyffenegger + + This source code is provided 'as-is', without any express or implied + warranty. In no event will the author be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this source code must not be misrepresented; you must not + claim that you wrote the original source code. If you use this source code + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original source code. + + 3. This notice may not be removed or altered from any source distribution. + + René Nyffenegger rene.nyffenegger@adp-gmbh.ch + +*/ + +#include "base64.h" +#include + +namespace base64 +{ + + +static const std::string base64_chars = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + + +inline bool is_base64(unsigned char c) +{ + return (isalnum(c) || (c == '+') || (c == '/')); +} + +std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) { + std::string ret; + int i = 0; + int j = 0; + unsigned char char_array_3[3]; + unsigned char char_array_4[4]; + + while (in_len--) { + char_array_3[i++] = *(bytes_to_encode++); + if (i == 3) { + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for(i = 0; (i <4) ; i++) + ret += base64_chars[char_array_4[i]]; + i = 0; + } + } + + if (i) + { + for(j = i; j < 3; j++) + char_array_3[j] = '\0'; + + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for (j = 0; (j < i + 1); j++) + ret += base64_chars[char_array_4[j]]; + + while((i++ < 3)) + ret += '='; + + } + + return ret; + +} + +std::string base64_decode(std::string const& encoded_string) { + int in_len = encoded_string.size(); + int i = 0; + int j = 0; + int in_ = 0; + unsigned char char_array_4[4], char_array_3[3]; + std::string ret; + + while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { + char_array_4[i++] = encoded_string[in_]; in_++; + if (i ==4) { + for (i = 0; i <4; i++) + char_array_4[i] = base64_chars.find(char_array_4[i]); + + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + + for (i = 0; (i < 3); i++) + ret += char_array_3[i]; + i = 0; + } + } + + if (i) { + for (j = i; j <4; j++) + char_array_4[j] = 0; + + for (j = 0; j <4; j++) + char_array_4[j] = base64_chars.find(char_array_4[j]); + + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + + for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; + } + + return ret; +} + +} // namespace base64 diff --git a/thirdparty/base64/base64.h b/thirdparty/base64/base64.h new file mode 100644 index 00000000..a6886a92 --- /dev/null +++ b/thirdparty/base64/base64.h @@ -0,0 +1,32 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#include + +namespace base64 +{ + +std::string base64_encode(unsigned char const* , unsigned int len); +std::string base64_decode(std::string const& s); + +} // namespace base64 From 610c7dd69b0082ad58ac8074b933c2ccab74f0de Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Fri, 4 Mar 2016 11:32:21 +0100 Subject: [PATCH 247/402] properly exit from Qt (crash on mac) --- cgogn/rendering/drawer.cpp | 35 ++++++++----- cgogn/rendering/drawer.h | 19 ++++--- cgogn/rendering/examples/drawing.cpp | 53 ++++++++------------ cgogn/rendering/examples/simple_viewer.cpp | 21 ++++---- cgogn/rendering/examples/viewer_per_face.cpp | 17 +++++-- cgogn/rendering/shaders/shader_flat.cpp | 4 +- cgogn/rendering/shaders/vbo.h | 4 +- 7 files changed, 81 insertions(+), 72 deletions(-) diff --git a/cgogn/rendering/drawer.cpp b/cgogn/rendering/drawer.cpp index 6987dc1e..df1acf92 100644 --- a/cgogn/rendering/drawer.cpp +++ b/cgogn/rendering/drawer.cpp @@ -35,36 +35,36 @@ namespace cgogn namespace rendering { -std::unique_ptr Drawer::shader_cpv_ = nullptr; -std::unique_ptr Drawer::shader_bl_ = nullptr; -std::unique_ptr Drawer::shader_rp_ = nullptr; +// static members init +ShaderColorPerVertex* Drawer::shader_cpv_ = nullptr; +ShaderBoldLine* Drawer::shader_bl_ = nullptr; +ShaderRoundPoint* Drawer::shader_rp_ = nullptr; +int Drawer::nb_instances_ = 0; Drawer::Drawer(QOpenGLFunctions_3_3_Core* ogl33): current_size_(1.0f), current_aa_(true), ogl33_(ogl33) { + nb_instances_++; + vbo_pos_ = new VBO(3); vbo_col_ = new VBO(3); - if (!shader_cpv_) - shader_cpv_ = std::unique_ptr(new ShaderColorPerVertex()); + shader_cpv_ = new ShaderColorPerVertex(); vao_cpv_ = shader_cpv_->add_vao(); shader_cpv_->set_vao(vao_cpv_,vbo_pos_,vbo_col_); if (!shader_bl_) - shader_bl_ = std::unique_ptr(new ShaderBoldLine(true)); - + shader_bl_ = new ShaderBoldLine(true); vao_bl_ = shader_bl_->add_vao(); shader_bl_->bind(); shader_bl_->release(); shader_bl_->set_vao(vao_bl_,vbo_pos_,vbo_col_); - if (!shader_rp_) - shader_rp_ = std::unique_ptr(new ShaderRoundPoint(true)); - + shader_rp_ = new ShaderRoundPoint(true); vao_rp_ = shader_rp_->add_vao(); shader_rp_->bind(); shader_rp_->release(); @@ -75,7 +75,18 @@ Drawer::Drawer(QOpenGLFunctions_3_3_Core* ogl33): Drawer::~Drawer() { + delete vbo_pos_; + delete vbo_col_; + nb_instances_--; + if (nb_instances_ ==0) + { + // delete shaders when last drawer is deleted + // ensure context still enable when delete shaders + delete shader_rp_; + delete shader_bl_; + delete shader_cpv_; + } } void Drawer::new_list() @@ -128,7 +139,7 @@ void Drawer::begin(GLenum mode) void Drawer::end() { - current_begin_->back().nb = data_pos_.size() - current_begin_->back().begin; + current_begin_->back().nb = static_cast(data_pos_.size() - current_begin_->back().begin); } @@ -156,7 +167,7 @@ void Drawer::color3f(float r, float g, float b) void Drawer::end_list() { - unsigned int nb_elts(data_pos_.size()); + unsigned int nb_elts = static_cast(data_pos_.size()); if (nb_elts == 0) return; diff --git a/cgogn/rendering/drawer.h b/cgogn/rendering/drawer.h index f97c6932..8d8158eb 100644 --- a/cgogn/rendering/drawer.h +++ b/cgogn/rendering/drawer.h @@ -32,7 +32,6 @@ #include #include -//#include namespace cgogn { @@ -40,7 +39,7 @@ namespace rendering { -class CGOGN_RENDERING_API Drawer//: protected QOpenGLFunctions_3_3_Core +class CGOGN_RENDERING_API Drawer { struct PrimParam { @@ -49,31 +48,31 @@ class CGOGN_RENDERING_API Drawer//: protected QOpenGLFunctions_3_3_Core float width; unsigned int nb; bool aa; - PrimParam(unsigned int b, GLenum m, float w, bool a): begin(b),mode(m),width(w),nb(0),aa(a){} + PrimParam(std::size_t b, GLenum m, float w, bool a) : begin(static_cast(b)), mode(m), width(w), nb(0), aa(a){} }; using Vec3f = std::array; protected: + + static ShaderColorPerVertex* shader_cpv_; + static ShaderBoldLine* shader_bl_; + static ShaderRoundPoint* shader_rp_; + static int nb_instances_; + VBO* vbo_pos_; VBO* vbo_col_; std::vector data_pos_; std::vector data_col_; - std::vector begins_point_; + std::vector begins_point_; std::vector begins_round_point_; - std::vector begins_line_; std::vector begins_bold_line_; std::vector begins_face_; - std::vector* current_begin_; - static std::unique_ptr shader_cpv_; - static std::unique_ptr shader_bl_; - static std::unique_ptr shader_rp_; - unsigned int vao_cpv_; unsigned int vao_bl_; unsigned int vao_rp_; diff --git a/cgogn/rendering/examples/drawing.cpp b/cgogn/rendering/examples/drawing.cpp index 64195418..ec60bd84 100644 --- a/cgogn/rendering/examples/drawing.cpp +++ b/cgogn/rendering/examples/drawing.cpp @@ -43,7 +43,7 @@ class Drawing : public QOGLViewer virtual void draw(); virtual void init(); -// virtual void keyPressEvent(QKeyEvent *); + virtual void closeEvent(QCloseEvent *e); virtual ~Drawing(); private: @@ -54,6 +54,9 @@ class Drawing : public QOGLViewer Drawing::~Drawing() +{} + +void Drawing::closeEvent(QCloseEvent *e) { delete drawer_; delete drawer2_; @@ -64,21 +67,6 @@ Drawing::Drawing() : drawer2_(nullptr) {} -//void Drawing::keyPressEvent(QKeyEvent *ev) -//{ -// switch (ev->key()) { -// case Qt::Key_P: -// phong_rendering_ = true; -// flat_rendering_ = false; -// break; -// case Qt::Key_Escape: -// exit(0); -// break; -// default: -// break; -// } -// update(); -//} void Drawing::draw() { @@ -88,7 +76,7 @@ void Drawing::draw() camera()->getModelViewMatrix(view); drawer_->callList(proj,view); -// drawer2_->callList(proj,view); + drawer2_->callList(proj,view); } void Drawing::init() @@ -132,30 +120,33 @@ void Drawing::init() drawer_->vertex3fv({{2.5,1,0}}); drawer_->end(); - drawer_->pointSizeAA(6.0); + drawer_->pointSizeAA(7.0); drawer_->begin(GL_POINTS); - for (float a=0.0; a < 1.0; a+= 0.1) + for (float a=0.0f; a < 1.0f; a+= 0.1f) { - Vec3 P(3.0+std::cos(6.28*a),-2.0+std::sin(6.28*a),0.0); + Vec3 P(4.0+std::cos(6.28*a),-2.0+std::sin(6.28*a),0.0); Vec3 C(a,0.5,1.0-a); drawer_->color3fv(C); drawer_->vertex3fv(P); } drawer_->end(); - -// drawer_->pointSizeAA(7.0); -// drawer_->begin(GL_POINTS); -// drawer_->color3f(1.0,1.0,1.0); -// for (float z=-3.0; z < 3.0; z+= 0.2) -// for (float y=-3.0; y < 3.0; y+= 0.2) -// for (float x=-3.0; x < 3.0; x+= 0.2) -// { -// drawer_->vertex3f(x,y,z); -// } -// drawer_->end(); drawer_->end_list(); + drawer2_ = new cgogn::rendering::Drawer(this); + drawer2_->new_list(); + drawer2_->pointSizeAA(5.0); + drawer2_->begin(GL_POINTS); + drawer2_->color3f(1.0,1.0,1.0); + for (float z=-1.0; z < 1.0; z+= 0.1) + for (float y=-2.0; y < 0.0; y+= 0.1) + for (float x=0.0; x < 2.0; x+= 0.1) + { + drawer2_->vertex3f(x,y,z); + } + drawer2_->end(); + drawer2_->end_list(); + } int main(int argc, char** argv) diff --git a/cgogn/rendering/examples/simple_viewer.cpp b/cgogn/rendering/examples/simple_viewer.cpp index 3da38100..6e3b7057 100644 --- a/cgogn/rendering/examples/simple_viewer.cpp +++ b/cgogn/rendering/examples/simple_viewer.cpp @@ -43,6 +43,7 @@ #include #include +#include #include @@ -71,6 +72,7 @@ class Viewer : public QOGLViewer virtual void keyPressEvent(QKeyEvent *); void import(const std::string& surfaceMesh); virtual ~Viewer(); + virtual void closeEvent(QCloseEvent *e); private: Map2 map_; @@ -86,7 +88,7 @@ class Viewer : public QOGLViewer cgogn::rendering::VBO* vbo_color_; cgogn::rendering::VBO* vbo_sphere_sz_; - cgogn::rendering::ShaderSimpleColor* shader_vertex_; +// cgogn::rendering::ShaderSimpleColor* shader_vertex_; cgogn::rendering::ShaderBoldLine* shader_edge_; cgogn::rendering::ShaderFlat* shader_flat_; cgogn::rendering::ShaderVectorPerVertex* shader_normal_; @@ -127,13 +129,16 @@ void Viewer::import(const std::string& surfaceMesh) } Viewer::~Viewer() +{} + +void Viewer::closeEvent(QCloseEvent *e) { delete render_; delete vbo_pos_; delete vbo_norm_; delete vbo_color_; delete vbo_sphere_sz_; - delete shader_vertex_; +// delete shader_vertex_; delete shader_flat_; delete shader_normal_; delete shader_phong_; @@ -151,7 +156,7 @@ Viewer::Viewer() : vbo_norm_(nullptr), vbo_color_(nullptr), vbo_sphere_sz_(nullptr), - shader_vertex_(nullptr), +// shader_vertex_(nullptr), shader_flat_(nullptr), shader_normal_(nullptr), shader_phong_(nullptr), @@ -188,12 +193,12 @@ void Viewer::keyPressEvent(QKeyEvent *ev) case Qt::Key_B: bb_rendering_ = !bb_rendering_; break; - case Qt::Key_Escape: - exit(0); - break; default: break; } + // enable QGLViewer keys + QOGLViewer::keyPressEvent(ev); + //update drawing update(); } @@ -300,10 +305,6 @@ void Viewer::init() render_->init_primitives(map_, cgogn::rendering::LINES, vertex_position_); render_->init_primitives(map_, cgogn::rendering::TRIANGLES, vertex_position_); -// shader_vertex_ = new cgogn::rendering::ShaderSimpleColor; -// shader_vertex_->add_vao(); -// shader_vertex_->set_vao(0, vbo_pos_); - shader_point_sprite_ = new cgogn::rendering::ShaderPointSprite(true,true); shader_point_sprite_->add_vao(); shader_point_sprite_->set_vao(0, vbo_pos_,vbo_color_,vbo_sphere_sz_); diff --git a/cgogn/rendering/examples/viewer_per_face.cpp b/cgogn/rendering/examples/viewer_per_face.cpp index ab0f5fe7..5b5da0cb 100644 --- a/cgogn/rendering/examples/viewer_per_face.cpp +++ b/cgogn/rendering/examples/viewer_per_face.cpp @@ -66,6 +66,7 @@ class Viewer : public QOGLViewer virtual void keyPressEvent(QKeyEvent *); void import(const std::string& surfaceMesh); virtual ~Viewer(); + virtual void closeEvent(QCloseEvent *e); private: Map2 map_; @@ -78,7 +79,6 @@ class Viewer : public QOGLViewer cgogn::rendering::VBO* vbo_norm_; cgogn::rendering::VBO* vbo_color_; -// cgogn::rendering::ShaderSimpleColor* shader_color_; cgogn::rendering::ShaderFlat* shader_flat_; cgogn::rendering::ShaderPhong* shader_phong_; @@ -109,10 +109,14 @@ void Viewer::import(const std::string& surfaceMesh) } Viewer::~Viewer() +{} + +void Viewer::closeEvent(QCloseEvent *e) { delete vbo_pos_; delete vbo_norm_; delete vbo_color_; + delete shader_flat_; delete shader_phong_; } @@ -122,7 +126,10 @@ Viewer::Viewer() : face_normal_(), bb_(), vbo_pos_(nullptr), + vbo_norm_(nullptr), vbo_color_(nullptr), + shader_flat_(nullptr), + shader_phong_(nullptr), phong_rendering_(true), flat_rendering_(false) {} @@ -138,12 +145,12 @@ void Viewer::keyPressEvent(QKeyEvent *ev) flat_rendering_ = true; phong_rendering_ = false; break; - case Qt::Key_Escape: - exit(0); - break; default: break; } + // enable QGLViewer keys + QOGLViewer::keyPressEvent(ev); + //update drawing update(); } @@ -178,7 +185,7 @@ void Viewer::draw() void Viewer::init() { - glClearColor(0.1,0.1,0.3,0.0); + glClearColor(0.1f,0.1f,0.3f,0.0f); vbo_pos_ = new cgogn::rendering::VBO(3); diff --git a/cgogn/rendering/shaders/shader_flat.cpp b/cgogn/rendering/shaders/shader_flat.cpp index 6bc481b5..1cf9c295 100644 --- a/cgogn/rendering/shaders/shader_flat.cpp +++ b/cgogn/rendering/shaders/shader_flat.cpp @@ -95,9 +95,9 @@ const char* ShaderFlat::fragment_shader_source2_ = " vec3 L = normalize(lightPosition-pos);\n" " float lambert = dot(N,L);\n" " if (gl_FrontFacing)\n" - " fragColor = ambiant_color+vec4(lambert*col,1.0);;\n" + " fragColor = ambiant_color+vec4(lambert*col,1.0);\n" " else\n" - " fragColor = ambiant_color-vec4(lambert*col,1.0);;\n" + " fragColor = ambiant_color-vec4(lambert*col,1.0);\n" "}\n"; diff --git a/cgogn/rendering/shaders/vbo.h b/cgogn/rendering/shaders/vbo.h index 18019122..6a31aada 100644 --- a/cgogn/rendering/shaders/vbo.h +++ b/cgogn/rendering/shaders/vbo.h @@ -75,7 +75,7 @@ class VBO * @param nb_vectors number of vectors * @param vector_dimension_ number of component of each vector */ - inline void allocate(int nb_vectors, int vector_dimension) + inline void allocate(int nb_vectors, unsigned int vector_dimension) { buffer_.bind(); unsigned int total = nb_vectors * vector_dimension; @@ -342,7 +342,7 @@ void generate_vbo(const ATTR& attr, const std::vector& indices, VB vec_dim = 4; // allocate vbo - vbo.allocate(indices.size(), vec_dim); + vbo.allocate(static_cast(indices.size()), vec_dim); // copy (after conversion) using OutputConvert = typename function_traits::result_type; From 477d6b88ec8bb027cdb925981893ed952701b85c Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Fri, 4 Mar 2016 15:17:47 +0100 Subject: [PATCH 248/402] topo2d rendering in a drawer --- cgogn/rendering/examples/CMakeLists.txt | 3 + cgogn/rendering/examples/viewer_topo.cpp | 213 +++++++++++++++++++++++ cgogn/rendering/map_render.h | 82 +++++++++ 3 files changed, 298 insertions(+) create mode 100644 cgogn/rendering/examples/viewer_topo.cpp diff --git a/cgogn/rendering/examples/CMakeLists.txt b/cgogn/rendering/examples/CMakeLists.txt index 408dee64..94667a57 100644 --- a/cgogn/rendering/examples/CMakeLists.txt +++ b/cgogn/rendering/examples/CMakeLists.txt @@ -18,6 +18,9 @@ target_link_libraries(simple_viewer cgogn_core cgogn_io cgogn_rendering QOGLView add_executable(viewer_per_face viewer_per_face.cpp) target_link_libraries(viewer_per_face cgogn_core cgogn_io cgogn_rendering QOGLViewer) +add_executable(viewer_topo viewer_topo.cpp) +target_link_libraries(viewer_topo cgogn_core cgogn_io cgogn_rendering QOGLViewer) + add_executable(drawing drawing.cpp) target_link_libraries(drawing cgogn_rendering QOGLViewer) diff --git a/cgogn/rendering/examples/viewer_topo.cpp b/cgogn/rendering/examples/viewer_topo.cpp new file mode 100644 index 00000000..14395dff --- /dev/null +++ b/cgogn/rendering/examples/viewer_topo.cpp @@ -0,0 +1,213 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#include +#include + +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include + +#define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) + +using Map2 = cgogn::CMap2; +using Vec3 = Eigen::Vector3d; +//using Vec3 = cgogn::geometry::Vec_T>; + +template +using VertexAttributeHandler = Map2::VertexAttributeHandler; + + +class Viewer : public QOGLViewer +{ +public: + Viewer(); + Viewer(const Viewer&) = delete; + Viewer& operator=(const Viewer&) = delete; + + virtual void draw(); + virtual void init(); + + virtual void keyPressEvent(QKeyEvent *); + void import(const std::string& surfaceMesh); + virtual ~Viewer(); + virtual void closeEvent(QCloseEvent *e); + +private: + Map2 map_; + VertexAttributeHandler vertex_position_; + + cgogn::geometry::BoundingBox bb_; + cgogn::rendering::MapRender* render_; + cgogn::rendering::VBO* vbo_pos_; + cgogn::rendering::ShaderFlat* shader_flat_; + cgogn::rendering::Drawer* drawer_topo; + + bool flat_rendering_; + bool topo_rendering_; + +}; + + +// +// IMPLEMENTATION +// + + +void Viewer::import(const std::string& surfaceMesh) +{ + cgogn::io::import_surface(map_, surfaceMesh); + + vertex_position_ = map_.get_attribute("position"); + + cgogn::geometry::compute_bounding_box(vertex_position_, bb_); + + setSceneRadius(bb_.diag_size()/2.0); + Vec3 center = bb_.center(); + setSceneCenter(qoglviewer::Vec(center[0], center[1], center[2])); + showEntireScene(); +} + +Viewer::~Viewer() +{} + +void Viewer::closeEvent(QCloseEvent *e) +{ + delete render_; + delete vbo_pos_; + delete shader_flat_; + delete drawer_topo; +} + +Viewer::Viewer() : + map_(), + vertex_position_(), + bb_(), + render_(nullptr), + vbo_pos_(nullptr), + shader_flat_(nullptr), + drawer_topo(nullptr), + flat_rendering_(true), + topo_rendering_(true) +{} + +void Viewer::keyPressEvent(QKeyEvent *ev) +{ + switch (ev->key()) { + case Qt::Key_F: + flat_rendering_ = !flat_rendering_; + break; + case Qt::Key_T: + topo_rendering_ = !topo_rendering_; + break; + default: + break; + } + // enable QGLViewer keys + QOGLViewer::keyPressEvent(ev); + //update drawing + update(); +} + +void Viewer::draw() +{ + QMatrix4x4 proj; + QMatrix4x4 view; + camera()->getProjectionMatrix(proj); + camera()->getModelViewMatrix(view); + + if (flat_rendering_) + { + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1.0f, 1.0f); + shader_flat_->bind(); + shader_flat_->set_matrices(proj,view); + shader_flat_->bind_vao(0); + render_->draw(cgogn::rendering::TRIANGLES); + shader_flat_->release_vao(0); + shader_flat_->release(); + glDisable(GL_POLYGON_OFFSET_FILL); + } + + if (topo_rendering_) + drawer_topo->callList(proj,view); + +} + +void Viewer::init() +{ + glClearColor(0.1f,0.1f,0.3f,0.0f); + + vbo_pos_ = new cgogn::rendering::VBO(3); + cgogn::rendering::update_vbo(vertex_position_, *vbo_pos_); + + + render_ = new cgogn::rendering::MapRender(); + render_->init_primitives(map_, cgogn::rendering::TRIANGLES, vertex_position_); + + shader_flat_ = new cgogn::rendering::ShaderFlat; + shader_flat_->add_vao(); + shader_flat_->set_vao(0, vbo_pos_); + shader_flat_->bind(); + shader_flat_->set_front_color(QColor(0,150,0)); + shader_flat_->set_back_color(QColor(0,0,150)); + shader_flat_->set_ambiant_color(QColor(5,5,5)); + shader_flat_->release(); + + drawer_topo = new cgogn::rendering::Drawer(this); + cgogn::rendering::create_drawer_topo2(map_,vertex_position_,*drawer_topo); +} + +int main(int argc, char** argv) +{ + std::string surfaceMesh; + if (argc < 2) + { + std::cout << "USAGE: " << argv[0] << " [filename]" << std::endl; + surfaceMesh = std::string(DEFAULT_MESH_PATH) + std::string("aneurysm3D_1.off"); + std::cout << "Using default mesh : " << surfaceMesh << std::endl; + } + else + surfaceMesh = std::string(argv[1]); + + QApplication application(argc, argv); + qoglviewer::init_ogl_context(); + + // Instantiate the viewer. + Viewer viewer; + viewer.setWindowTitle("simpleViewer"); + viewer.import(surfaceMesh); + viewer.show(); + + // Run main loop. + return application.exec(); +} diff --git a/cgogn/rendering/map_render.h b/cgogn/rendering/map_render.h index da7598f9..68aa7c36 100644 --- a/cgogn/rendering/map_render.h +++ b/cgogn/rendering/map_render.h @@ -30,6 +30,7 @@ #include // impossible to include directly attribute_handler.h ! #include +#include namespace cgogn { @@ -220,6 +221,87 @@ void create_indices_vertices_faces(MAP& m, const typename MAP::template VertexAt }); } +/** + * @brief create topologie rendering in a Drawer + * @param m the map + * @param position vertices positions + * @param dr output drawer + */ +template +void create_drawer_topo2(MAP& m, const typename MAP::template VertexAttributeHandler& position, + Drawer& dr) +{ + using Vertex = typename MAP::Vertex; + using Face = typename MAP::Face; + using Scalar = typename VEC3::Scalar; + + const Scalar expl1 = 0.95; + const Scalar expl2 = 0.85; + + const Scalar opp_expl1 = 1.0 -expl1; + const Scalar opp_expl2 = 1.0 - expl2; + + + std::vector local_vertices; + local_vertices.reserve(256); + + dr.new_list(); + + m.foreach_cell([&] (Face f) + { + local_vertices.clear(); + VEC3 center; + center.setZero(); + unsigned int count = 0u; + m.foreach_incident_vertex(f, [&] (Vertex v) + { + local_vertices.push_back(position[v]); + center += position[v]; + count++; + }); + center /= Scalar(count); + + // phi2 mid-edge: N -> 2N-1 + for (unsigned int i=0; i N-1 + for (unsigned int i=0; i 3N-1 + for (unsigned int i=0; i 4N-1 + for (unsigned int i=0; i Date: Fri, 4 Mar 2016 15:44:03 +0100 Subject: [PATCH 249/402] remove some warnings --- cgogn/rendering/examples/drawing.cpp | 8 ++++---- cgogn/rendering/examples/simple_viewer.cpp | 2 +- cgogn/rendering/examples/viewer_per_face.cpp | 2 +- cgogn/rendering/examples/viewer_topo.cpp | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cgogn/rendering/examples/drawing.cpp b/cgogn/rendering/examples/drawing.cpp index ec60bd84..5cdab8e1 100644 --- a/cgogn/rendering/examples/drawing.cpp +++ b/cgogn/rendering/examples/drawing.cpp @@ -56,7 +56,7 @@ class Drawing : public QOGLViewer Drawing::~Drawing() {} -void Drawing::closeEvent(QCloseEvent *e) +void Drawing::closeEvent(QCloseEvent*) { delete drawer_; delete drawer2_; @@ -138,9 +138,9 @@ void Drawing::init() drawer2_->pointSizeAA(5.0); drawer2_->begin(GL_POINTS); drawer2_->color3f(1.0,1.0,1.0); - for (float z=-1.0; z < 1.0; z+= 0.1) - for (float y=-2.0; y < 0.0; y+= 0.1) - for (float x=0.0; x < 2.0; x+= 0.1) + for (float z=-1.0f; z < 1.0f; z+= 0.1f) + for (float y=-2.0f; y < 0.0f; y+= 0.1f) + for (float x=0.0f; x < 2.0f; x+= 0.1f) { drawer2_->vertex3f(x,y,z); } diff --git a/cgogn/rendering/examples/simple_viewer.cpp b/cgogn/rendering/examples/simple_viewer.cpp index 6e3b7057..5b2b2e2c 100644 --- a/cgogn/rendering/examples/simple_viewer.cpp +++ b/cgogn/rendering/examples/simple_viewer.cpp @@ -131,7 +131,7 @@ void Viewer::import(const std::string& surfaceMesh) Viewer::~Viewer() {} -void Viewer::closeEvent(QCloseEvent *e) +void Viewer::closeEvent(QCloseEvent*) { delete render_; delete vbo_pos_; diff --git a/cgogn/rendering/examples/viewer_per_face.cpp b/cgogn/rendering/examples/viewer_per_face.cpp index 5b5da0cb..9606f428 100644 --- a/cgogn/rendering/examples/viewer_per_face.cpp +++ b/cgogn/rendering/examples/viewer_per_face.cpp @@ -111,7 +111,7 @@ void Viewer::import(const std::string& surfaceMesh) Viewer::~Viewer() {} -void Viewer::closeEvent(QCloseEvent *e) +void Viewer::closeEvent(QCloseEvent*) { delete vbo_pos_; delete vbo_norm_; diff --git a/cgogn/rendering/examples/viewer_topo.cpp b/cgogn/rendering/examples/viewer_topo.cpp index 14395dff..8b93001d 100644 --- a/cgogn/rendering/examples/viewer_topo.cpp +++ b/cgogn/rendering/examples/viewer_topo.cpp @@ -100,7 +100,7 @@ void Viewer::import(const std::string& surfaceMesh) Viewer::~Viewer() {} -void Viewer::closeEvent(QCloseEvent *e) +void Viewer::closeEvent(QCloseEvent*) { delete render_; delete vbo_pos_; From 7730ac96326b1fd9b1cf476f792e3593cbec6dcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Fri, 4 Mar 2016 16:03:20 +0100 Subject: [PATCH 250/402] fixed minor bugs in DataIO::read_n and splitted surface_import in several subclasses. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/container/chunk_array_container.h | 17 +- cgogn/io/CMakeLists.txt | 5 +- cgogn/io/c_locale.h | 11 +- cgogn/io/data_io.h | 100 +-- cgogn/io/io_utils.h | 32 +- cgogn/io/map_import.h | 29 +- cgogn/io/obj_io.h | 151 ++++ cgogn/io/off_io.h | 240 +++++++ cgogn/io/ply_io.h | 115 +++ cgogn/io/surface_import.h | 716 +------------------ cgogn/io/vtk_cell_types.h | 89 --- cgogn/io/vtk_io.h | 402 +++++++++++ 12 files changed, 1061 insertions(+), 846 deletions(-) create mode 100644 cgogn/io/obj_io.h create mode 100644 cgogn/io/off_io.h create mode 100644 cgogn/io/ply_io.h delete mode 100644 cgogn/io/vtk_cell_types.h create mode 100644 cgogn/io/vtk_io.h diff --git a/cgogn/core/container/chunk_array_container.h b/cgogn/core/container/chunk_array_container.h index 4f040092..94491770 100644 --- a/cgogn/core/container/chunk_array_container.h +++ b/cgogn/core/container/chunk_array_container.h @@ -24,15 +24,6 @@ #ifndef CORE_CONTAINER_CHUNK_ARRAY_CONTAINER_H_ #define CORE_CONTAINER_CHUNK_ARRAY_CONTAINER_H_ -#include -#include -#include -#include -#include -#include -#include -#include - #include #include #include @@ -41,6 +32,14 @@ #include #include +#include +#include +#include +#include +#include +#include +#include + namespace cgogn { diff --git a/cgogn/io/CMakeLists.txt b/cgogn/io/CMakeLists.txt index cca80773..d42b9cd1 100644 --- a/cgogn/io/CMakeLists.txt +++ b/cgogn/io/CMakeLists.txt @@ -8,11 +8,14 @@ set(HEADER_FILES map_import.h map_export.h import_ply_data.h - vtk_cell_types.h io_utils.h data_io.h dll.h c_locale.h + vtk_io.h + off_io.h + obj_io.h + ply_io.h ) set(SOURCE_FILES diff --git a/cgogn/io/c_locale.h b/cgogn/io/c_locale.h index 1421c8ec..65bf73c3 100644 --- a/cgogn/io/c_locale.h +++ b/cgogn/io/c_locale.h @@ -24,6 +24,12 @@ #ifndef IO_C_LOCALE_H_ #define IO_C_LOCALE_H_ +#include +#include + +namespace cgogn +{ + class Scoped_C_Locale { std::string current_locale_; @@ -32,16 +38,17 @@ class Scoped_C_Locale /// set numeric locale to C after saving current locale inline Scoped_C_Locale() { - current_locale_ = std::string(setlocale(LC_NUMERIC, NULL)); + current_locale_ = std::string(std::setlocale(LC_NUMERIC, NULL)); setlocale(LC_NUMERIC, "C"); } /// restore locale inline ~Scoped_C_Locale() { - setlocale(LC_NUMERIC, current_locale_.c_str()); + std::setlocale(LC_NUMERIC, current_locale_.c_str()); } }; +} // namespace cgogn #endif // IO_C_LOCALE_H_ diff --git a/cgogn/io/data_io.h b/cgogn/io/data_io.h index e3bbdfb7..1f4871f1 100644 --- a/cgogn/io/data_io.h +++ b/cgogn/io/data_io.h @@ -29,6 +29,7 @@ #include #include +#include #include @@ -41,37 +42,39 @@ namespace io /** * @brief The BaseDataIO class : used to read numerical values (scalar & vectors) in mesh files */ -template +template class DataIOGen { public: - using ChunkArrayGen = cgogn::ChunkArrayGen; - using ChunkArrayContainer = typename MAP::template ChunkArrayContainer; + using ChunkArrayGen = cgogn::ChunkArrayGen; + using ChunkArrayContainer = cgogn::ChunkArrayContainer; - virtual void read_n(std::ifstream& fp, std::size_t n, bool binary, bool big_endian) = 0; - virtual void skip_n(std::ifstream& fp, std::size_t n, bool binary) = 0; + virtual void read_n(std::istream& fp, std::size_t n, bool binary, bool big_endian) = 0; + virtual void skip_n(std::istream& fp, std::size_t n, bool binary) = 0; virtual void* get_data() = 0; virtual void reset() = 0; virtual void to_chunk_array(ChunkArrayGen* ca_gen) const = 0; - virtual ChunkArrayGen* add_attribute(ChunkArrayContainer& cac, const std::string& att_name) = 0; + virtual ChunkArrayGen* add_attribute(ChunkArrayContainer& cac, const std::string& att_name) const = 0; virtual unsigned int nb_components() const = 0; virtual ~DataIOGen() {} + template inline static std::unique_ptr newDataIO(const std::string type_name); + template inline static std::unique_ptr newDataIO(const std::string type_name, unsigned int nb_components); }; -template -class DataIO : public DataIOGen +template +class DataIO : public DataIOGen { public: - using Inherit = DataIOGen; - using Self = DataIO; + using Inherit = DataIOGen; + using Self = DataIO; using ChunkArrayGen = typename Inherit::ChunkArrayGen; - using ChunkArray = cgogn::ChunkArray; + using ChunkArray = cgogn::ChunkArray; using ChunkArrayContainer = typename Inherit::ChunkArrayContainer; DataIO() @@ -83,7 +86,7 @@ class DataIO : public DataIOGen DataIO& operator =(const Self&) = delete; DataIO(Self&&) = default; - virtual void read_n(std::ifstream& fp, std::size_t n, bool binary, bool big_endian) override + virtual void read_n(std::istream& fp, std::size_t n, bool binary, bool big_endian) override { const std::size_t old_size = data_->size(); data_->resize(old_size + n); @@ -92,8 +95,8 @@ class DataIO : public DataIOGen fp.read(reinterpret_cast(std::addressof(data_->operator[](old_size))), n * sizeof(T)); if (big_endian != ::cgogn::internal::cgogn_is_little_endian) { - for (auto & x : *data_) - x = cgogn::io::internal::swap_endianness(x); + for (auto it = data_->begin() + old_size, end = data_->end() ; it != end; ++it) + *it = cgogn::io::internal::swap_endianness(*it); } if (fp.eof() || fp.bad()) this->reset(); @@ -119,7 +122,7 @@ class DataIO : public DataIOGen } } - virtual void skip_n(std::ifstream& fp, std::size_t n, bool binary) override + virtual void skip_n(std::istream& fp, std::size_t n, bool binary) override { if (binary) { @@ -149,10 +152,10 @@ class DataIO : public DataIOGen data_ = make_unique>(); } - virtual ChunkArray* add_attribute(ChunkArrayContainer& cac, const std::string& att_name) override + virtual ChunkArray* add_attribute(ChunkArrayContainer& cac, const std::string& att_name) const override { - for (unsigned i = cac.capacity(), end = data_->size(); i < end; ++i) - cac.template insert_lines(); + for (unsigned i = cac.capacity(), end = data_->size(); i < end; i+=PRIM_SIZE) + cac.template insert_lines(); return cac.template add_attribute(att_name); } @@ -169,6 +172,11 @@ class DataIO : public DataIOGen return data_.get(); } + inline std::vector const * get_vec() const + { + return data_.get(); + } + virtual unsigned int nb_components() const override { return geometry::nb_components_traits::value; @@ -178,49 +186,50 @@ class DataIO : public DataIOGen std::unique_ptr> data_; }; -template -std::unique_ptr> DataIOGen::newDataIO(const std::string type_name) +template +template +std::unique_ptr> DataIOGen::newDataIO(const std::string type_name) { if (type_name == name_of_type(float())) - return make_unique>(); + return make_unique>(); else { if (type_name == name_of_type(double())) - return make_unique>(); + return make_unique>(); else { if (type_name == name_of_type(char())) - return make_unique>(); + return make_unique>(); else { if (type_name == name_of_type(std::int8_t())) - return make_unique>(); + return make_unique>(); else { if (type_name == name_of_type(std::uint8_t())) - return make_unique>(); + return make_unique>(); else { if (type_name == name_of_type(std::int16_t())) - return make_unique>(); + return make_unique>(); else { if (type_name == name_of_type(std::uint16_t())) - return make_unique>(); + return make_unique>(); else { if (type_name == name_of_type(std::uint32_t())) - return make_unique>(); + return make_unique>(); else { if (type_name == name_of_type(std::int32_t())) - return make_unique>(); + return make_unique>(); else { if (type_name == name_of_type(std::uint64_t())) - return make_unique>(); + return make_unique>(); else { if (type_name == name_of_type(std::int64_t())) - return make_unique>(); + return make_unique>(); } } } @@ -232,23 +241,24 @@ std::unique_ptr> DataIOGen::newDataIO(const std::string type } } std::cerr << "DataIOGen::newDataIO : couldn't create a DataIO of type \"" << type_name << "\"." << std::endl; - return std::unique_ptr>(); + return std::unique_ptr>(); } -template -std::unique_ptr> DataIOGen::newDataIO(const std::string type_name, unsigned int nb_components) +template +template +std::unique_ptr> DataIOGen::newDataIO(const std::string type_name, unsigned int nb_components) { cgogn_assert(nb_components >=1u && nb_components <= 4u); if (nb_components == 1u) - return DataIOGen::newDataIO(type_name); + return DataIOGen::newDataIO(type_name); if (type_name == name_of_type(std::int32_t())) { switch (nb_components) { - case 2u: return make_unique>(); break; - case 3u: return make_unique>(); break; - case 4u: return make_unique>(); break; + case 2u: return make_unique>(); break; + case 3u: return make_unique>(); break; + case 4u: return make_unique>(); break; default:break; } } else { @@ -256,9 +266,9 @@ std::unique_ptr> DataIOGen::newDataIO(const std::string type { switch (nb_components) { - case 2u: return make_unique>(); break; - case 3u: return make_unique>(); break; - case 4u: return make_unique>(); break; + case 2u: return make_unique>(); break; + case 3u: return make_unique>(); break; + case 4u: return make_unique>(); break; default:break; } } else { @@ -266,9 +276,9 @@ std::unique_ptr> DataIOGen::newDataIO(const std::string type { switch (nb_components) { - case 2u: return make_unique>(); break; - case 3u: return make_unique>(); break; - case 4u: return make_unique>(); break; + case 2u: return make_unique>(); break; + case 3u: return make_unique>(); break; + case 4u: return make_unique>(); break; default:break; } } @@ -276,7 +286,7 @@ std::unique_ptr> DataIOGen::newDataIO(const std::string type } std::cerr << "DataIOGen::newDataIO : couldn't create a DataIO of type \"" << type_name << "\" with " << nb_components << " components." << std::endl; - return std::unique_ptr>(); + return std::unique_ptr>(); } } // namespace io diff --git a/cgogn/io/io_utils.h b/cgogn/io/io_utils.h index 472ede69..cbf1992f 100644 --- a/cgogn/io/io_utils.h +++ b/cgogn/io/io_utils.h @@ -37,6 +37,34 @@ namespace cgogn namespace io { + + +enum FileType +{ + FileType_UNKNOWN = 0, + FileType_OFF, + FileType_OBJ, + FileType_PLY, + FileType_VTK_LEGACY, + FileType_VTU +}; + +inline FileType get_file_type(const std::string& filename) +{ + const std::string& extension = to_lower(get_extension(filename)); + if (extension == "off") + return FileType::FileType_OFF; + if (extension == "obj") + return FileType::FileType_OBJ; + if (extension == "ply") + return FileType::FileType_PLY; + if (extension == "vtk") + return FileType::FileType_VTK_LEGACY; + if (extension == "vtu") + return FileType::FileType_VTU; + return FileType::FileType_UNKNOWN; +} + namespace internal { @@ -55,14 +83,14 @@ inline typename std::enable_if<(!std::is_arithmetic::value) && !std::is_float } template -inline typename std::enable_if::value || std::is_floating_point::value, std::istringstream&>::type parse(std::istringstream& iss, T& x) +inline typename std::enable_if::value || std::is_floating_point::value, std::istream&>::type parse(std::istream& iss, T& x) { iss >> x; return iss; } template -inline typename std::enable_if::value && !std::is_floating_point::value, std::istringstream&>::type parse(std::istringstream& iss, T& x) +inline typename std::enable_if::value && !std::is_floating_point::value, std::istream&>::type parse(std::istream& iss, T& x) { for (std::size_t i = 0u ; i < geometry::vector_traits::SIZE; ++i) iss >> x[i]; diff --git a/cgogn/io/map_import.h b/cgogn/io/map_import.h index d32b319c..82480f74 100644 --- a/cgogn/io/map_import.h +++ b/cgogn/io/map_import.h @@ -25,11 +25,17 @@ #define IO_MAP_IMPORT_H_ #include +#include #include #include + #include #include +#include +#include +#include +#include namespace cgogn { @@ -37,6 +43,23 @@ namespace cgogn namespace io { +template +inline std::unique_ptr> newSurfaceImport(const std::string& filename) +{ + const FileType file_type = get_file_type(filename); + switch (file_type) + { + case FileType::FileType_OFF : return make_unique>(); + case FileType::FileType_VTK_LEGACY: + case FileType::FileType_VTU: return make_unique>(); + case FileType::FileType_OBJ: return make_unique>(); + case FileType::FileType_PLY: return make_unique>(); + default: + std::cerr << "SurfaceImport does not handle files with extension \"" << get_extension(filename) << "\"." << std::endl; + return std::unique_ptr> (); + } +} + template inline void import_surface(cgogn::CMap2& cmap2, const std::string& filename); @@ -49,9 +72,9 @@ inline void import_volume(cgogn::CMap3& cmap3, const std::string& fi template inline void import_surface(cgogn::CMap2& cmap2, const std::string& filename) { - SurfaceImport si; - si.template import_file(filename); - si.create_map(cmap2); + auto si = newSurfaceImport(filename); + si->import_file(filename); + si->create_map(cmap2); } template diff --git a/cgogn/io/obj_io.h b/cgogn/io/obj_io.h new file mode 100644 index 00000000..1dff2620 --- /dev/null +++ b/cgogn/io/obj_io.h @@ -0,0 +1,151 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef IO_OBJ_IO_H_ +#define IO_OBJ_IO_H_ + +#include + +namespace cgogn +{ + +namespace io +{ + +template +class ObjSurfaceImport : public SurfaceImport { +public: + using Self = ObjSurfaceImport; + using Inherit = SurfaceImport; + using Scalar = typename geometry::vector_traits::Scalar; + template + using ChunkArray = typename Inherit::template ChunkArray; + + virtual ~ObjSurfaceImport() override {} +protected: + virtual bool import_file_impl(const std::string& filename) override + { + std::ifstream fp(filename.c_str(), std::ios::in); + ChunkArray* position = + this->vertex_attributes_.template add_attribute("position"); + + std::string line, tag; + + do + { + fp >> tag; + std::getline(fp, line); + } while (tag != std::string("v")); + + // lecture des sommets + std::vector vertices_id; + vertices_id.reserve(102400); + + unsigned int i = 0; + do + { + if (tag == std::string("v")) + { + std::stringstream oss(line); + + double x, y, z; + oss >> x; + oss >> y; + oss >> z; + + VEC3 pos{Scalar(x), Scalar(y), Scalar(z)}; + + unsigned int vertex_id = this->vertex_attributes_.template insert_lines<1>(); + (*position)[vertex_id] = pos; + + vertices_id.push_back(vertex_id); + i++; + } + + fp >> tag; + std::getline(fp, line); + } while (!fp.eof()); + + this->nb_vertices_ = static_cast(vertices_id.size()); + + fp.clear(); + fp.seekg(0, std::ios::beg); + + do + { + fp >> tag; + std::getline(fp, line); + } while (tag != std::string("f")); + + this->faces_nb_edges_.reserve(vertices_id.size() * 2); + this->faces_vertex_indices_.reserve(vertices_id.size() * 8); + + std::vector table; + table.reserve(64); + do + { + if (tag == std::string("f")) // lecture d'une face + { + std::stringstream oss(line); + + table.clear(); + while (!oss.eof()) // lecture de tous les indices + { + std::string str; + oss >> str; + + unsigned int ind = 0; + + while ((ind < str.length()) && (str[ind] != '/')) + ind++; + + if (ind > 0) + { + unsigned int index; + std::stringstream iss(str.substr(0, ind)); + iss >> index; + table.push_back(index); + } + } + + unsigned int n = static_cast(table.size()); + this->faces_nb_edges_.push_back(static_cast(n)); + for (unsigned int j = 0; j < n; ++j) + { + unsigned int index = table[j] - 1; // indices start at 1 + this->faces_vertex_indices_.push_back(vertices_id[index]); + } + this->nb_faces_++; + } + fp >> tag; + std::getline(fp, line); + } while (!fp.eof()); + + return true; + } +}; + +} // namespace io +} // namespace cgogn + +#endif // IO_OBJ_IO_H_ diff --git a/cgogn/io/off_io.h b/cgogn/io/off_io.h new file mode 100644 index 00000000..20c3d665 --- /dev/null +++ b/cgogn/io/off_io.h @@ -0,0 +1,240 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef IO_OFF_IO_H_ +#define IO_OFF_IO_H_ + +#include + +namespace cgogn +{ + +namespace io +{ + +template +class OffSurfaceImport : public SurfaceImport { +public: + using Self = OffSurfaceImport; + using Inherit = SurfaceImport; + using Scalar = typename geometry::vector_traits::Scalar; + template + using ChunkArray = typename Inherit::template ChunkArray; + + virtual ~OffSurfaceImport() override {} +protected: + virtual bool import_file_impl(const std::string& filename) override + { + std::ifstream fp(filename.c_str(), std::ios::in); + + std::string line; + line.reserve(512); + + // read OFF header + std::getline(fp, line); + if (line.rfind("OFF") == std::string::npos) + { + std::cerr << "Problem reading off file: not an off file" << std::endl; + std::cerr << line << std::endl; + return false; + } + + // check if binary file + if (line.rfind("BINARY") != std::string::npos) + { + return this->import_off_bin(fp); + } + + + // read number of vertices, edges, faces + this->nb_vertices_ = this->read_uint(fp,line); + this->nb_faces_ = this->read_uint(fp,line); + this->nb_edges_ = this->read_uint(fp,line); + + ChunkArray* position = this->vertex_attributes_.template add_attribute("position"); + + // read vertices position + std::vector vertices_id; + vertices_id.reserve(this->nb_vertices_); + + for (unsigned int i = 0; i < this->nb_vertices_; ++i) + { + + double x = this->read_double(fp,line); + double y = this->read_double(fp,line); + double z = this->read_double(fp,line); + + VEC3 pos{Scalar(x), Scalar(y), Scalar(z)}; + + unsigned int vertex_id = this->vertex_attributes_.template insert_lines<1>(); + (*position)[vertex_id] = pos; + + vertices_id.push_back(vertex_id); + } + + // read faces (vertex indices) + this->faces_nb_edges_.reserve(this->nb_faces_); + this->faces_vertex_indices_.reserve(this->nb_vertices_ * 8); + for (unsigned int i = 0; i < this->nb_faces_; ++i) + { + unsigned int n = this->read_uint(fp,line); + this->faces_nb_edges_.push_back(n); + for (unsigned int j = 0; j < n; ++j) + { + unsigned int index = this->read_uint(fp,line); + this->faces_vertex_indices_.push_back(vertices_id[index]); + } + + } + + return true; + } + + inline bool import_off_bin(std::istream& fp) + { + char buffer1[12]; + fp.read(buffer1,12); + + this->nb_vertices_= swap_endianness_native_big(*(reinterpret_cast(buffer1))); + this->nb_faces_= swap_endianness_native_big(*(reinterpret_cast(buffer1+4))); + this->nb_edges_= swap_endianness_native_big(*(reinterpret_cast(buffer1+8))); + + + ChunkArray* position = this->vertex_attributes_.template add_attribute("position"); + + + static const unsigned int BUFFER_SZ = 1024*1024; + float* buff_pos = new float[3*BUFFER_SZ]; + std::vector vertices_id; + vertices_id.reserve(this->nb_vertices_); + + unsigned j = BUFFER_SZ; + for (unsigned int i = 0; i < this->nb_vertices_; ++i,++j) + { + if (j == BUFFER_SZ) + { + j = 0; + // read from file into buffer + if (i+BUFFER_SZ < this->nb_vertices_) + fp.read(reinterpret_cast(buff_pos),3*sizeof(float)*BUFFER_SZ); + else + fp.read(reinterpret_cast(buff_pos),3*sizeof(float)*(this->nb_vertices_-i)); + + //endian + unsigned int* ptr = reinterpret_cast(buff_pos); + for (unsigned int k=0; k< 3*BUFFER_SZ;++k) + { + *ptr = swap_endianness_native_big(*ptr); + ++ptr; + } + } + + VEC3 pos{buff_pos[3*j], buff_pos[3*j+1], buff_pos[3*j+2]}; + + unsigned int vertex_id = this->vertex_attributes_.template insert_lines<1>(); + (*position)[vertex_id] = pos; + + vertices_id.push_back(vertex_id); + } + + delete[] buff_pos; + + // read faces (vertex indices) + + unsigned int* buff_ind = new unsigned int[BUFFER_SZ]; + this->faces_nb_edges_.reserve(this->nb_faces_); + this->faces_vertex_indices_.reserve(this->nb_vertices_ * 8); + + unsigned int* ptr = buff_ind; + unsigned int nb_read = BUFFER_SZ; + for (unsigned int i = 0; i < this->nb_faces_; ++i) + { + if (nb_read == BUFFER_SZ) + { + fp.read(reinterpret_cast(buff_ind),BUFFER_SZ*sizeof(unsigned int)); + ptr = buff_ind; + for (unsigned int i=0; i< BUFFER_SZ;++i) + { + *ptr = swap_endianness_native_big(*ptr); + ++ptr; + } + ptr = buff_ind; + nb_read =0; + } + + unsigned int n = *ptr++; + nb_read++; + + this->faces_nb_edges_.push_back(n); + for (unsigned int j = 0; j < n; ++j) + { + if (nb_read == BUFFER_SZ) + { + fp.read(reinterpret_cast(buff_ind),BUFFER_SZ*sizeof(unsigned int)); + ptr = buff_ind; + for (unsigned int k=0; k< BUFFER_SZ;++k) + { + *ptr = swap_endianness_native_big(*ptr); + ++ptr; + } + ptr = buff_ind; + nb_read=0; + } + unsigned int index = *ptr++; + nb_read++; + this->faces_vertex_indices_.push_back(vertices_id[index]); + } + } + + delete[] buff_ind; + + return true; + } +private: + static inline double read_double(std::istream& fp, std::string& line) + { + fp >> line; + while (line[0]=='#') + { + fp.ignore(std::numeric_limits::max(), '\n'); + fp >> line; + } + return std::stod(line); + } + + static inline unsigned int read_uint(std::istream& fp, std::string& line) + { + fp >> line; + while (line[0]=='#') + { + fp.ignore(std::numeric_limits::max(), '\n'); + fp >> line; + } + return static_cast((std::stoul(line))); + } +}; + +} // namespace io +} // namespace cgogn + +#endif // IO_OFF_IO_H_ diff --git a/cgogn/io/ply_io.h b/cgogn/io/ply_io.h new file mode 100644 index 00000000..8ad28e61 --- /dev/null +++ b/cgogn/io/ply_io.h @@ -0,0 +1,115 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef IO_PLY_IO_H_ +#define IO_PLY_IO_H_ + +#include +#include + +namespace cgogn +{ + +namespace io +{ + +template +class PlySurfaceImport : public SurfaceImport { +public: + using Self = PlySurfaceImport; + using Inherit = SurfaceImport; + using Scalar = typename geometry::vector_traits::Scalar; + template + using ChunkArray = typename Inherit::template ChunkArray; + + virtual ~PlySurfaceImport() override {} + +protected: + virtual bool import_file_impl(const std::string& filename) override + { + + PlyImportData pid; + + if (! pid.read_file(filename) ) + { + std::cerr << "Unable to open file " << filename << std::endl; + return false; + } + + ChunkArray* position = this->vertex_attributes_.template add_attribute("position"); + ChunkArray* color = nullptr; + if (pid.has_colors()) + { + color = this->vertex_attributes_.template add_attribute("color"); + } + + this->nb_vertices_ = pid.nb_vertices(); + this->nb_faces_ = pid.nb_faces(); + + + // read vertices position + std::vector vertices_id; + vertices_id.reserve(this->nb_vertices_); + + for (unsigned int i = 0; i < this->nb_vertices_; ++i) + { + VEC3 pos; + pid.vertex_position(i, pos); + + unsigned int vertex_id = this->vertex_attributes_.template insert_lines<1>(); + (*position)[vertex_id] = pos; + + vertices_id.push_back(vertex_id); + + if (pid.has_colors()) + { + VEC3 rgb; + pid.vertex_color_float32(i, rgb); + + (*color)[vertex_id] = pos; + } + } + + // read faces (vertex indices) + this->faces_nb_edges_.reserve(this->nb_faces_); + this->faces_vertex_indices_.reserve(this->nb_vertices_ * 8); + for (unsigned int i = 0; i < this->nb_faces_; ++i) + { + unsigned int n = pid.get_face_valence(i); + this->faces_nb_edges_.push_back(n); + int* indices = pid.get_face_indices(i); + for (unsigned int j = 0; j < n; ++j) + { + unsigned int index = (unsigned int)(indices[j]); + this->faces_vertex_indices_.push_back(vertices_id[index]); + } + } + + return true; + } +}; + + +}// namespace io +} // namespace cgogn +#endif // IO_PLY_IO_H_ diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index 361fbb10..f03b0b0b 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -29,17 +29,13 @@ #include #include +#include #include #include #include -#include -#include -#include - -#include #include -#include +#include namespace cgogn { @@ -47,52 +43,23 @@ namespace cgogn namespace io { -enum SurfaceFileType -{ - SurfaceFileType_UNKNOWN = 0, - SurfaceFileType_OFF, - SurfaceFileType_OBJ, - SurfaceFileType_PLY, - SurfaceFileType_VTK_LEGACY -}; - -inline SurfaceFileType get_file_type(const std::string& filename) -{ - const std::string& extension = to_lower(get_extension(filename)); - if (extension == "off") - return SurfaceFileType_OFF; - if (extension == "obj") - return SurfaceFileType_OBJ; - if (extension == "ply") - return SurfaceFileType_PLY; - if (extension == "vtk") - return SurfaceFileType_VTK_LEGACY; - return SurfaceFileType_UNKNOWN; -} - template class SurfaceImport { public: - using Self = SurfaceImport; using Map = CMap2; - using Vertex = typename Map::Vertex; - using Edge = typename Map::Edge; - using Face = typename Map::Face; static const unsigned int CHUNK_SIZE = MAP_TRAITS::CHUNK_SIZE; template using ChunkArray = ChunkArray; using ChunkArrayContainer = cgogn::ChunkArrayContainer; - template using AttributeHandler = AttributeHandler; - template - using VertexAttributeHandler = typename Map::template VertexAttributeHandler; +protected: unsigned int nb_vertices_; unsigned int nb_edges_; unsigned int nb_faces_; @@ -103,9 +70,7 @@ class SurfaceImport ChunkArrayContainer vertex_attributes_; ChunkArrayContainer face_attributes_; - using DataIOGen = cgogn::io::DataIOGen; - template - using DataIO = cgogn::io::DataIO; +public: SurfaceImport() : nb_vertices_(0u) @@ -115,7 +80,7 @@ class SurfaceImport ,faces_vertex_indices_() {} - ~SurfaceImport() + virtual ~SurfaceImport() {} SurfaceImport(const Self&) = delete; @@ -134,58 +99,29 @@ class SurfaceImport face_attributes_.remove_attributes(); } - template - bool import_file(const std::string& filename) - { - return import_file(filename, get_file_type(filename)); - } - - template - bool import_file(const std::string& filename, SurfaceFileType type) + inline bool import_file(const std::string& filename) { - //ensure that locale are set to C for reading files +// this->clear(); Scoped_C_Locale loc; - clear(); - - std::ifstream fp(filename.c_str(), std::ios::in); - if (!fp.good()) { - std::cerr << "Unable to open file " << filename << std::endl; - return false; - } - - bool result = false; - switch (type) - { - case SurfaceFileType_UNKNOWN : - std::cerr << "Unknown file type " << filename << std::endl; - result = false; - break; - case SurfaceFileType_OFF : - result = import_OFF(fp); - break; - case SurfaceFileType_OBJ : - result = import_OBJ(fp); - break; - case SurfaceFileType_VTK_LEGACY : - result = import_vtk_legacy(fp); - break; - case SurfaceFileType_PLY : - fp.close(); - result = import_ply(filename); - break; - + // test if file exist + std::ifstream fp(filename.c_str(), std::ios::in); + if (!fp.good()) + { + std::cerr << "Unable to open file \"" << filename << "\"" << std::endl; + return false; + } } - if (!result) - this->clear(); - - return result; + return this->import_file_impl(filename); } - void create_map(Map& map) + inline void create_map(Map& map) { + using Vertex = typename Map::Vertex; + using Edge = typename Map::Edge; + using Face = typename Map::Face; using MapBuilder = cgogn::CMap2Builder_T; if (this->nb_vertices_ == 0u) @@ -197,7 +133,7 @@ class SurfaceImport mbuild.template create_embedding(); mbuild.template swap_chunk_array_container(this->vertex_attributes_); - VertexAttributeHandler> darts_per_vertex = + typename Map::template VertexAttributeHandler> darts_per_vertex = map.template add_attribute, Vertex::ORBIT>("darts_per_vertex"); unsigned int faces_vertex_index = 0; @@ -287,617 +223,7 @@ class SurfaceImport } protected: - - template - bool import_OFF(std::ifstream& fp) - { - using Scalar = typename VEC3::Scalar; - - std::string line; - line.reserve(512); - - // local function for reading double with comment ignoring - auto read_double = [&fp,&line]() -> double - { - fp >> line; - while (line[0]=='#') - { - fp.ignore(std::numeric_limits::max(), '\n'); - fp >> line; - } - return std::stod(line); - }; - - // local function for reading int with comment ignoring - auto read_uint = [&fp,&line]() -> unsigned int - { - fp >> line; - while (line[0]=='#') - { - fp.ignore(std::numeric_limits::max(), '\n'); - fp >> line; - } - return (unsigned int)(std::stoul(line)); - }; - - - - // read OFF header - std::getline(fp, line); - if (line.rfind("OFF") == std::string::npos) - { - std::cerr << "Problem reading off file: not an off file" << std::endl; - std::cerr << line << std::endl; - return false; - } - - // check if binary file - if (line.rfind("BINARY") != std::string::npos) - { - return import_OFF_BIN(fp); - } - - - // read number of vertices, edges, faces - nb_vertices_ = read_uint(); - nb_faces_ = read_uint(); - nb_edges_ = read_uint(); - - ChunkArray* position = vertex_attributes_.template add_attribute("position"); - - // read vertices position - std::vector vertices_id; - vertices_id.reserve(nb_vertices_); - - for (unsigned int i = 0; i < nb_vertices_; ++i) - { - - double x = read_double(); - double y = read_double(); - double z = read_double(); - - VEC3 pos{Scalar(x), Scalar(y), Scalar(z)}; - - unsigned int vertex_id = vertex_attributes_.template insert_lines<1>(); - (*position)[vertex_id] = pos; - - vertices_id.push_back(vertex_id); - } - - // read faces (vertex indices) - faces_nb_edges_.reserve(nb_faces_); - faces_vertex_indices_.reserve(nb_vertices_ * 8); - for (unsigned int i = 0; i < nb_faces_; ++i) - { - unsigned int n = read_uint(); - faces_nb_edges_.push_back(n); - for (unsigned int j = 0; j < n; ++j) - { - unsigned int index = read_uint(); - faces_vertex_indices_.push_back(vertices_id[index]); - } - - } - - return true; - } - - template - bool import_OFF_BIN(std::ifstream& fp) - { - char buffer1[12]; - fp.read(buffer1,12); - - nb_vertices_= swap_endianness_native_big(*(reinterpret_cast(buffer1))); - nb_faces_= swap_endianness_native_big(*(reinterpret_cast(buffer1+4))); - nb_edges_= swap_endianness_native_big(*(reinterpret_cast(buffer1+8))); - - - ChunkArray* position = vertex_attributes_.template add_attribute("position"); - - - static const unsigned int BUFFER_SZ = 1024*1024; - float* buff_pos = new float[3*BUFFER_SZ]; - std::vector vertices_id; - vertices_id.reserve(nb_vertices_); - - unsigned j = BUFFER_SZ; - for (unsigned int i = 0; i < nb_vertices_; ++i,++j) - { - if (j == BUFFER_SZ) - { - j = 0; - // read from file into buffer - if (i+BUFFER_SZ < nb_vertices_) - fp.read(reinterpret_cast(buff_pos),3*sizeof(float)*BUFFER_SZ); - else - fp.read(reinterpret_cast(buff_pos),3*sizeof(float)*(nb_vertices_-i)); - - //endian - unsigned int* ptr = reinterpret_cast(buff_pos); - for (unsigned int k=0; k< 3*BUFFER_SZ;++k) - { - *ptr = swap_endianness_native_big(*ptr); - ++ptr; - } - } - - VEC3 pos{buff_pos[3*j], buff_pos[3*j+1], buff_pos[3*j+2]}; - - unsigned int vertex_id = vertex_attributes_.template insert_lines<1>(); - (*position)[vertex_id] = pos; - - vertices_id.push_back(vertex_id); - } - - delete[] buff_pos; - - // read faces (vertex indices) - - unsigned int* buff_ind = new unsigned int[BUFFER_SZ]; - faces_nb_edges_.reserve(nb_faces_); - faces_vertex_indices_.reserve(nb_vertices_ * 8); - - unsigned int* ptr = buff_ind; - unsigned int nb_read = BUFFER_SZ; - for (unsigned int i = 0; i < nb_faces_; ++i) - { - if (nb_read == BUFFER_SZ) - { - fp.read(reinterpret_cast(buff_ind),BUFFER_SZ*sizeof(unsigned int)); - ptr = buff_ind; - for (unsigned int i=0; i< BUFFER_SZ;++i) - { - *ptr = swap_endianness_native_big(*ptr); - ++ptr; - } - ptr = buff_ind; - nb_read =0; - } - - unsigned int n = *ptr++; - nb_read++; - - faces_nb_edges_.push_back(n); - for (unsigned int j = 0; j < n; ++j) - { - if (nb_read == BUFFER_SZ) - { - fp.read(reinterpret_cast(buff_ind),BUFFER_SZ*sizeof(unsigned int)); - ptr = buff_ind; - for (unsigned int k=0; k< BUFFER_SZ;++k) - { - *ptr = swap_endianness_native_big(*ptr); - ++ptr; - } - ptr = buff_ind; - nb_read=0; - } - unsigned int index = *ptr++; - nb_read++; - faces_vertex_indices_.push_back(vertices_id[index]); - } - } - - delete[] buff_ind; - - return true; - } - - - template - bool import_OBJ(std::ifstream& fp) - { - using Scalar = typename VEC3::Scalar; - - ChunkArray* position = - vertex_attributes_.template add_attribute("position"); - - std::string line, tag; - - do - { - fp >> tag; - std::getline(fp, line); - } while (tag != std::string("v")); - - // lecture des sommets - std::vector vertices_id; - vertices_id.reserve(102400); - - unsigned int i = 0; - do - { - if (tag == std::string("v")) - { - std::stringstream oss(line); - - double x, y, z; - oss >> x; - oss >> y; - oss >> z; - - VEC3 pos{Scalar(x), Scalar(y), Scalar(z)}; - - unsigned int vertex_id = vertex_attributes_.template insert_lines<1>(); - (*position)[vertex_id] = pos; - - vertices_id.push_back(vertex_id); - i++; - } - - fp >> tag; - std::getline(fp, line); - } while (!fp.eof()); - - nb_vertices_ = static_cast(vertices_id.size()); - - fp.clear(); - fp.seekg(0, std::ios::beg); - - do - { - fp >> tag; - std::getline(fp, line); - } while (tag != std::string("f")); - - faces_nb_edges_.reserve(vertices_id.size() * 2); - faces_vertex_indices_.reserve(vertices_id.size() * 8); - - std::vector table; - table.reserve(64); - do - { - if (tag == std::string("f")) // lecture d'une face - { - std::stringstream oss(line); - - table.clear(); - while (!oss.eof()) // lecture de tous les indices - { - std::string str; - oss >> str; - - unsigned int ind = 0; - - while ((ind < str.length()) && (str[ind] != '/')) - ind++; - - if (ind > 0) - { - unsigned int index; - std::stringstream iss(str.substr(0, ind)); - iss >> index; - table.push_back(index); - } - } - - unsigned int n = static_cast(table.size()); - faces_nb_edges_.push_back(static_cast(n)); - for (unsigned int j = 0; j < n; ++j) - { - unsigned int index = table[j] - 1; // indices start at 1 - faces_vertex_indices_.push_back(vertices_id[index]); - } - nb_faces_++; - } - fp >> tag; - std::getline(fp, line); - } while (!fp.eof()); - - return true; - } - - - - template - bool import_ply(const std::string& filename) - { - - PlyImportData pid; - - if (! pid.read_file(filename) ) - { - std::cerr << "Unable to open file " << filename << std::endl; - return false; - } - - ChunkArray* position = vertex_attributes_.template add_attribute("position"); - ChunkArray* color = nullptr; - if (pid.has_colors()) - { - color = vertex_attributes_.template add_attribute("color"); - } - - nb_vertices_ = pid.nb_vertices(); - nb_faces_ = pid.nb_faces(); - - - // read vertices position - std::vector vertices_id; - vertices_id.reserve(nb_vertices_); - - for (unsigned int i = 0; i < nb_vertices_; ++i) - { - VEC3 pos; - pid.vertex_position(i, pos); - - unsigned int vertex_id = vertex_attributes_.template insert_lines<1>(); - (*position)[vertex_id] = pos; - - vertices_id.push_back(vertex_id); - - if (pid.has_colors()) - { - VEC3 rgb; - pid.vertex_color_float32(i, rgb); - - (*color)[vertex_id] = pos; - } - } - - // read faces (vertex indices) - faces_nb_edges_.reserve(nb_faces_); - faces_vertex_indices_.reserve(nb_vertices_ * 8); - for (unsigned int i = 0; i < nb_faces_; ++i) - { - unsigned int n = pid.get_face_valence(i); - faces_nb_edges_.push_back(n); - int* indices = pid.get_face_indices(i); - for (unsigned int j = 0; j < n; ++j) - { - unsigned int index = (unsigned int)(indices[j]); - faces_vertex_indices_.push_back(vertices_id[index]); - } - } - - return true; - } - - template - bool import_vtk_legacy(std::ifstream& fp) - { - enum VTK_TYPE - { - UNKNOWN = 0, - UNSTRUCTURED_GRID, - POLYDATA - }; - - VTK_TYPE vtk_type(VTK_TYPE::UNKNOWN); - - std::cout << "Opening a legacy vtk file" << std::endl; - using Scalar = typename VEC3::Scalar; - - std::string line; - std::string word; - line.reserve(512); - word.reserve(128); - - // printing the 2 first lines - std::getline(fp, line); - std::cout << line << std::endl; - std::getline(fp, line); - std::cout << line << std::endl; - - fp >> word; - bool ascii_file = to_upper(word) == "ASCII"; - cgogn_assert(ascii_file || to_upper(word) == "BINARY"); - - fp >> word; - cgogn_assert(to_upper(word) == "DATASET"); - fp >> word; - const std::string& dataset = to_upper(word); - if (dataset == "UNSTRUCTURED_GRID") - vtk_type = VTK_TYPE::UNSTRUCTURED_GRID; - else { - if (dataset == "POLYDATA") - vtk_type = VTK_TYPE::POLYDATA; - } - - DataIO cells; - DataIO cell_types; - - ChunkArray* position_arr = vertex_attributes_.template add_attribute("position"); - - if (vtk_type == VTK_TYPE::UNSTRUCTURED_GRID || vtk_type == VTK_TYPE::POLYDATA) - { - while(!fp.eof()) - { - std::getline(fp,line); - word.clear(); - std::istringstream sstream(line); - sstream >> word; - word = to_upper(word); - - if (word == "POINTS") - { - std::string type_str; - sstream >> this->nb_vertices_ >> type_str; - type_str = to_lower(type_str); - DataIO positions; - positions.read_n(fp, nb_vertices_, !ascii_file, false); - for (std::size_t i = 0ul ; i < nb_vertices_ ; ++i) - vertex_attributes_.template insert_lines<1>(); - positions.to_chunk_array(position_arr); - } else { - if (word == "CELLS" || word == "POLYGONS" || word == "TRIANGLE_STRIPS") - { - unsigned int size; - sstream >> this->nb_faces_ >> size; - cells.read_n(fp, size, !ascii_file, false); - - std::vector* cell_types_vec = static_cast*>(cell_types.get_data()); - cgogn_assert(cell_types_vec != nullptr); - if (word == "POLYGONS") - { - cell_types_vec->reserve(nb_faces_); - for (unsigned i = 0u; i < nb_faces_ ;++i) - { - cell_types_vec->push_back(VTK_CELL_TYPES::VTK_POLYGON); - } - } else if (word == "TRIANGLE_STRIPS") - { - cell_types_vec->reserve(nb_faces_); - for (unsigned i = 0u; i < nb_faces_ ;++i) - { - cell_types_vec->push_back(VTK_CELL_TYPES::VTK_TRIANGLE_STRIP); - } - } - - } else { - if (word == "CELL_TYPES") - { - unsigned int nbc; - sstream >> nbc; - cell_types.read_n(fp, nbc, !ascii_file, false); - } else { - if (word == "POINT_DATA" || word == "CELL_DATA") - { - const bool cell_data = (word == "CELL_DATA"); - unsigned int nb_data; - sstream >> nb_data; - - if (!cell_data) - { - cgogn_assert(this->nb_vertices_ == 0u || nb_data == this->nb_vertices_); - } - std::ifstream::pos_type previous_pos; - do { - previous_pos = fp.tellg(); - std::getline(fp, line); - sstream.str(line); - sstream.clear(); - word.clear(); - sstream >> word; - word = to_upper(word); - if (word == "SCALARS" || word == "VECTOR" || word == "NORMALS") - { - const bool is_vector = !(word == "SCALARS"); - std::string att_name; - std::string att_type; - unsigned int num_comp = is_vector? 3u : 1u; - sstream >> att_name >> att_type >> num_comp; - std::cout << "reading attribute \"" << att_name << "\" of type " << att_type << " (" << num_comp << " components)." << std::endl; - - const auto pos_before_lookup_table = fp.tellg(); // the lookup table might (or might not) be defined - std::getline(fp,line); - sstream.str(line); - sstream.clear(); - std::string lookup_table; - std::string lookup_table_name; - sstream >> lookup_table >> lookup_table_name; - if (to_upper(lookup_table) == "LOOKUP_TABLE") - { - std::cout << "VTK import : ignoring lookup table named \"" << lookup_table_name << "\"" << std::endl; - } else { - fp.seekg(pos_before_lookup_table); // if there wasn't a lookup table we go back and start reading the numerical values - } - - std::unique_ptr att(DataIOGen::newDataIO(att_type, num_comp)); - att->read_n(fp, nb_data, !ascii_file, false); - if (cell_data) - att->to_chunk_array(att->add_attribute(face_attributes_, att_name)); - else - att->to_chunk_array(att->add_attribute(vertex_attributes_, att_name)); - } else { - if (word == "FIELD") - { - std::string field_name; - unsigned int num_arrays = 0u; - sstream >> field_name >> num_arrays; - for (unsigned int i = 0u ; i< num_arrays; ++i) - { - std::getline(fp,line); - sstream.str(line); - sstream.clear(); - std::string data_name; - unsigned int nb_comp; - unsigned int nb_data; - std::string data_type; - sstream >> data_name >> nb_comp >> nb_data >> data_type; - std::cout << "reading field \"" << data_name << "\" of type " << data_type << " (" << nb_comp << " components)." << std::endl; - std::unique_ptr att(DataIOGen::newDataIO(data_type, nb_comp)); - att->read_n(fp, nb_data, !ascii_file, false); - if (cell_data) - att->to_chunk_array(att->add_attribute(face_attributes_, data_name)); - else - att->to_chunk_array(att->add_attribute(vertex_attributes_, data_name)); - } - } else - if (word == "LOOKUP_TABLE") - { - std::string table_name; - unsigned int nb_data = 0u; - sstream >> table_name >> nb_data; - std::cout << "ignoring the definition of the lookuptable named \"" << table_name << "\"" << std::endl; - if (ascii_file) - { - DataIO trash; - trash.skip_n(fp, nb_data, false); - } else - { - DataIO trash; - trash.skip_n(fp, nb_data, true); - } - } - } - } while (word != "POINT_DATA" && word != "CELL_DATA" && (!fp.eof())); - if (!fp.eof()) - { - fp.seekg(previous_pos); - word.clear(); - } else - break; - } else - { - if (!word.empty()) - std::cerr << "VTK keyword \"" << word << "\" is not supported." << std::endl; - } - } - } - } - } - } - - auto cells_it = static_cast*>(cells.get_data())->begin(); - const std::vector* cell_types_vec = static_cast*>(cell_types.get_data()); - for(auto cell_types_it = cell_types_vec->begin(); cell_types_it != cell_types_vec->end() ; ) - { - const std::size_t nb_vert = *(cells_it++); - const int cell_type = *(cell_types_it++); - - if (cell_type != VTK_CELL_TYPES::VTK_TRIANGLE_STRIP) - { - faces_nb_edges_.push_back(nb_vert); - for (std::size_t i = 0ul ; i < nb_vert;++i) - { - faces_vertex_indices_.push_back(*cells_it++); - } - } else { - std::vector vertexIDS; - vertexIDS.reserve(nb_vert); - for (std::size_t i = 0ul ; i < nb_vert;++i) - { - vertexIDS.push_back(*cells_it++); - } - - for (unsigned int i = 0u ; i < nb_vert -2u; ++i) - { - if (i != 0u) - ++nb_faces_; - faces_nb_edges_.push_back(3); - faces_vertex_indices_.push_back(vertexIDS[i]); - faces_vertex_indices_.push_back(vertexIDS[i+1]); - faces_vertex_indices_.push_back(vertexIDS[i+2]); - if (i % 2u == 0u) - std::swap(faces_vertex_indices_.back(), *(faces_vertex_indices_.end()-2)); - } - } - } - - return true; - } + virtual bool import_file_impl(const std::string& filename) = 0; }; #if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_SURFACE_IMPORT_CPP_)) diff --git a/cgogn/io/vtk_cell_types.h b/cgogn/io/vtk_cell_types.h deleted file mode 100644 index f9e39f98..00000000 --- a/cgogn/io/vtk_cell_types.h +++ /dev/null @@ -1,89 +0,0 @@ -/******************************************************************************* -* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * -* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * -* * -* This library is free software; you can redistribute it and/or modify it * -* under the terms of the GNU Lesser General Public License as published by the * -* Free Software Foundation; either version 2.1 of the License, or (at your * -* option) any later version. * -* * -* This library is distributed in the hope that it will be useful, but WITHOUT * -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * -* for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with this library; if not, write to the Free Software Foundation, * -* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * -* * -* Web site: http://cgogn.unistra.fr/ * -* Contact information: cgogn@unistra.fr * -* * -*******************************************************************************/ - -#ifndef IO_VTK_CELL_TYPES_H_ -#define IO_VTK_CELL_TYPES_H_ - -namespace cgogn -{ - -enum VTK_CELL_TYPES -{ - VTK_VERTEX = 1, - VTK_POLY_VERTEX = 2, - VTK_LINE = 3, - VTK_POLY_LINE = 4, - VTK_TRIANGLE = 5, - VTK_TRIANGLE_STRIP = 6, - VTK_POLYGON = 7, - VTK_PIXEL = 8, - VTK_QUAD = 9, - - VTK_TETRA = 10, - VTK_VOXEL = 11, - VTK_HEXAHEDRON = 12, - VTK_WEDGE = 13, - VTK_PYRAMID = 14, - - VTK_QUADRATIC_EDGE = 21, - VTK_QUADRATIC_TRIANGLE = 22, - VTK_QUADRATIC_QUAD = 23, - VTK_QUADRATIC_TETRA = 24, - VTK_QUADRATIC_HEXAHEDRON = 25 -}; - -/** - * @brief vtk_data_type_to_cgogn_name_of_type : convert the type names we can find in VTK files to the one we use in cgogn. - * @param vtk_type_str a typename extracted from a vtk file - * @return a typename string that can be match with some cgogn::name_of_type - */ -inline std::string vtk_data_type_to_cgogn_name_of_type(const std::string& vtk_type_str) -{ - const std::string& data_type = to_lower(vtk_type_str); - if (data_type == "char" || data_type == "int8") - return name_of_type(std::int8_t()); - if (data_type == "unsigned_char" || data_type == "uint8") - return name_of_type(std::uint8_t()); - if (data_type == "short" || data_type == "int16") - return name_of_type(std::int16_t()); - if (data_type == "unsigned_short" || data_type == "uint16") - return name_of_type(std::uint16_t()); - if (data_type == "int" || data_type == "int32") - return name_of_type(std::int32_t()); - if (data_type == "unsigned_int" || data_type == "uint32") - return name_of_type(std::uint32_t()); - if (data_type == "long" || data_type == "int64") - return name_of_type(std::int64_t()); - if (data_type == "unsigned_long" || data_type == "uint64") - return name_of_type(std::uint64_t()); - if (data_type == "float" || data_type == "float32") - return name_of_type(float()); - if (data_type == "double" || data_type == "float64") - return name_of_type(double()); - - std::cerr << "vtk_data_type_to_cgogn_name_of_type : unknown vtk type : " << vtk_type_str << std::endl; - return std::string(); -} - -} // namespace cgogn -#endif // IO_VTK_CELL_TYPES_H_ diff --git a/cgogn/io/vtk_io.h b/cgogn/io/vtk_io.h new file mode 100644 index 00000000..8fc0876d --- /dev/null +++ b/cgogn/io/vtk_io.h @@ -0,0 +1,402 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef IO_VTK_IO_H_ +#define IO_VTK_IO_H_ + +#include +#include + +#include +#include + + +namespace cgogn +{ + +namespace io +{ + +template +class VtkIO +{ +public : + enum VTK_CELL_TYPES + { + VTK_VERTEX = 1, + VTK_POLY_VERTEX = 2, + VTK_LINE = 3, + VTK_POLY_LINE = 4, + VTK_TRIANGLE = 5, + VTK_TRIANGLE_STRIP = 6, + VTK_POLYGON = 7, + VTK_PIXEL = 8, + VTK_QUAD = 9, + + VTK_TETRA = 10, + VTK_VOXEL = 11, + VTK_HEXAHEDRON = 12, + VTK_WEDGE = 13, + VTK_PYRAMID = 14, + + VTK_QUADRATIC_EDGE = 21, + VTK_QUADRATIC_TRIANGLE = 22, + VTK_QUADRATIC_QUAD = 23, + VTK_QUADRATIC_TETRA = 24, + VTK_QUADRATIC_HEXAHEDRON = 25 + }; + + + enum VTK_MESH_TYPE + { + UNKNOWN = 0, + UNSTRUCTURED_GRID, + POLYDATA + }; + + using Self = VtkIO; + using DataIOGen = cgogn::io::DataIOGen; + template + using DataIO = cgogn::io::DataIO; + + virtual ~VtkIO() {} + +protected : + DataIO positions_; + DataIO cells_; + DataIO cell_types_; + +protected : + virtual void add_vertex_attribute(const DataIOGen& attribute_data, const std::string& attribute_name) = 0; + virtual void add_cell_attribute(const DataIOGen& attribute_data, const std::string& attribute_name) = 0; + + bool parse_vtk_legacy_file(std::ifstream& fp) + { + VTK_MESH_TYPE vtk_type(VTK_MESH_TYPE::UNKNOWN); + + std::cout << "Opening a legacy vtk file" << std::endl; + using Scalar = typename VEC3::Scalar; + + std::string line; + std::string word; + line.reserve(512); + word.reserve(128); + + // printing the 2 first lines + std::getline(fp, line); + std::cout << line << std::endl; + std::getline(fp, line); + std::cout << line << std::endl; + + fp >> word; + bool ascii_file = to_upper(word) == "ASCII"; + cgogn_assert(ascii_file || to_upper(word) == "BINARY"); + + fp >> word; + cgogn_assert(to_upper(word) == "DATASET"); + fp >> word; + const std::string& dataset = to_upper(word); + if (dataset == "UNSTRUCTURED_GRID") + vtk_type = VTK_MESH_TYPE::UNSTRUCTURED_GRID; + else { + if (dataset == "POLYDATA") + vtk_type = VTK_MESH_TYPE::POLYDATA; + } + + unsigned int nb_vertices = 0u; + unsigned int nb_cells = 0u; + + if (vtk_type == VTK_MESH_TYPE::UNSTRUCTURED_GRID || vtk_type == VTK_MESH_TYPE::POLYDATA) + { + while(!fp.eof()) + { + std::getline(fp,line); + word.clear(); + std::istringstream sstream(line); + sstream >> word; + word = to_upper(word); + + if (word == "POINTS") + { + std::string type_str; + sstream >> nb_vertices >> type_str; + type_str = to_lower(type_str); + positions_.read_n(fp, nb_vertices, !ascii_file, false); + this->add_vertex_attribute(positions_,"position"); + } else { + if (word == "CELLS" || word == "POLYGONS" || word == "TRIANGLE_STRIPS") + { + unsigned int size; + sstream >> nb_cells >> size; + cells_.read_n(fp, size, !ascii_file, false); + + std::vector* cell_types_vec = static_cast*>(cell_types_.get_data()); + cgogn_assert(cell_types_vec != nullptr); + if (word == "POLYGONS") + { + cell_types_vec->reserve(nb_cells); + for (unsigned i = 0u; i < nb_cells ;++i) + { + cell_types_vec->push_back(VTK_CELL_TYPES::VTK_POLYGON); + } + } else if (word == "TRIANGLE_STRIPS") + { + cell_types_vec->reserve(nb_cells); + for (unsigned i = 0u; i < nb_cells ;++i) + { + cell_types_vec->push_back(VTK_CELL_TYPES::VTK_TRIANGLE_STRIP); + } + } + + } else { + if (word == "CELL_TYPES") + { + unsigned int nbc; + sstream >> nbc; + cell_types_.read_n(fp, nbc, !ascii_file, false); + } else { + if (word == "POINT_DATA" || word == "CELL_DATA") + { + const bool cell_data = (word == "CELL_DATA"); + unsigned int nb_data; + sstream >> nb_data; + + if (!cell_data) + { + cgogn_assert( nb_vertices == 0u || nb_data == nb_vertices ); + } + std::ifstream::pos_type previous_pos; + do { + previous_pos = fp.tellg(); + std::getline(fp, line); + sstream.str(line); + sstream.clear(); + word.clear(); + sstream >> word; + word = to_upper(word); + if (word == "SCALARS" || word == "VECTOR" || word == "NORMALS") + { + const bool is_vector = !(word == "SCALARS"); + std::string att_name; + std::string att_type; + unsigned int num_comp = is_vector? 3u : 1u; + sstream >> att_name >> att_type >> num_comp; + std::cout << "reading attribute \"" << att_name << "\" of type " << att_type << " (" << num_comp << " components)." << std::endl; + + const auto pos_before_lookup_table = fp.tellg(); // the lookup table might (or might not) be defined + std::getline(fp,line); + sstream.str(line); + sstream.clear(); + std::string lookup_table; + std::string lookup_table_name; + sstream >> lookup_table >> lookup_table_name; + if (to_upper(lookup_table) == "LOOKUP_TABLE") + { + std::cout << "VTK import : ignoring lookup table named \"" << lookup_table_name << "\"" << std::endl; + } else { + fp.seekg(pos_before_lookup_table); // if there wasn't a lookup table we go back and start reading the numerical values + } + + std::unique_ptr att(DataIOGen::template newDataIO(att_type, num_comp)); + att->read_n(fp, nb_data, !ascii_file, false); + if (cell_data) + this->add_cell_attribute(*att, att_name); + else + this->add_vertex_attribute(*att, att_name); + } else { + if (word == "FIELD") + { + std::string field_name; + unsigned int num_arrays = 0u; + sstream >> field_name >> num_arrays; + for (unsigned int i = 0u ; i< num_arrays; ++i) + { + do { + std::getline(fp,line); + } while (line.empty()); + + sstream.str(line); + sstream.clear(); + std::string data_name; + unsigned int nb_comp; + unsigned int nb_data; + std::string data_type; + sstream >> data_name >> nb_comp >> nb_data >> data_type; + std::cout << "reading field \"" << data_name << "\" of type " << data_type << " (" << nb_comp << " components)." << std::endl; + std::unique_ptr att(DataIOGen::template newDataIO(data_type, nb_comp)); + att->read_n(fp, nb_data, !ascii_file, false); + if (cell_data) + this->add_cell_attribute(*att, data_name); + else + this->add_vertex_attribute(*att, data_name); + } + } else + if (word == "LOOKUP_TABLE") + { + std::string table_name; + unsigned int nb_data = 0u; + sstream >> table_name >> nb_data; + std::cout << "ignoring the definition of the lookuptable named \"" << table_name << "\"" << std::endl; + if (ascii_file) + { + DataIO trash; + trash.skip_n(fp, nb_data, false); + } else + { + DataIO trash; + trash.skip_n(fp, nb_data, true); + } + } + } + } while (word != "POINT_DATA" && word != "CELL_DATA" && (!fp.eof())); + if (!fp.eof()) + { + fp.seekg(previous_pos); + word.clear(); + } else + break; + } else + { + if (!word.empty()) + std::cerr << "VTK keyword \"" << word << "\" is not supported." << std::endl; + } + } + } + } + } + } + return true; + } + + static inline std::string vtk_data_type_to_cgogn_name_of_type(const std::string& vtk_type_str) + { + const std::string& data_type = to_lower(vtk_type_str); + if (data_type == "char" || data_type == "int8") + return name_of_type(std::int8_t()); + if (data_type == "unsigned_char" || data_type == "uint8") + return name_of_type(std::uint8_t()); + if (data_type == "short" || data_type == "int16") + return name_of_type(std::int16_t()); + if (data_type == "unsigned_short" || data_type == "uint16") + return name_of_type(std::uint16_t()); + if (data_type == "int" || data_type == "int32") + return name_of_type(std::int32_t()); + if (data_type == "unsigned_int" || data_type == "uint32") + return name_of_type(std::uint32_t()); + if (data_type == "long" || data_type == "int64") + return name_of_type(std::int64_t()); + if (data_type == "unsigned_long" || data_type == "uint64") + return name_of_type(std::uint64_t()); + if (data_type == "float" || data_type == "float32") + return name_of_type(float()); + if (data_type == "double" || data_type == "float64") + return name_of_type(double()); + + std::cerr << "vtk_data_type_to_cgogn_name_of_type : unknown vtk type : " << vtk_type_str << std::endl; + return std::string(); + } +}; + + +template +class VtkSurfaceImport : public VtkIO::PRIM_SIZE, VEC3>, public SurfaceImport +{ +public: + using Self = VtkSurfaceImport; + using Inherit_Vtk = VtkIO::PRIM_SIZE, VEC3>; + using Inherit_Import = SurfaceImport; + using DataIOGen = typename Inherit_Vtk::DataIOGen; + template + using DataIO = typename Inherit_Vtk::template DataIO; + using VTK_CELL_TYPES = typename Inherit_Vtk::VTK_CELL_TYPES; + + virtual ~VtkSurfaceImport() override {} +protected: + inline bool read_vtk_legacy_file(std::ifstream& fp) + { + if (!Inherit_Vtk::parse_vtk_legacy_file(fp)) + return false; + + this->nb_vertices_ = this->positions_.get_vec()->size(); + this->nb_faces_ = this->cell_types_.get_vec()->size(); + + auto cells_it = static_cast*>(this->cells_.get_data())->begin(); + const std::vector* cell_types_vec = static_cast*>(this->cell_types_.get_data()); + for(auto cell_types_it = cell_types_vec->begin(); cell_types_it != cell_types_vec->end() ; ) + { + const std::size_t nb_vert = *(cells_it++); + const int cell_type = *(cell_types_it++); + + if (cell_type != VTK_CELL_TYPES::VTK_TRIANGLE_STRIP) + { + this->faces_nb_edges_.push_back(nb_vert); + for (std::size_t i = 0ul ; i < nb_vert;++i) + { + this->faces_vertex_indices_.push_back(*cells_it++); + } + } else { + std::vector vertexIDS; + vertexIDS.reserve(nb_vert); + for (std::size_t i = 0ul ; i < nb_vert;++i) + { + vertexIDS.push_back(*cells_it++); + } + + for (unsigned int i = 0u ; i < nb_vert -2u; ++i) + { + if (i != 0u) + ++this->nb_faces_; + this->faces_nb_edges_.push_back(3); + this->faces_vertex_indices_.push_back(vertexIDS[i]); + this->faces_vertex_indices_.push_back(vertexIDS[i+1]); + this->faces_vertex_indices_.push_back(vertexIDS[i+2]); + if (i % 2u == 0u) + std::swap(this->faces_vertex_indices_.back(), *(this->faces_vertex_indices_.end()-2)); + } + } + } + return true; + } + + virtual void add_vertex_attribute(const DataIOGen& attribute_data, const std::string& attribute_name) override + { + attribute_data.to_chunk_array(attribute_data.add_attribute(this->vertex_attributes_, attribute_name)); + } + virtual void add_cell_attribute(const DataIOGen& attribute_data, const std::string& attribute_name) override + { + attribute_data.to_chunk_array(attribute_data.add_attribute(this->face_attributes_, attribute_name)); + } + virtual bool import_file_impl(const std::string& filename) + { + std::ifstream fp(filename.c_str(), std::ios::in | std::ios::binary); + cgogn_assert(fp.good()); + const FileType file_type = get_file_type(filename); + if (file_type == FileType::FileType_VTK_LEGACY) + return this->read_vtk_legacy_file(fp); + } +}; + +} // namespace io +} // namespace cgogn + +#endif // IO_VTK_IO_H_ From 4477ba1f52d50ebf95b13cdfff7023bbcb8647f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Fri, 4 Mar 2016 16:07:31 +0100 Subject: [PATCH 251/402] restored this->clear() in SurfaceImport MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/surface_import.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index f03b0b0b..1954fb86 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -101,7 +101,7 @@ class SurfaceImport inline bool import_file(const std::string& filename) { -// this->clear(); + this->clear(); Scoped_C_Locale loc; { From 93579e0cc50e3889a3580be6d366e81db3ba777e Mon Sep 17 00:00:00 2001 From: David Cazier Date: Fri, 4 Mar 2016 17:27:10 +0100 Subject: [PATCH 252/402] file transfert --- cgogn/core/cmap/cmap2.h | 154 ++++++++++---------- cgogn/core/tests/cmap/cmap1_test.cpp | 104 ++++++++------ cgogn/core/tests/cmap/cmap1_topo_test.cpp | 19 +-- cgogn/core/tests/cmap/cmap2_test.cpp | 4 +- cgogn/core/tests/cmap/cmap2_topo_test.cpp | 164 +++++++++++++--------- 5 files changed, 243 insertions(+), 202 deletions(-) diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 64f36136..477923f6 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -194,6 +194,83 @@ class CMap2_T : public CMap1_T * High-level embedded and topological operations *******************************************************************************/ +protected: + + /*! + * \brief Add a face in the map. + * \param size : the number of darts in the built face + * \return A dart of the built face. + */ + Dart add_face_topo(unsigned int size) + { + Dart d = Inherit::add_face_topo(size); + Dart e = Inherit::add_face_topo(size); + + Dart it = d; + do + { + phi2_sew(it, e); + it = this->phi1(it); + e = this->phi_1(e); + } while (it != d); + + return d; + } + +public: + + /*! + * \brief Add a face in the map. + * \param size : the number of edges in the built face + * \return The built face + * If the map has Dart, Vertex, Edge, Face or Volume attributes, + * the inserted cells are automatically embedded on new attribute elements. + * More precisely : + * - a Face attribute is created, if needed, for the new face. + */ + Face add_face(unsigned int size) + { + CGOGN_CHECK_CONCRETE_TYPE; + + const Face f = add_face_topo(size); + + if (this->template is_embedded()) + { + foreach_dart_of_orbit(f, [this] (Dart d) + { + this->new_orbit_embedding(CDart(d)); + this->new_orbit_embedding(CDart(phi2(d))); + }); + } + + if (this->template is_embedded()) + { + foreach_dart_of_orbit(f, [this] (Dart d) + { + this->new_orbit_embedding(Vertex(d)); + }); + } + + if (this->template is_embedded()) + { + foreach_dart_of_orbit(f, [this] (Dart d) + { + this->new_orbit_embedding(Edge(d)); + }); + } + + if (this->template is_embedded()) + { + this->new_orbit_embedding(f); + this->new_orbit_embedding(Face(phi2(f.dart))); + } + + if (this->template is_embedded()) + this->new_orbit_embedding(Volume(f.dart)); + + return f; + } + protected: /** @@ -359,83 +436,6 @@ class CMap2_T : public CMap1_T } } -protected: - - /*! - * \brief Add a face in the map. - * \param size : the number of darts in the built face - * \return A dart of the built face. - */ - Dart add_face_topo(unsigned int size) - { - Dart d = Inherit::add_face_topo(size); - Dart e = Inherit::add_face_topo(size); - - Dart it = d; - do - { - phi2_sew(it, e); - it = this->phi1(it); - e = this->phi_1(e); - } while (it != d); - - return d; - } - -public: - - /*! - * \brief Add a face in the map. - * \param size : the number of edges in the built face - * \return The built face - * If the map has Dart, Vertex, Edge, Face or Volume attributes, - * the inserted cells are automatically embedded on new attribute elements. - * More precisely : - * - a Face attribute is created, if needed, for the new face. - */ - Face add_face(unsigned int size) - { - CGOGN_CHECK_CONCRETE_TYPE; - - const Face f = add_face_topo(size); - - if (this->template is_embedded()) - { - foreach_dart_of_orbit(f, [this] (Dart d) - { - this->new_orbit_embedding(CDart(d)); - this->new_orbit_embedding(CDart(phi2(d))); - }); - } - - if (this->template is_embedded()) - { - foreach_dart_of_orbit(f, [this] (Dart d) - { - this->new_orbit_embedding(Vertex(d)); - }); - } - - if (this->template is_embedded()) - { - foreach_dart_of_orbit(f, [this] (Dart d) - { - this->new_orbit_embedding(Edge(d)); - }); - } - - if (this->template is_embedded()) - { - this->new_orbit_embedding(f); - this->new_orbit_embedding(Face(phi2(f.dart))); - } - - if (this->template is_embedded()) - this->new_orbit_embedding(Volume(f.dart)); - - return f; - } - protected: inline void close_hole_topo(Dart d) diff --git a/cgogn/core/tests/cmap/cmap1_test.cpp b/cgogn/core/tests/cmap/cmap1_test.cpp index 391ea1a6..8f5858d1 100644 --- a/cgogn/core/tests/cmap/cmap1_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_test.cpp @@ -45,105 +45,121 @@ class CMap1Test: public ::testing::Test public: using testCMap1 = CMap1; - using VertexAttributeHandler = testCMap1::VertexAttributeHandler; using Vertex = testCMap1::Vertex; - using FaceAttributeHandler = testCMap1::FaceAttributeHandler; using Face = testCMap1::Face; protected: testCMap1 cmap_; - VertexAttributeHandler vertices_; - FaceAttributeHandler faces_; + + /*! + * \brief A vector of darts on which the methods are tested. + */ + std::vector darts_; CMap1Test() { std::srand(static_cast(std::time(0))); - vertices_ = cmap_.add_attribute("vertices"); - faces_ = cmap_.add_attribute("faces"); + cmap_.add_attribute("vertices"); + cmap_.add_attribute("faces"); } - int randomFaces() { - int count = 0; - for (int i = 0; i < NB_MAX; ++i) { - int n = 1 + std::rand() % 100; + /*! + * \brief Generate a random set of faces and put them in darts_ + * \return The total number of added darts or vertices. + * The face size ranges from 1 to 10. + * A random dart of each face is put in the darts_ array. + */ + unsigned int addFaces(unsigned int n) + { + unsigned int count = 0; + for (unsigned int i = 0; i < n; ++i) + { + unsigned int n = 1 + std::rand() % 10; Dart d = cmap_.add_face(n); count += n; while (std::rand()%10 != 1) d = cmap_.phi1(d); - tdarts_[i] = d; + darts_.push_back(d); } return count; } - - std::array tdarts_; }; /*! - * \brief Adding vertices preserves the cell indexation + * \brief Adding faces preserves the cell indexation */ TEST_F(CMap1Test, add_face) { - int n = randomFaces(); + unsigned int countVertices = addFaces(NB_MAX); - EXPECT_EQ(cmap_.nb_cells(), n); + EXPECT_EQ(cmap_.nb_cells(), countVertices); EXPECT_EQ(cmap_.nb_cells(), NB_MAX); EXPECT_TRUE(cmap_.check_map_integrity()); } +/*! + * \brief Removing faces preserves the cell indexation + */ TEST_F(CMap1Test, remove_face) { - int n = randomFaces(); - - int countVertex = n; - int countFace = NB_MAX; - for (int i = 0; i < NB_MAX; ++i) { - Face d = tdarts_[i]; - unsigned int k = cmap_.degree(d); - cmap_.remove_face(d); - countVertex -= k; - --countFace; + unsigned int countVertices = addFaces(NB_MAX); + int countFaces = NB_MAX; + + for (Dart d: darts_) + { + if (std::rand()%3 == 1) { + unsigned int k = cmap_.degree(d); + cmap_.remove_face(d); + countVertices -= k; + --countFaces; + } } - EXPECT_EQ(cmap_.nb_cells(), countVertex); - EXPECT_EQ(cmap_.nb_cells(), countFace); + EXPECT_EQ(cmap_.nb_cells(), countVertices); + EXPECT_EQ(cmap_.nb_cells(), countFaces); EXPECT_TRUE(cmap_.check_map_integrity()); } +/*! + * \brief Splitting vertices preserves the cell indexation + */ TEST_F(CMap1Test, split_vertex) { - int n = randomFaces(); + unsigned int countVertices = addFaces(NB_MAX); - for (int i = 0; i < NB_MAX; ++i) { - Face d = tdarts_[i]; - unsigned int k = cmap_.degree(Face(d)); - cmap_.split_vertex(Vertex(d)); + for (Dart d: darts_) + { + cmap_.split_vertex(d); + ++countVertices; } - EXPECT_EQ(cmap_.nb_cells(), n+NB_MAX); + EXPECT_EQ(cmap_.nb_cells(), countVertices); EXPECT_EQ(cmap_.nb_cells(), NB_MAX); EXPECT_TRUE(cmap_.check_map_integrity()); } +/*! + * \brief Removing vertices preserves the cell indexation + */ TEST_F(CMap1Test, remove_vertex) { - int n = randomFaces(); + unsigned int countVertices = addFaces(NB_MAX); + unsigned int countFaces = NB_MAX; - int countVertex = n; - int countFace = NB_MAX; - for (int i = 0; i < NB_MAX; ++i) { - Face d = tdarts_[i]; - unsigned int k = cmap_.degree(d); + for (Dart d: darts_) + { + unsigned int k = cmap_.degree(Face(d)); cmap_.remove_vertex(Vertex(d)); - --countVertex; - if (k == 1u) --countFace; + --countVertices; + if (k == 1) --countFaces; } - EXPECT_EQ(cmap_.nb_cells(), countVertex); - EXPECT_EQ(cmap_.nb_cells(), countFace); + EXPECT_EQ(cmap_.nb_cells(), countVertices); + EXPECT_EQ(cmap_.nb_cells(), countFaces); EXPECT_TRUE(cmap_.check_map_integrity()); } diff --git a/cgogn/core/tests/cmap/cmap1_topo_test.cpp b/cgogn/core/tests/cmap/cmap1_topo_test.cpp index 33a13b57..1e61c339 100644 --- a/cgogn/core/tests/cmap/cmap1_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_topo_test.cpp @@ -105,8 +105,7 @@ TEST_F(CMap1TopoTest, Constructor) /*! * \brief Sewing and unsewing darts correctly changes the topological relations. * The test perfoms NB_MAX sewing and unsewing on randomly chosen dart of darts_. - * The number of vertices is unchanged, the number of faces changes correctly - * and the map integrity is preserved. + * The map integrity is preserved. */ TEST_F(CMap1TopoTest, phi1_sew_unsew) { @@ -119,26 +118,16 @@ TEST_F(CMap1TopoTest, phi1_sew_unsew) Dart f = darts_[std::rand() % NB_MAX]; Dart nd = phi1(d); Dart ne = phi1(e); - if (d != e) { - if (same_cell(Face(d),Face(e))) - ++countFaces; - else - --countFaces; - } phi1_sew(d, e); EXPECT_TRUE(phi1(d) == ne); EXPECT_TRUE(phi1(e) == nd); Dart nf1 = phi1(f); Dart nf2 = phi1(nf1); phi1_unsew(f); - if (f != nf1) ++countFaces; EXPECT_TRUE(phi1(nf1) == nf1); EXPECT_TRUE(phi1(f) == nf2); } - EXPECT_EQ(nb_darts(), NB_MAX); - EXPECT_EQ(nb_cells(), NB_MAX); - EXPECT_EQ(nb_cells(), countFaces); EXPECT_TRUE(check_map_integrity()); } @@ -204,10 +193,12 @@ TEST_F(CMap1TopoTest, split_vertex_topo) { unsigned int k = degree(Face(d)); split_vertex_topo(d); + ++countVertices; EXPECT_EQ(degree(Face(d)), k+1); } - EXPECT_EQ(nb_darts(), countVertices+NB_MAX); - EXPECT_EQ(nb_cells(), countVertices+NB_MAX); + + EXPECT_EQ(nb_darts(), countVertices); + EXPECT_EQ(nb_cells(), countVertices); EXPECT_EQ(nb_cells(), NB_MAX); EXPECT_TRUE(check_map_integrity()); } diff --git a/cgogn/core/tests/cmap/cmap2_test.cpp b/cgogn/core/tests/cmap/cmap2_test.cpp index 029ddbc1..7e13f16e 100644 --- a/cgogn/core/tests/cmap/cmap2_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_test.cpp @@ -28,7 +28,7 @@ namespace cgogn { -#define NB_MAX 1000 +#define NB_MAX 100 /*! * \brief The CMap2Test class implements tests on embedded CMap2 @@ -101,4 +101,6 @@ TEST_F(CMap2Test, addFace) EXPECT_TRUE(cmap_.check_map_integrity()); } +#undef NB_MAX + } // namespace cgogn diff --git a/cgogn/core/tests/cmap/cmap2_topo_test.cpp b/cgogn/core/tests/cmap/cmap2_topo_test.cpp index 71abd126..3171bab3 100644 --- a/cgogn/core/tests/cmap/cmap2_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_topo_test.cpp @@ -44,14 +44,16 @@ class CMap2TopoTest: public CMap2, public ::testing::Test public: using Vertex = CMap2TopoTest::Vertex; + using Edge = CMap2TopoTest::Edge; using Face = CMap2TopoTest::Face; + using Volume = CMap2TopoTest::Volume; protected: /*! - * \brief An array of randomly genrated darts on which the methods are tested. + * \brief A vector of darts on which the methods are tested. */ - std::array tdarts_; + std::vector darts_; /*! * \brief Generate a random set of faces. @@ -61,31 +63,60 @@ class CMap2TopoTest: public CMap2, public ::testing::Test std::srand(static_cast(std::time(0))); } - int randomDarts() { - int n = 1 + std::rand() % (NB_MAX-1); - for (int i = 0; i < n; ++i) - tdarts_[i] = add_dart(); - - return n; - } - - int randomFaces() { - int count = 0; - for (int i = 0; i < NB_MAX; ++i) { - int n = 1 + std::rand() % 100; + /*! + * \brief Generate a random set of faces and put them in darts_ + * \return The total number of added vertices. + * The face size ranges from 1 to 10. + * A random dart of each face is put in the darts_ array. + */ + unsigned int addFaces(unsigned int n) + { + unsigned int count = 0; + for (unsigned int i = 0; i < n; ++i) + { + unsigned int n = 1 + std::rand() % 10; Dart d = add_face_topo(n); count += n; while (std::rand()%10 != 1) d = phi1(d); - tdarts_[i] = d; + darts_.push_back(d); } return count; } + + /*! + * \brief Generate a closed surface from the set of faces in darts_ + */ + void makeSurface() + { + for (unsigned int i = 0; i < NB_MAX; ++i) { + Face f1 = darts_[std::rand() % NB_MAX]; + while (std::rand()%10 != 1) f1 = phi1(f1.dart); + Face f2 = darts_[std::rand() % NB_MAX]; + while (std::rand()%10 != 1) f2 = phi1(f2.dart); + + foreach_dart_of_orbit_until(f1, [&] (Dart d) { + if (phi2(d) == d) { + if (phi2(f2.dart) == f2.dart) { + // sewfaces + return (std::rand()%3 == 1); + } + else + return false; + } + else + return false; + }); + } + } }; -TEST_F(CMap2TopoTest, testCMap2Constructor) +/*! + * \brief An empty CMap2 contains no dart and no cells. + */ +TEST_F(CMap2TopoTest, Constructor) { EXPECT_EQ(nb_darts(), 0u); EXPECT_EQ(this->template nb_cells(), 0u); @@ -94,75 +125,76 @@ TEST_F(CMap2TopoTest, testCMap2Constructor) EXPECT_EQ(this->template nb_cells(), 0u); } -TEST_F(CMap2TopoTest, testAddDart) -{ - int n = randomDarts(); - - EXPECT_EQ(nb_darts(), n); - EXPECT_TRUE(check_map_integrity()); -} - -TEST_F(CMap2TopoTest, testDeleteDart) -{ - int n = randomDarts(); - - int count = n; - for (int i = 0; i < n; ++i) { - if (std::rand() % 3 == 1) { - remove_dart(tdarts_[i]); - --count; - } - } - - EXPECT_EQ(nb_darts(), count); - EXPECT_TRUE(check_map_integrity()); -} - -TEST_F(CMap2TopoTest, testPhi2SewUnSew) +/*! + * \brief Sewing and unsewing darts correctly changes the topological relations. + * The test perfoms NB_MAX sewing and unsewing on randomly chosen dart of darts_. + * The map integrity is preserved. + */ +TEST_F(CMap2TopoTest, phi2_sew_unsew) { - int n = randomDarts(); + unsigned int countVertices = addFaces(NB_MAX); + unsigned int countFaces = NB_MAX; + unsigned int countVolumes = NB_MAX; - for (int i = 0; i < 1000; ++i) { - Dart d0 = tdarts_[std::rand() % n]; + for (int i = 0; i < NB_MAX; ++i) { + Dart d0 = darts_[std::rand() % NB_MAX]; Dart d2 = phi2(d0); - if (d0 != d2) { - phi2_unsew(d0); - EXPECT_FALSE(phi2(d0) == d2); - EXPECT_TRUE(phi2(d0) == d0); - EXPECT_TRUE(phi2(d2) == d2); - } + phi2_unsew(d0); + EXPECT_TRUE(phi2(d0) == d0); + EXPECT_TRUE(phi2(d2) == d2); Dart e0 = d0; - while (e0 == d0) e0 = tdarts_[std::rand() % n]; - EXPECT_FALSE(d0 == e0); + while (e0 == d0) e0 = darts_[std::rand() % NB_MAX]; phi2_unsew(e0); - EXPECT_TRUE(phi2(e0) == e0); phi2_sew(d0,e0); EXPECT_TRUE(phi2(d0) == e0); EXPECT_TRUE(phi2(e0) == d0); } - EXPECT_EQ(nb_darts(), n); EXPECT_TRUE(check_map_integrity()); } -TEST_F(CMap2TopoTest, testAddFace) +/*! + * \brief Adding a 2-face of size n adds 2*n darts, n vertices and edges, 2 1-faces and 1 volume. + * The test adds some faces and check that the number of generated cells is correct + * and that the map integrity is preserved. + */ +TEST_F(CMap2TopoTest, add_face_topo) { - int n = randomFaces(); - - EXPECT_EQ(this->template nb_cells(), n); - EXPECT_EQ(this->template nb_cells(), n); - EXPECT_EQ(this->template nb_cells(), 2*NB_MAX); - EXPECT_EQ(this->template nb_cells(), NB_MAX); + add_face_topo(1); + EXPECT_EQ(nb_darts(), 2); + EXPECT_EQ(nb_cells(), 1); + EXPECT_EQ(nb_cells(), 1); + EXPECT_EQ(nb_cells(), 2); + EXPECT_EQ(nb_cells(), 1); + + add_face_topo(10); + EXPECT_EQ(nb_darts(), 22); + EXPECT_EQ(nb_cells(), 11); + EXPECT_EQ(nb_cells(), 11); + EXPECT_EQ(nb_cells(), 4); + EXPECT_EQ(nb_cells(), 2); + + unsigned int countVertices = 11 + addFaces(NB_MAX); + + EXPECT_EQ(nb_darts(), 2*countVertices); + EXPECT_EQ(nb_cells(), countVertices); + EXPECT_EQ(nb_cells(), countVertices); + EXPECT_EQ(nb_cells(), 2*(NB_MAX+2)); + EXPECT_EQ(nb_cells(), NB_MAX+2); EXPECT_TRUE(check_map_integrity()); } +/*! \brief Cutting an edge increases the size of both incident faces and add a vertex of degree 2. + * The test performs NB_MAX edge cutting on edges of randomly generated faces. + * The number of generated cells is correct and the map integrity is preserved. + */ TEST_F(CMap2TopoTest, testCutEdge) { - int n = randomFaces(); + int n = addFaces(NB_MAX); for (int i = 0; i < NB_MAX; ++i) { - Dart d = tdarts_[i]; + Dart d = darts_[i]; unsigned int k = degree(Face(d)); cut_edge_topo(d); EXPECT_EQ(degree(Face(d)), k+1); @@ -177,13 +209,13 @@ TEST_F(CMap2TopoTest, testCutEdge) TEST_F(CMap2TopoTest, testCutFace) { - int n = randomFaces(); + int n = addFaces(NB_MAX); int countEdges = n; int countFaces = 2*NB_MAX; for (int i = 0; i < NB_MAX; ++i) { - Dart d = tdarts_[i]; + Dart d = darts_[i]; Dart e = d; while (std::rand()%10 != 1) e = phi1(e); if (e == d) e = phi1(e); @@ -211,6 +243,6 @@ TEST_F(CMap2TopoTest, testFaceDegree) EXPECT_EQ(degree(f),10); } -// The traversal methods are tested through the nb_cells calls and wihtin other methods +#undef NB_MAX } // namespace cgogn From 18744b1567d60d82d9916a80922fdf17b2e99de2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Fri, 4 Mar 2016 19:29:13 +0100 Subject: [PATCH 253/402] added 2 meshes (vtk legacy unstructured grid of voxels) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- data/meshes/vox8_ascii.vtk | 231 ++++++++++++++++++++++++++++++++++++ data/meshes/vox8_binary.vtk | Bin 0 -> 2855 bytes 2 files changed, 231 insertions(+) create mode 100644 data/meshes/vox8_ascii.vtk create mode 100644 data/meshes/vox8_binary.vtk diff --git a/data/meshes/vox8_ascii.vtk b/data/meshes/vox8_ascii.vtk new file mode 100644 index 00000000..225b9b10 --- /dev/null +++ b/data/meshes/vox8_ascii.vtk @@ -0,0 +1,231 @@ +# vtk DataFile Version 3.0 +vtk output +ASCII +DATASET UNSTRUCTURED_GRID +POINTS 27 float +0 0 0 0 0 1 0 0 2 +0 1 0 0 1 1 0 1 2 +0 2 0 0 2 1 0 2 2 +1 0 0 1 0 1 1 0 2 +1 1 0 1 1 1 1 1 2 +1 2 0 1 2 1 1 2 2 +2 0 0 2 0 1 2 0 2 +2 1 0 2 1 1 2 1 2 +2 2 0 2 2 1 2 2 2 + +CELLS 8 72 +8 0 9 3 12 1 10 4 13 +8 1 10 4 13 2 11 5 14 +8 3 12 6 15 4 13 7 16 +8 4 13 7 16 5 14 8 17 +8 9 18 12 21 10 19 13 22 +8 10 19 13 22 11 20 14 23 +8 12 21 15 24 13 22 16 25 +8 13 22 16 25 14 23 17 26 + +CELL_TYPES 8 +11 +11 +11 +11 +11 +11 +11 +11 + +CELL_DATA 8 +SCALARS scalars float +LOOKUP_TABLE default +0 0.4 0.4 0 0.4 0 0 0.4 +FIELD FieldData 4 +cRamp1 1 8 float +0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 +cRamp2 1 8 float +8.1 7.2 6.3 5.4 4.5 3.6 2.7 1.8 +cVects 3 8 float +-1 -1 -1 -1 -1 1 -1 1 -1 +-1 1 1 1 -1 -1 1 -1 1 +1 1 -1 1 1 1 +cv2 3 8 float +0 -2 -1 0 -2 1 0 2 -1 +-1 2 1 2 -1 -2 1 -2 1 +2 2 -1 2 2 1 + +POINT_DATA 27 +SCALARS scalars float +LOOKUP_TABLE mytable +-0.4 -0.4 -0.4 -0.4 -1 -0.4 -0.4 -0.4 -0.4 +0.4 1 0.4 1 0.4 1 0.4 1 0.4 +0.4 0.4 0.4 0.4 1 0.4 0.4 0.4 0.4 + +FIELD FieldData 1 +mytest 1 27 float +-13.0 +-12.0 +-11.0 +-10.0 +-9.0 +-8.0 +-7.0 +-6.0 +-5.0 +-4.0 +-3.0 +-2.0 +-1.0 +0.0 +1.0 +2.0 +3.0 +4.0 +5.0 +6.0 +7.0 +8.0 +9.0 +10.0 +11.0 +12.0 +13.0 + +LOOKUP_TABLE mytable 64 + 6.7397900e-02 7.3764400e-02 9.5253700e-01 1.0000000e+00 + 7.9526300e-02 8.7038400e-02 9.3611300e-01 1.0000000e+00 + 9.3329400e-02 1.0214500e-01 9.2136300e-01 1.0000000e+00 + 1.0893600e-01 1.1922600e-01 9.0841600e-01 1.0000000e+00 + 1.2646400e-01 1.3840900e-01 8.9739100e-01 1.0000000e+00 + 1.4601700e-01 1.5981000e-01 8.8839200e-01 1.0000000e+00 + 1.6768300e-01 1.8352200e-01 8.8150500e-01 1.0000000e+00 + 1.9152000e-01 2.0961100e-01 8.7678900e-01 1.0000000e+00 + 2.1756300e-01 2.3811400e-01 8.7427900e-01 1.0000000e+00 + 2.4581000e-01 2.6903000e-01 8.7397400e-01 1.0000000e+00 + 2.7622200e-01 3.0231400e-01 8.7583200e-01 1.0000000e+00 + 3.0871700e-01 3.3787800e-01 8.7977400e-01 1.0000000e+00 + 3.4316700e-01 3.7558300e-01 8.8567200e-01 1.0000000e+00 + 3.7939900e-01 4.1523700e-01 8.9335000e-01 1.0000000e+00 + 4.1718600e-01 4.5659300e-01 9.0258400e-01 1.0000000e+00 + 4.5625400e-01 4.9935200e-01 9.1310000e-01 1.0000000e+00 + 4.9628100e-01 5.4316000e-01 9.2457400e-01 1.0000000e+00 + 5.3689900e-01 5.8761500e-01 9.3663900e-01 1.0000000e+00 + 5.7769800e-01 6.3226800e-01 9.4888600e-01 1.0000000e+00 + 6.1823500e-01 6.7663400e-01 9.6086900e-01 1.0000000e+00 + 6.5803600e-01 7.2019500e-01 9.7211800e-01 1.0000000e+00 + 6.9661000e-01 7.6241300e-01 9.8213900e-01 1.0000000e+00 + 7.3345600e-01 8.0273800e-01 9.9043200e-01 1.0000000e+00 + 7.6807100e-01 8.4062400e-01 9.9649400e-01 1.0000000e+00 + 7.9996900e-01 8.7553400e-01 9.9983900e-01 1.0000000e+00 + 8.2868300e-01 9.0696100e-01 1.0000000e+00 1.0000000e+00 + 8.5378300e-01 9.3443200e-01 9.9654700e-01 1.0000000e+00 + 8.7488400e-01 9.5752600e-01 9.8909500e-01 1.0000000e+00 + 8.9165500e-01 9.7588200e-01 9.7731400e-01 1.0000000e+00 + 9.0383100e-01 9.8920800e-01 9.6093700e-01 1.0000000e+00 + 9.1121700e-01 9.9729100e-01 9.3977000e-01 1.0000000e+00 + 9.1369200e-01 1.0000000e+00 9.1369200e-01 1.0000000e+00 + 9.1369200e-01 1.0000000e+00 9.1369200e-01 1.0000000e+00 + 9.3977000e-01 9.9729100e-01 9.1121700e-01 1.0000000e+00 + 9.6093700e-01 9.8920800e-01 9.0383100e-01 1.0000000e+00 + 9.7731400e-01 9.7588200e-01 8.9165500e-01 1.0000000e+00 + 9.8909500e-01 9.5752600e-01 8.7488400e-01 1.0000000e+00 + 9.9654700e-01 9.3443200e-01 8.5378300e-01 1.0000000e+00 + 1.0000000e+00 9.0696100e-01 8.2868300e-01 1.0000000e+00 + 9.9983900e-01 8.7553400e-01 7.9996900e-01 1.0000000e+00 + 9.9649400e-01 8.4062400e-01 7.6807100e-01 1.0000000e+00 + 9.9043200e-01 8.0273800e-01 7.3345600e-01 1.0000000e+00 + 9.8213900e-01 7.6241300e-01 6.9661000e-01 1.0000000e+00 + 9.7211800e-01 7.2019500e-01 6.5803600e-01 1.0000000e+00 + 9.6086900e-01 6.7663400e-01 6.1823500e-01 1.0000000e+00 + 9.4888600e-01 6.3226800e-01 5.7769800e-01 1.0000000e+00 + 9.3663900e-01 5.8761500e-01 5.3689900e-01 1.0000000e+00 + 9.2457400e-01 5.4316000e-01 4.9628100e-01 1.0000000e+00 + 9.1310000e-01 4.9935200e-01 4.5625400e-01 1.0000000e+00 + 9.0258400e-01 4.5659300e-01 4.1718600e-01 1.0000000e+00 + 8.9335000e-01 4.1523700e-01 3.7939900e-01 1.0000000e+00 + 8.8567200e-01 3.7558300e-01 3.4316700e-01 1.0000000e+00 + 8.7977400e-01 3.3787800e-01 3.0871700e-01 1.0000000e+00 + 8.7583200e-01 3.0231400e-01 2.7622200e-01 1.0000000e+00 + 8.7397400e-01 2.6903000e-01 2.4581000e-01 1.0000000e+00 + 8.7427900e-01 2.3811400e-01 2.1756300e-01 1.0000000e+00 + 8.7678900e-01 2.0961100e-01 1.9152000e-01 1.0000000e+00 + 8.8150500e-01 1.8352200e-01 1.6768300e-01 1.0000000e+00 + 8.8839200e-01 1.5981000e-01 1.4601700e-01 1.0000000e+00 + 8.9739100e-01 1.3840900e-01 1.2646400e-01 1.0000000e+00 + 9.0841600e-01 1.1922600e-01 1.0893600e-01 1.0000000e+00 + 9.2136300e-01 1.0214500e-01 9.3329400e-02 1.0000000e+00 + 9.3611300e-01 8.7038400e-02 7.9526300e-02 1.0000000e+00 + 9.5253700e-01 7.3764400e-02 6.7397900e-02 1.0000000e+00 + +FIELD FieldData 5 +xRamp 1 27 float +0 0 0 0 0 0 0 0 0 +0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 +0.8 0.8 0.8 0.8 0.8 0.8 0.8 0.8 0.8 + +yRamp 1 27 float +0.1 0.1 0.1 0.5 0.5 0.5 0.9 0.9 0.9 +0.1 0.1 0.1 0.5 0.5 0.5 0.9 0.9 0.9 +0.1 0.1 0.1 0.5 0.5 0.5 0.9 0.9 0.9 + +zRamp 1 27 float +0.2 0.6 1 0.2 0.6 1 0.2 0.6 1 +0.2 0.6 1 0.2 0.6 1 0.2 0.6 1 +0.2 0.6 1 0.2 0.6 1 0.2 0.6 1 + +outVect 3 27 float +-1 -1 -1 +-1 -1 0 +-1 -1 1 +-1 0 -1 +-1 0 0 +-1 0 1 +-1 1 -1 +-1 1 0 +-1 1 1 +0 -1 -1 +0 -1 0 +0 -1 1 +0 0 -1 +0 0 0 +0 0 1 +0 1 -1 +0 1 0 +0 1 1 +1 -1 -1 +1 -1 0 +1 -1 1 +1 0 -1 +1 0 0 +1 0 1 +1 1 -1 +1 1 0 +1 1 1 + +vect2 3 27 float +-1 -1 0 +-1 -1 1 +-1 -1 2 +-1 0 -1 +-1 0 0 +-1 0 1 +-1 1 -2 +-1 1 -1 +-1 1 0 +0 -1 0 +0 -1 1 +0 -1 2 +0 0 -1 +0 0 0 +0 0 1 +0 1 -2 +0 1 -1 +0 1 0 +1 -1 0 +1 -1 1 +1 -1 2 +1 0 -1 +1 0 0 +1 0 1 +1 1 -2 +1 1 -1 +1 1 0 + + diff --git a/data/meshes/vox8_binary.vtk b/data/meshes/vox8_binary.vtk new file mode 100644 index 0000000000000000000000000000000000000000..2ee403f4124394afc0ac65e1ec9f443da9232a84 GIT binary patch literal 2855 zcmcImO>7fa5MKJ7Ri zbaHesJ(`S0GCw4TB6?zEXgHlR0wE(`DB6y$y~e`jjil*OH3u#+ylBL0Y~Z2+S7Q#_ zHFYe}NT1YHFB*6lYNqFfBL>7wk4POMasYBLlL0Oo@yG)((}TaJ4@Tqhl<~b03Sd7! zV!%FTyvz8Mv5A4&dyLN*(D-xjaPAYv`;5;S&`AFW%)ekr|A)-KWI*H3sr? zfwg?iz*;&PSW7np22;+CVeOozww#LbNnrLb6(Gm<+4u62)5_ATGli_aJrBaFC4Ky_qv+s z;PvcuK$%Wst1!?8t1uvgnGECsaOB|;SJ)#KZ*mNX7991~>yl}HuR!SEe6T{Xcywwq z<%PKIu8iVg+V5)!esHqUWn$!PwZq#KMdw1&{olmK&dxd&>AJCSqOJwxj zqix$4X~)jn)W4@jp#hh|QI}!|TpAgx(ZR!a$ey@M6Hc9+nPr+e^^i`US)tSCpU~Nh zt90S=bGmfx1zlNqN!M>SsOl2kxKDKJQG?uP>$JGGM)mboT53F|W$*8CV~JMR>$JAE zNbApBYCO6{bpHmCTcyU$>-2Kr3ca{?iJo7+K&uze(v$P2Y30mGdU$GvmS-HQI}>zw z!lpZi4^nMxgxmu$a-(5#2SQZa(@(c|?x4l(+vr}OK}%b=(1YF{TIuehr=1=2%Kg}@ zA3NdXN)Dg)_D{!rLeu6=#x91z;74Fy<5N;&R2b(NWroSnTBn6w`(&9WpQ1A39HYXh zX_}=mcpS@M@VJ)ANbt$}1=mxZorP~T^@G2O<0`)m`U(H+cpL=Hhk@79^nBgJ9;6Qc zUo`r!{@L*?HJ_p~Uxfde>-?Vuo-KYx+Fu?Q(+_+M$>G9*!z9;=Hu9no4;?s6xEdn| z6E9pe62tpVH1N_dIcUKJr~`=MVZz}77;3^13x^k6Rk&!Rrcd*x;&FauSD{3wbPG4V zJiB%s90m<6T;AxbaO@ugbusBdEIQ#Ph-a!!a_}-1d<6+MaM7!EH3yCw0B&j1%^Z)<= literal 0 HcmV?d00001 From 8822af0f915938810b4d3b677e37cee289168261 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Fri, 4 Mar 2016 19:29:37 +0100 Subject: [PATCH 254/402] Added MeshImportGen class. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/CMakeLists.txt | 2 ++ cgogn/io/mesh_io_gen.cpp | 59 ++++++++++++++++++++++++++++++++++++++++ cgogn/io/mesh_io_gen.h | 58 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+) create mode 100644 cgogn/io/mesh_io_gen.cpp create mode 100644 cgogn/io/mesh_io_gen.h diff --git a/cgogn/io/CMakeLists.txt b/cgogn/io/CMakeLists.txt index d42b9cd1..c9de4a78 100644 --- a/cgogn/io/CMakeLists.txt +++ b/cgogn/io/CMakeLists.txt @@ -16,12 +16,14 @@ set(HEADER_FILES off_io.h obj_io.h ply_io.h + mesh_io_gen.h ) set(SOURCE_FILES surface_import.cpp volume_import.cpp import_ply_data.cpp + mesh_io_gen.cpp ) add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) diff --git a/cgogn/io/mesh_io_gen.cpp b/cgogn/io/mesh_io_gen.cpp new file mode 100644 index 00000000..fcc709bb --- /dev/null +++ b/cgogn/io/mesh_io_gen.cpp @@ -0,0 +1,59 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#define CGOGN_IO_DLL_EXPORT + +#include +#include + +#include + +namespace cgogn +{ + +namespace io +{ + +MeshImportGen::~MeshImportGen() {} + +bool MeshImportGen::import_file(const std::string& filename) +{ + this->clear(); + Scoped_C_Locale loc; + + { + // test if file exist + std::ifstream fp(filename.c_str(), std::ios::in); + if (!fp.good()) + { + std::cerr << "Unable to open file \"" << filename << "\"" << std::endl; + return false; + } + } + + return this->import_file_impl(filename); +} + +} // namespace io + +} // namespace cgogn diff --git a/cgogn/io/mesh_io_gen.h b/cgogn/io/mesh_io_gen.h new file mode 100644 index 00000000..a59d530c --- /dev/null +++ b/cgogn/io/mesh_io_gen.h @@ -0,0 +1,58 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef IO_MESH_IO_GEN_H_ +#define IO_MESH_IO_GEN_H_ + +#include +#include +#include + +namespace cgogn +{ + +namespace io +{ + +class CGOGN_IO_API MeshImportGen +{ +public: + MeshImportGen() = default; + MeshImportGen(const MeshImportGen&) = delete; + MeshImportGen(MeshImportGen&&) = delete; + MeshImportGen& operator=(const MeshImportGen&) = delete; + MeshImportGen& operator=(MeshImportGen&&) = delete; + + bool import_file(const std::string& filename); + virtual ~MeshImportGen(); + virtual void clear() = 0; + +protected: + virtual bool import_file_impl(const std::string& filename) = 0; +}; + +} // namespace io + +} // namespace cgogn + +#endif // IO_MESH_IO_GEN_H_ From 47fbb20653d836915da24ea004914f1f4bc87bd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Fri, 4 Mar 2016 19:30:49 +0100 Subject: [PATCH 255/402] work on volume import. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/data_io.h | 6 + cgogn/io/map_import.h | 55 ++++--- cgogn/io/surface_import.h | 30 +--- cgogn/io/volume_import.h | 318 +++++++++----------------------------- cgogn/io/vtk_io.h | 273 ++++++++++++++++++++++++++++++-- 5 files changed, 384 insertions(+), 298 deletions(-) diff --git a/cgogn/io/data_io.h b/cgogn/io/data_io.h index 1f4871f1..c2bbe40a 100644 --- a/cgogn/io/data_io.h +++ b/cgogn/io/data_io.h @@ -53,6 +53,7 @@ class DataIOGen virtual void skip_n(std::istream& fp, std::size_t n, bool binary) = 0; virtual void* get_data() = 0; virtual void reset() = 0; + virtual std::size_t size() const = 0; virtual void to_chunk_array(ChunkArrayGen* ca_gen) const = 0; virtual ChunkArrayGen* add_attribute(ChunkArrayContainer& cac, const std::string& att_name) const = 0; @@ -182,6 +183,11 @@ class DataIO : public DataIOGen return geometry::nb_components_traits::value; } + virtual std::size_t size() const override + { + return data_->size(); + } + private: std::unique_ptr> data_; }; diff --git a/cgogn/io/map_import.h b/cgogn/io/map_import.h index 82480f74..96782996 100644 --- a/cgogn/io/map_import.h +++ b/cgogn/io/map_import.h @@ -44,21 +44,10 @@ namespace io { template -inline std::unique_ptr> newSurfaceImport(const std::string& filename) -{ - const FileType file_type = get_file_type(filename); - switch (file_type) - { - case FileType::FileType_OFF : return make_unique>(); - case FileType::FileType_VTK_LEGACY: - case FileType::FileType_VTU: return make_unique>(); - case FileType::FileType_OBJ: return make_unique>(); - case FileType::FileType_PLY: return make_unique>(); - default: - std::cerr << "SurfaceImport does not handle files with extension \"" << get_extension(filename) << "\"." << std::endl; - return std::unique_ptr> (); - } -} +inline std::unique_ptr> newSurfaceImport(const std::string& filename); + +template +inline std::unique_ptr> newVolumeImport(const std::string& filename); template inline void import_surface(cgogn::CMap2& cmap2, const std::string& filename); @@ -80,11 +69,41 @@ inline void import_surface(cgogn::CMap2& cmap2, const std::string& f template inline void import_volume(cgogn::CMap3& cmap3, const std::string& filename) { - VolumeImport vi; - vi.template import_file(filename); - vi.create_map(cmap3); + auto si = newVolumeImport(filename); + si->import_file(filename); + si->create_map(cmap3); } +template +inline std::unique_ptr> newSurfaceImport(const std::string& filename) +{ + const FileType file_type = get_file_type(filename); + switch (file_type) + { + case FileType::FileType_OFF : return make_unique>(); + case FileType::FileType_VTK_LEGACY: + case FileType::FileType_VTU: return make_unique>(); + case FileType::FileType_OBJ: return make_unique>(); + case FileType::FileType_PLY: return make_unique>(); + default: + std::cerr << "SurfaceImport does not handle files with extension \"" << get_extension(filename) << "\"." << std::endl; + return std::unique_ptr> (); + } +} + +template +inline std::unique_ptr > newVolumeImport(const std::string& filename) +{ + const FileType file_type = get_file_type(filename); + switch (file_type) + { + case FileType::FileType_VTK_LEGACY: + case FileType::FileType_VTU: return make_unique>(); + default: + std::cerr << "SurfaceImport does not handle files with extension \"" << get_extension(filename) << "\"." << std::endl; + return std::unique_ptr> (); + } +} } // namespace io } // namespace cgogn diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index 1954fb86..8acaf1e5 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -36,6 +36,7 @@ #include #include +#include namespace cgogn { @@ -43,11 +44,13 @@ namespace cgogn namespace io { + template -class SurfaceImport +class SurfaceImport : public MeshImportGen { public: using Self = SurfaceImport; + using Inherit = MeshImportGen; using Map = CMap2; static const unsigned int CHUNK_SIZE = MAP_TRAITS::CHUNK_SIZE; @@ -80,7 +83,7 @@ class SurfaceImport ,faces_vertex_indices_() {} - virtual ~SurfaceImport() + virtual ~SurfaceImport() override {} SurfaceImport(const Self&) = delete; @@ -88,7 +91,7 @@ class SurfaceImport Self& operator=(const Self&) = delete; Self& operator=(Self&&) = delete; - void clear() + virtual void clear() override { nb_vertices_ = 0; nb_edges_ = 0; @@ -99,24 +102,6 @@ class SurfaceImport face_attributes_.remove_attributes(); } - inline bool import_file(const std::string& filename) - { - this->clear(); - Scoped_C_Locale loc; - - { - // test if file exist - std::ifstream fp(filename.c_str(), std::ios::in); - if (!fp.good()) - { - std::cerr << "Unable to open file \"" << filename << "\"" << std::endl; - return false; - } - } - - return this->import_file_impl(filename); - } - inline void create_map(Map& map) { using Vertex = typename Map::Vertex; @@ -221,9 +206,6 @@ class SurfaceImport map.remove_attribute(darts_per_vertex); this->clear(); } - -protected: - virtual bool import_file_impl(const std::string& filename) = 0; }; #if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_SURFACE_IMPORT_CPP_)) diff --git a/cgogn/io/volume_import.h b/cgogn/io/volume_import.h index 717ed07f..5c92d492 100644 --- a/cgogn/io/volume_import.h +++ b/cgogn/io/volume_import.h @@ -34,6 +34,7 @@ #include #include +#include #include @@ -43,17 +44,13 @@ namespace cgogn namespace io { -enum VolumeFileType -{ - VolumeFileType_UNKNOWN = 0, -}; - template -class VolumeImport +class VolumeImport : public MeshImportGen { public: using Self = VolumeImport; + using Inherit = MeshImportGen; using Map = CMap3; using Vertex = typename Map::Vertex; @@ -65,77 +62,41 @@ class VolumeImport template using AttributeHandler = AttributeHandler; - template - - using VertexAttributeHandler = typename Map::template VertexAttributeHandler; using MapBuilder = cgogn::CMap3Builder_T; + + virtual ~VolumeImport() override {} + +protected: unsigned int nb_vertices_; - unsigned int nb_edges_; - unsigned int nb_faces_; unsigned int nb_volumes_; std::vector volumes_nb_vertices_; std::vector volumes_vertex_indices_; ChunkArrayContainer vertex_attributes_; + ChunkArrayContainer volume_attributes_; +public: VolumeImport() : nb_vertices_(0u) - ,nb_edges_(0u) - ,nb_faces_(0u) ,volumes_nb_vertices_() ,volumes_vertex_indices_() {} - ~VolumeImport() - {} - VolumeImport(const Self&) = delete; VolumeImport(Self&&) = delete; Self& operator=(const Self&) = delete; Self& operator=(Self&&) = delete; - void clear() + virtual void clear() override { nb_vertices_ = 0; - nb_edges_ = 0; - nb_faces_ = 0; volumes_nb_vertices_.clear(); volumes_vertex_indices_.clear(); vertex_attributes_.remove_attributes(); + volume_attributes_.remove_attributes(); } - template - bool import_file(const std::string& filename) - { - Scoped_C_Locale loc; - - const std::string& extension = to_lower(get_extension(filename)); - if (extension.empty()) - return false; - - std::ifstream fp(filename.c_str(), std::ios::in); - if (!fp.good()) - { - std::cerr << "Unable to open file " << filename << std::endl; - return false; - } - - this->clear(); - bool res = false; - - if (extension == "vtu" || extension == "vtk") - { - res = this->import_VTU(filename); - } - if (!res) - { - this->clear(); - std::cerr << "Unable to read mesh from file " << filename << std::endl; - } - - return res; - } bool create_map(Map& map) { @@ -149,7 +110,7 @@ class VolumeImport mbuild.template create_embedding(); mbuild.template swap_chunk_array_container(this->vertex_attributes_); - VertexAttributeHandler> darts_per_vertex = map.template add_attribute, Vertex::ORBIT>("darts_per_vertex"); + typename Map::template VertexAttributeHandler> darts_per_vertex = map.template add_attribute, Vertex::ORBIT>("darts_per_vertex"); unsigned int index = 0u; // buffer for tempo faces (used to remove degenerated edges) @@ -345,210 +306,73 @@ class VolumeImport return true; } -protected: - - template - bool import_VTU(const std::string& filename) + template + void add_hexa(ChunkArrayconst& pos,unsigned int& p0, unsigned int& p1, unsigned int& p2, unsigned int& p3, unsigned int& p4, unsigned int& p5, unsigned int& p6, unsigned int& p7) { - using tinyxml2::XMLDocument; - using tinyxml2::XMLError; - using tinyxml2::XML_NO_ERROR; - using tinyxml2::XMLElement; - - ChunkArray* position = - vertex_attributes_.template add_attribute("position"); - cgogn_assert(position != nullptr); - - XMLDocument doc; - XMLError eResult = doc.LoadFile(filename.c_str()); - if (eResult != XML_NO_ERROR) - { - std::cerr << "unable loading file " << filename << std::endl; - return false; - } - - XMLElement* vtu_node = doc.RootElement(); - cgogn_assert(vtu_node != nullptr); - XMLElement* grid_node = vtu_node->FirstChildElement("UnstructuredGrid"); - cgogn_assert(grid_node != nullptr); - XMLElement* piece_node = grid_node->FirstChildElement("Piece"); - cgogn_assert(piece_node != nullptr); - - eResult = piece_node->QueryUnsignedAttribute("NumberOfPoints",&nb_vertices_); - if (eResult != XML_NO_ERROR) - { - std::cerr << "unreadable VTU file: " << filename << std::endl; - return false; - } - eResult = piece_node->QueryUnsignedAttribute("NumberOfCells",&nb_volumes_); - if (eResult != XML_NO_ERROR) - { - std::cerr << "unreadable VTU file: " << filename << std::endl; - return false; - } - - std::cout << "reading file " << filename << std::endl; - std::cout << "Number of vertices : " << this->nb_vertices_ << std::endl; - std::cout << "Number of volumes : " << this->nb_volumes_ << std::endl; - - XMLElement* points_node = piece_node->FirstChildElement("Points"); - cgogn_assert(points_node != nullptr); - XMLElement* array_node = points_node->FirstChildElement("DataArray"); - cgogn_assert(array_node != nullptr); - - std::vector verticesID; - verticesID.reserve(nb_vertices_); - std::stringstream ss(array_node->GetText()); - for (unsigned int i=0u; i< nb_vertices_; ++i) - { - VEC3 P; - ss >> P[0]; - ss >> P[1]; - ss >> P[2]; - unsigned int id = vertex_attributes_.template insert_lines<1>(); - position->operator [](id) = P; - verticesID.push_back(id); - } - - XMLElement* cell_node = piece_node->FirstChildElement("Cells"); - cgogn_assert(cell_node != nullptr); - array_node = cell_node->FirstChildElement("DataArray"); - cgogn_assert(array_node != nullptr); - - std::vector typeVols; - typeVols.reserve(nb_volumes_); - std::vector offsets; - offsets.reserve(nb_volumes_); - std::vector indices; - indices.reserve(nb_volumes_*4u); - - while (array_node) + this->reoriente_hexa(pos, p0, p1, p2, p3, p4, p5, p6, p7); + this->volumes_nb_vertices_.push_back(8u); + this->volumes_vertex_indices_.push_back(p0); + this->volumes_vertex_indices_.push_back(p1); + this->volumes_vertex_indices_.push_back(p2); + this->volumes_vertex_indices_.push_back(p3); + this->volumes_vertex_indices_.push_back(p4); + this->volumes_vertex_indices_.push_back(p5); + this->volumes_vertex_indices_.push_back(p6); + this->volumes_vertex_indices_.push_back(p7); + } + template + inline void reoriente_hexa(ChunkArrayconst& pos, unsigned int& p0, unsigned int& p1, unsigned int& p2, unsigned int& p3, unsigned int& p4, unsigned int& p5, unsigned int& p6, unsigned int& p7) + { + if (geometry::test_orientation_3D(pos[p4], pos[p0],pos[p1],pos[p2]) == geometry::Orientation3D::OVER) { - const std::string& propName = to_lower(std::string(array_node->Attribute("Name"))); - if (propName.empty()) - { - std::cerr << "Error reading VTU unreadable file: "<< filename << std::endl; - return false; - } - - if (propName == "connectivity") - { - std::stringstream ss(array_node->GetText()); - while (!ss.eof()) - { - unsigned int ind; - ss >> ind; - indices.push_back(ind); - } - } - if (propName == "offsets") - { - std::stringstream ss(array_node->GetText()); - for (unsigned int i=0u; i< nb_volumes_; ++i) - { - unsigned int o; - ss >> o; - offsets.push_back(o); - } - } - if (propName == "types") - { - bool unsupported = false; - std::stringstream ss(array_node->GetText()); - for (unsigned int i=0u; i< nb_volumes_; ++i) - { - unsigned int t; - ss >> t; - if (!(t == 10u || t == 12u)) - { - std::cerr << "error while parsing vtk file : volumes of type " << t << " are not supported" << std::endl; - unsupported = true; - } - typeVols.push_back(t); - } - if (unsupported) - { - std::cerr << "warning, some unsupported volume cell types"<< std::endl; - } - - } - array_node = array_node->NextSiblingElement("DataArray"); + std::swap(p0, p3); + std::swap(p1, p2); + std::swap(p4, p7); + std::swap(p5, p6); } + } - unsigned int currentOffset = 0; - for (unsigned int i=0u; i< nb_volumes_; ++i) - { - if (typeVols[i]==12u) - { - volumes_nb_vertices_.push_back(8u); - - std::array pt; - VEC3 const& P = position->operator [](verticesID[indices[currentOffset+4]]); - VEC3 const& A = position->operator [](verticesID[indices[currentOffset ]]); - VEC3 const& B = position->operator [](verticesID[indices[currentOffset+1]]); - VEC3 const& C = position->operator [](verticesID[indices[currentOffset+2]]); - - if (geometry::test_orientation_3D(P,A,B,C) == geometry::Orientation3D::OVER) - { - pt[0] = indices[currentOffset+3]; - pt[1] = indices[currentOffset+2]; - pt[2] = indices[currentOffset+1]; - pt[3] = indices[currentOffset+0]; - pt[4] = indices[currentOffset+7]; - pt[5] = indices[currentOffset+6]; - pt[6] = indices[currentOffset+5]; - pt[7] = indices[currentOffset+4]; - } - else - { - pt[0] = indices[currentOffset+0]; - pt[1] = indices[currentOffset+1]; - pt[2] = indices[currentOffset+2]; - pt[3] = indices[currentOffset+3]; - pt[4] = indices[currentOffset+4]; - pt[5] = indices[currentOffset+5]; - pt[6] = indices[currentOffset+6]; - pt[7] = indices[currentOffset+7]; - } + template + void add_tetra(ChunkArrayconst& pos,unsigned int& p0, unsigned int& p1, unsigned int& p2, unsigned int& p3) + { + this->reoriente_tetra(pos,p0,p1,p2,p3); + this->volumes_nb_vertices_.push_back(4u); + this->volumes_vertex_indices_.push_back(p0); + this->volumes_vertex_indices_.push_back(p1); + this->volumes_vertex_indices_.push_back(p2); + this->volumes_vertex_indices_.push_back(p3); + } - volumes_vertex_indices_.push_back(verticesID[pt[0]]); - volumes_vertex_indices_.push_back(verticesID[pt[1]]); - volumes_vertex_indices_.push_back(verticesID[pt[2]]); - volumes_vertex_indices_.push_back(verticesID[pt[3]]); - volumes_vertex_indices_.push_back(verticesID[pt[4]]); - volumes_vertex_indices_.push_back(verticesID[pt[5]]); - volumes_vertex_indices_.push_back(verticesID[pt[6]]); - volumes_vertex_indices_.push_back(verticesID[pt[7]]); + template + void add_pyramid(ChunkArrayconst& pos,unsigned int& p0, unsigned int& p1, unsigned int& p2, unsigned int& p3, unsigned int& p4) + { + this->volumes_nb_vertices_.push_back(5u); + this->volumes_vertex_indices_.push_back(p0); + this->volumes_vertex_indices_.push_back(p1); + this->volumes_vertex_indices_.push_back(p2); + this->volumes_vertex_indices_.push_back(p3); + this->volumes_vertex_indices_.push_back(p4); + } - } - else if (typeVols[i]==10u) - { - volumes_nb_vertices_.push_back(4u); - - std::array pt; - pt[0] = indices[currentOffset]; - pt[1] = indices[currentOffset+1]; - pt[2] = indices[currentOffset+2]; - pt[3] = indices[currentOffset+3]; - - VEC3 const& P = position->operator [](verticesID[pt[0]]); - VEC3 const& A = position->operator [](verticesID[pt[1]]); - VEC3 const& B = position->operator [](verticesID[pt[2]]); - VEC3 const& C = position->operator [](verticesID[pt[3]]); - - if (geometry::test_orientation_3D(P,A,B,C) == geometry::Orientation3D::OVER) - std::swap(pt[1], pt[2]); - - volumes_vertex_indices_.push_back(verticesID[pt[0]]); - volumes_vertex_indices_.push_back(verticesID[pt[1]]); - volumes_vertex_indices_.push_back(verticesID[pt[2]]); - volumes_vertex_indices_.push_back(verticesID[pt[3]]); - } - currentOffset = offsets[i]; - } + template + void add_triangular_prism(ChunkArrayconst& pos,unsigned int& p0, unsigned int& p1, unsigned int& p2, unsigned int& p3, unsigned int& p4, unsigned int& p5) + { + this->volumes_nb_vertices_.push_back(6u); + this->volumes_vertex_indices_.push_back(p0); + this->volumes_vertex_indices_.push_back(p1); + this->volumes_vertex_indices_.push_back(p2); + this->volumes_vertex_indices_.push_back(p3); + this->volumes_vertex_indices_.push_back(p4); + this->volumes_vertex_indices_.push_back(p5); + } - return true; + template + inline void reoriente_tetra(ChunkArrayconst& pos, unsigned int& p0, unsigned int& p1, unsigned int& p2, unsigned int& p3) + { + if (geometry::test_orientation_3D(pos[p0], pos[p1],pos[p2],pos[p3]) == geometry::Orientation3D::OVER) + std::swap(p1, p2); } + }; #if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_VOLUME_IMPORT_CPP_)) diff --git a/cgogn/io/vtk_io.h b/cgogn/io/vtk_io.h index 8fc0876d..41df7d0c 100644 --- a/cgogn/io/vtk_io.h +++ b/cgogn/io/vtk_io.h @@ -29,7 +29,7 @@ #include #include - +#include namespace cgogn { @@ -78,13 +78,14 @@ public : using DataIOGen = cgogn::io::DataIOGen; template using DataIO = cgogn::io::DataIO; + using Scalar = typename VEC3::Scalar; virtual ~VtkIO() {} protected : - DataIO positions_; - DataIO cells_; - DataIO cell_types_; + std::unique_ptr positions_; + DataIO cells_; + DataIO cell_types_; protected : virtual void add_vertex_attribute(const DataIOGen& attribute_data, const std::string& attribute_name) = 0; @@ -95,7 +96,6 @@ protected : VTK_MESH_TYPE vtk_type(VTK_MESH_TYPE::UNKNOWN); std::cout << "Opening a legacy vtk file" << std::endl; - using Scalar = typename VEC3::Scalar; std::string line; std::string word; @@ -141,8 +141,9 @@ protected : std::string type_str; sstream >> nb_vertices >> type_str; type_str = to_lower(type_str); - positions_.read_n(fp, nb_vertices, !ascii_file, false); - this->add_vertex_attribute(positions_,"position"); + positions_ = DataIOGen::template newDataIO(type_str, 3); + positions_->read_n(fp, nb_vertices, !ascii_file, false); + this->add_vertex_attribute(*positions_,"position"); } else { if (word == "CELLS" || word == "POLYGONS" || word == "TRIANGLE_STRIPS") { @@ -337,8 +338,8 @@ class VtkSurfaceImport : public VtkIO: if (!Inherit_Vtk::parse_vtk_legacy_file(fp)) return false; - this->nb_vertices_ = this->positions_.get_vec()->size(); - this->nb_faces_ = this->cell_types_.get_vec()->size(); + this->nb_vertices_ = this->positions_->size(); + this->nb_faces_ = this->cell_types_.size(); auto cells_it = static_cast*>(this->cells_.get_data())->begin(); const std::vector* cell_types_vec = static_cast*>(this->cell_types_.get_data()); @@ -396,6 +397,260 @@ class VtkSurfaceImport : public VtkIO: } }; + +template +class VtkVolumeImport : public VtkIO::PRIM_SIZE, VEC3>, public VolumeImport +{ +public: + using Self = VtkVolumeImport; + using Inherit_Vtk = VtkIO::PRIM_SIZE, VEC3>; + using Inherit_Import = VolumeImport; + using DataIOGen = typename Inherit_Vtk::DataIOGen; + template + using DataIO = typename Inherit_Vtk::template DataIO; + using VTK_CELL_TYPES = typename Inherit_Vtk::VTK_CELL_TYPES; + template + using ChunkArray = typename Inherit_Import::template ChunkArray; + + virtual ~VtkVolumeImport() override {} + +protected: + inline bool read_vtk_legacy_file(std::ifstream& fp) + { + if (!Inherit_Vtk::parse_vtk_legacy_file(fp)) + return false; + + this->nb_vertices_ = this->positions_->size(); + this->nb_volumes_ = this->cell_types_.size(); + + const std::vector* cell_types_vec = this->cell_types_.get_vec(); + const std::vector* cells_vec =this->cells_.get_vec(); + + std::vector cells_buffer; + cells_buffer.reserve(cells_vec->size()); + + // in the legacy file , the first number of each line is the number of vertices. We need to remove it. + auto cells_it = cells_vec->begin(); + for (std::vector::const_iterator type_it = cell_types_vec->begin(), end = cell_types_vec->end(); type_it != end; ++type_it) + { + ++cells_it; + unsigned int vol_nb_verts = 0u; + if (*type_it == VTK_CELL_TYPES::VTK_TETRA) + vol_nb_verts = 4u; + else { + if (*type_it == VTK_CELL_TYPES::VTK_HEXAHEDRON || *type_it == VTK_CELL_TYPES::VTK_VOXEL) + vol_nb_verts = 8u; + else { + if (*type_it == VTK_CELL_TYPES::VTK_WEDGE) + vol_nb_verts = 6u; + else { + if (*type_it == VTK_CELL_TYPES::VTK_PYRAMID) + vol_nb_verts = 5u; + } + } + } + for (unsigned int i = 0u ; i < vol_nb_verts;++i) + { + cells_buffer.push_back(*cells_it++); + } + } + + + add_vtk_volumes(cells_buffer,*cell_types_vec, *(this->vertex_attributes_.template get_attribute("position"))); + + return true; + } + + virtual void add_vertex_attribute(const DataIOGen& attribute_data, const std::string& attribute_name) override + { + attribute_data.to_chunk_array(attribute_data.add_attribute(this->vertex_attributes_, attribute_name)); + } + virtual void add_cell_attribute(const DataIOGen& attribute_data, const std::string& attribute_name) override + { + attribute_data.to_chunk_array(attribute_data.add_attribute(this->volume_attributes_, attribute_name)); + } + + virtual bool import_file_impl(const std::string& filename) + { + const FileType file_type = get_file_type(filename); + switch (file_type) { + case FileType::FileType_VTK_LEGACY: + { + std::ifstream fp(filename.c_str(), std::ios::in | std::ios::binary); + return this->read_vtk_legacy_file(fp); + } + case FileType::FileType_VTU: return this->import_VTU(filename); + default: + std::cerr << "VtkVolumeImport does not handle the files of type \"" << get_extension(filename) << "\"." << std::endl; + return false; + } + } + + bool import_VTU(const std::string& filename) + { + using tinyxml2::XMLDocument; + using tinyxml2::XMLError; + using tinyxml2::XML_NO_ERROR; + using tinyxml2::XMLElement; + + typename Inherit_Import::template ChunkArray* position = + this->vertex_attributes_.template add_attribute("position"); + cgogn_assert(position != nullptr); + + XMLDocument doc; + XMLError eResult = doc.LoadFile(filename.c_str()); + if (eResult != XML_NO_ERROR) + { + std::cerr << "unable loading file " << filename << std::endl; + return false; + } + + XMLElement* vtu_node = doc.RootElement(); + cgogn_assert(vtu_node != nullptr); + XMLElement* grid_node = vtu_node->FirstChildElement("UnstructuredGrid"); + cgogn_assert(grid_node != nullptr); + XMLElement* piece_node = grid_node->FirstChildElement("Piece"); + cgogn_assert(piece_node != nullptr); + + eResult = piece_node->QueryUnsignedAttribute("NumberOfPoints",&this->nb_vertices_); + if (eResult != XML_NO_ERROR) + { + std::cerr << "unreadable VTU file: " << filename << std::endl; + return false; + } + eResult = piece_node->QueryUnsignedAttribute("NumberOfCells",&this->nb_volumes_); + if (eResult != XML_NO_ERROR) + { + std::cerr << "unreadable VTU file: " << filename << std::endl; + return false; + } + + std::cout << "reading file " << filename << std::endl; + std::cout << "Number of vertices : " << this->nb_vertices_ << std::endl; + std::cout << "Number of volumes : " << this->nb_volumes_ << std::endl; + + XMLElement* points_node = piece_node->FirstChildElement("Points"); + cgogn_assert(points_node != nullptr); + XMLElement* array_node = points_node->FirstChildElement("DataArray"); + cgogn_assert(array_node != nullptr); + + std::stringstream ss(array_node->GetText()); + for (unsigned int i=0u; i< this->nb_vertices_; ++i) + { + VEC3 P; + ss >> P[0]; + ss >> P[1]; + ss >> P[2]; + unsigned int id = this->vertex_attributes_.template insert_lines<1>(); + position->operator [](id) = P; + cgogn_assert(id == i); + } + + XMLElement* cell_node = piece_node->FirstChildElement("Cells"); + cgogn_assert(cell_node != nullptr); + array_node = cell_node->FirstChildElement("DataArray"); + cgogn_assert(array_node != nullptr); + + std::vector typeVols; + typeVols.reserve(this->nb_volumes_); + std::vector offsets; + offsets.reserve(this->nb_volumes_); + std::vector indices; + indices.reserve(this->nb_volumes_*4u); + + while (array_node) + { + const std::string& propName = to_lower(std::string(array_node->Attribute("Name"))); + if (propName.empty()) + { + std::cerr << "Error reading VTU unreadable file: "<< filename << std::endl; + return false; + } + + if (propName == "connectivity") + { + std::stringstream ss(array_node->GetText()); + while (!ss.eof()) + { + unsigned int ind; + ss >> ind; + indices.push_back(ind); + } + } + if (propName == "offsets") + { + std::stringstream ss(array_node->GetText()); + for (unsigned int i=0u; i< this->nb_volumes_; ++i) + { + unsigned int o; + ss >> o; + offsets.push_back(o); + } + } + if (propName == "types") + { + bool unsupported = false; + std::stringstream ss(array_node->GetText()); + for (unsigned int i=0u; i< this->nb_volumes_; ++i) + { + unsigned int t; + ss >> t; + if (!(t == 10u || t == 12u)) + { + std::cerr << "error while parsing vtk file : volumes of type " << t << " are not supported" << std::endl; + unsupported = true; + } + typeVols.push_back(t); + } + if (unsupported) + { + std::cerr << "warning, some unsupported volume cell types"<< std::endl; + } + + } + array_node = array_node->NextSiblingElement("DataArray"); + } + + add_vtk_volumes(indices, typeVols, *position); + return true; + } + + inline void add_vtk_volumes(std::vector& ids, const std::vector& type_vol, ChunkArray const& pos) + { + unsigned int curr_offset = 0; + for (unsigned int i=0u; i< this->nb_volumes_; ++i) + { + if (type_vol[i]== VTK_CELL_TYPES::VTK_HEXAHEDRON || type_vol[i]== VTK_CELL_TYPES::VTK_VOXEL) + { + if (type_vol[i]== VTK_CELL_TYPES::VTK_VOXEL) + { + std::swap(ids[curr_offset+2],ids[curr_offset+3]); + std::swap(ids[curr_offset+6],ids[curr_offset+7]); + } + this->add_hexa(pos, ids[curr_offset+0],ids[curr_offset+1],ids[curr_offset+2],ids[curr_offset+3],ids[curr_offset+4],ids[curr_offset+5],ids[curr_offset+6],ids[curr_offset+7]); + curr_offset+=8u; + }else { + if (type_vol[i]== VTK_CELL_TYPES::VTK_TETRA) + { + this->add_tetra(pos, ids[curr_offset+0],ids[curr_offset+1],ids[curr_offset+2],ids[curr_offset+3]); + curr_offset+=4u; + } else { + if (type_vol[i]== VTK_CELL_TYPES::VTK_PYRAMID) + { + this->add_pyramid(pos, ids[curr_offset+0],ids[curr_offset+1],ids[curr_offset+2],ids[curr_offset+3],ids[curr_offset+4]); + curr_offset+=5u; + } else { + if (type_vol[i]== VTK_CELL_TYPES::VTK_WEDGE) + { + this->add_triangular_prism(pos, ids[curr_offset+0],ids[curr_offset+1],ids[curr_offset+2],ids[curr_offset+3],ids[curr_offset+4],ids[curr_offset+5]); + curr_offset+=6u; + } + } + } + } + } + } +}; } // namespace io } // namespace cgogn From e03942d4624828aea8540cf189049e8efa8ea749 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Sat, 5 Mar 2016 18:08:43 +0100 Subject: [PATCH 256/402] DataIOGen, DataIO -> DataInputGen, DataInput Added the possibilty of forcing a conversion of the Data after having read it from the file. This is necessary when we want to have a position attribute of type Vec3d and the data in the files are of type Vec3f. Signed-off-by: Etienne Schmitt --- cgogn/io/CMakeLists.txt | 3 +- cgogn/io/data_io.h | 256 +++++++++++++++++++++++++--------------- cgogn/io/io_utils.h | 70 +++++++++++ cgogn/io/vtk_io.h | 40 +++---- 4 files changed, 255 insertions(+), 114 deletions(-) diff --git a/cgogn/io/CMakeLists.txt b/cgogn/io/CMakeLists.txt index c9de4a78..8d221a73 100644 --- a/cgogn/io/CMakeLists.txt +++ b/cgogn/io/CMakeLists.txt @@ -35,10 +35,11 @@ target_include_directories(${PROJECT_NAME} PUBLIC $ $ $ + $ $ ) -target_link_libraries(${PROJECT_NAME} tinyxml2 cgogn_core cgogn_geometry ply) +target_link_libraries(${PROJECT_NAME} tinyxml2 cgogn_core cgogn_geometry ply base64) install(DIRECTORY . DESTINATION include/cgogn/io diff --git a/cgogn/io/data_io.h b/cgogn/io/data_io.h index c2bbe40a..fb1ff316 100644 --- a/cgogn/io/data_io.h +++ b/cgogn/io/data_io.h @@ -43,7 +43,7 @@ namespace io * @brief The BaseDataIO class : used to read numerical values (scalar & vectors) in mesh files */ template -class DataIOGen +class DataInputGen { public: using ChunkArrayGen = cgogn::ChunkArrayGen; @@ -52,6 +52,7 @@ class DataIOGen virtual void read_n(std::istream& fp, std::size_t n, bool binary, bool big_endian) = 0; virtual void skip_n(std::istream& fp, std::size_t n, bool binary) = 0; virtual void* get_data() = 0; + virtual const void* get_data() const = 0; virtual void reset() = 0; virtual std::size_t size() const = 0; @@ -59,62 +60,93 @@ class DataIOGen virtual ChunkArrayGen* add_attribute(ChunkArrayContainer& cac, const std::string& att_name) const = 0; virtual unsigned int nb_components() const = 0; - virtual ~DataIOGen() {} + virtual ~DataInputGen() {} template - inline static std::unique_ptr newDataIO(const std::string type_name); + inline static std::unique_ptr newDataIO(const std::string type_name); template - inline static std::unique_ptr newDataIO(const std::string type_name, unsigned int nb_components); + inline static std::unique_ptr newDataIO(const std::string type_name, unsigned int nb_components); + + // This versions converts the data to the type T (if T is different from the type that has been read in the file) + template + inline static std::unique_ptr newDataIO(const std::string type_name); + // This versions converts the data to the type T (if T is different from the type that has been read in the file) + template + inline static std::unique_ptr newDataIO(const std::string type_name, unsigned int nb_components); }; -template -class DataIO : public DataIOGen +template +class DataInput : public DataInputGen { public: - using Inherit = DataIOGen; - using Self = DataIO; + using Inherit = DataInputGen; + using Self = DataInput ; using ChunkArrayGen = typename Inherit::ChunkArrayGen; using ChunkArray = cgogn::ChunkArray; using ChunkArrayContainer = typename Inherit::ChunkArrayContainer; - DataIO() - { - data_ = make_unique>(); - } + DataInput() + {} - DataIO(const Self&) = delete; - DataIO& operator =(const Self&) = delete; - DataIO(Self&&) = default; + DataInput(const Self&) = delete; + DataInput& operator =(const Self&) = delete; + DataInput(Self&&) = default; virtual void read_n(std::istream& fp, std::size_t n, bool binary, bool big_endian) override { - const std::size_t old_size = data_->size(); - data_->resize(old_size + n); + const std::size_t old_size = data_.size(); + data_.resize(old_size + n); if (binary) { - fp.read(reinterpret_cast(std::addressof(data_->operator[](old_size))), n * sizeof(T)); - if (big_endian != ::cgogn::internal::cgogn_is_little_endian) - { - for (auto it = data_->begin() + old_size, end = data_->end() ; it != end; ++it) - *it = cgogn::io::internal::swap_endianness(*it); + if (std::is_same::value) + { // if BUFFER_T = T we can directly store the data + fp.read(reinterpret_cast(&data_[old_size]), n * sizeof(T)); + if (big_endian != ::cgogn::internal::cgogn_is_little_endian) + { + for (auto it = data_.begin() + old_size, end = data_.end() ; it != end; ++it) + *it = cgogn::io::internal::swap_endianness(*it); + } + if (fp.eof() || fp.bad()) + this->reset(); + } else { // 2nd case : BUFFER_T and T are different. + std::vector buffer(old_size+n); + fp.read(reinterpret_cast(std::addressof(buffer[old_size])), n * sizeof(BUFFER_T)); + if (big_endian != ::cgogn::internal::cgogn_is_little_endian) + { + for (auto it = buffer.begin() + old_size, end = buffer.end() ; it != end; ++it) + *it = cgogn::io::internal::swap_endianness(*it); + } + if (fp.eof() || fp.bad()) + this->reset(); + // copy + auto dest_it = data_.begin(); + for (auto & x : buffer) + { + *dest_it++ = internal::convert(x); + } } - if (fp.eof() || fp.bad()) - this->reset(); } else { std::string line; line.reserve(256); std::size_t i = 0ul; + BUFFER_T buff; for (; i < n && (!fp.eof()) && (!fp.bad()); ) { bool no_error = true; std::getline(fp,line); std::istringstream line_stream(line); - while (i < n && (no_error = static_cast(internal::parse(line_stream, data_->operator[](i+old_size))))) + BUFFER_T buff; + while (i < n && (no_error = static_cast(internal::parse(line_stream, buff)))) + { + data_[i+old_size] = internal::convert(buff); ++i; + } + if (!no_error && (!line_stream.eof())) break; } + if (i < n) { std::cerr << "read_n : An eccor occured while reading the line \n\"" << line << "\"" << std::endl; @@ -127,7 +159,7 @@ class DataIO : public DataIOGen { if (binary) { - fp.ignore(n * sizeof(T)); + fp.ignore(n * sizeof(BUFFER_T)); } else { std::string line; line.reserve(256); @@ -150,12 +182,12 @@ class DataIO : public DataIOGen } virtual void reset() override { - data_ = make_unique>(); + data_.clear(); } virtual ChunkArray* add_attribute(ChunkArrayContainer& cac, const std::string& att_name) const override { - for (unsigned i = cac.capacity(), end = data_->size(); i < end; i+=PRIM_SIZE) + for (unsigned i = cac.capacity(), end = data_.size(); i < end; i+=PRIM_SIZE) cac.template insert_lines(); return cac.template add_attribute(att_name); } @@ -164,18 +196,23 @@ class DataIO : public DataIOGen { ChunkArray* ca = dynamic_cast(ca_gen); unsigned int i = 0u; - for (auto& x : *data_) + for (auto& x : data_) ca->operator[](i++) = x; } virtual void* get_data() override { - return data_.get(); + return &data_; + } + + virtual const void* get_data() const override + { + return &data_; } inline std::vector const * get_vec() const { - return data_.get(); + return &data_; } virtual unsigned int nb_components() const override @@ -185,86 +222,119 @@ class DataIO : public DataIOGen virtual std::size_t size() const override { - return data_->size(); + return data_.size(); } private: - std::unique_ptr> data_; + std::vector data_; }; template template -std::unique_ptr> DataIOGen::newDataIO(const std::string type_name) +std::unique_ptr> DataInputGen::newDataIO(const std::string type_name) +{ + const DataType type = get_data_type(type_name); + switch (type) { + case DataType::FLOAT: return make_unique>(); + case DataType::DOUBLE: return make_unique>(); + case DataType::CHAR: return make_unique>(); + case DataType::INT8: return make_unique>(); + case DataType::UINT8: return make_unique>(); + case DataType::INT16: return make_unique>(); + case DataType::UINT16: return make_unique>(); + case DataType::INT32: return make_unique>(); + case DataType::UINT32: return make_unique>(); + case DataType::INT64: return make_unique>(); + case DataType::UINT64: return make_unique>(); + default: + std::cerr << "DataIOGen::newDataIO : couldn't create a DataIO of type \"" << type_name << "\"." << std::endl; + return std::unique_ptr>(); + } +} + +template +template +std::unique_ptr> DataInputGen::newDataIO(const std::string type_name) +{ + const DataType type = get_data_type(type_name); + switch (type) { + case DataType::FLOAT: return make_unique>(); + case DataType::DOUBLE: return make_unique>(); + case DataType::CHAR: return make_unique>(); + case DataType::INT8: return make_unique>(); + case DataType::UINT8: return make_unique>(); + case DataType::INT16: return make_unique>(); + case DataType::UINT16: return make_unique>(); + case DataType::INT32: return make_unique>(); + case DataType::UINT32: return make_unique>(); + case DataType::INT64: return make_unique>(); + case DataType::UINT64: return make_unique>(); + default: + std::cerr << "DataIOGen::newDataIO : couldn't create a DataIO of type \"" << type_name << "\"." << std::endl; + return std::unique_ptr>(); + } +} + +template +template +std::unique_ptr> DataInputGen::newDataIO(const std::string type_name, unsigned int nb_components) { - if (type_name == name_of_type(float())) - return make_unique>(); - else { - if (type_name == name_of_type(double())) - return make_unique>(); - else { - if (type_name == name_of_type(char())) - return make_unique>(); - else + cgogn_assert(nb_components >=1u && nb_components <= 4u); + if (nb_components == 1u) + return DataInputGen::newDataIO(type_name); + + if (type_name == name_of_type(std::int32_t())) + { + switch (nb_components) + { + case 2u: return make_unique>(); break; + case 3u: return make_unique>(); break; + case 4u: return make_unique>(); break; + default:break; + } + } else { + if (type_name == name_of_type(float())) + { + switch (nb_components) { - if (type_name == name_of_type(std::int8_t())) - return make_unique>(); - else + case 2u: return make_unique>(); break; + case 3u: return make_unique>(); break; + case 4u: return make_unique>(); break; + default:break; + } + } else { + if (type_name == name_of_type(double())) + { + switch (nb_components) { - if (type_name == name_of_type(std::uint8_t())) - return make_unique>(); - else - { - if (type_name == name_of_type(std::int16_t())) - return make_unique>(); - else - { - if (type_name == name_of_type(std::uint16_t())) - return make_unique>(); - else - { - if (type_name == name_of_type(std::uint32_t())) - return make_unique>(); - else - { - if (type_name == name_of_type(std::int32_t())) - return make_unique>(); - else - { - if (type_name == name_of_type(std::uint64_t())) - return make_unique>(); - else - { - if (type_name == name_of_type(std::int64_t())) - return make_unique>(); - } - } - } - } - } - } + case 2u: return make_unique>(); break; + case 3u: return make_unique>(); break; + case 4u: return make_unique>(); break; + default:break; } } } } - std::cerr << "DataIOGen::newDataIO : couldn't create a DataIO of type \"" << type_name << "\"." << std::endl; - return std::unique_ptr>(); + + std::cerr << "DataIOGen::newDataIO : couldn't create a DataIO of type \"" << type_name << "\" with " << nb_components << " components." << std::endl; + return std::unique_ptr>(); } template -template -std::unique_ptr> DataIOGen::newDataIO(const std::string type_name, unsigned int nb_components) +template +std::unique_ptr> DataInputGen::newDataIO(const std::string type_name, unsigned int nb_components) { cgogn_assert(nb_components >=1u && nb_components <= 4u); if (nb_components == 1u) - return DataIOGen::newDataIO(type_name); + return DataInputGen::newDataIO(type_name); if (type_name == name_of_type(std::int32_t())) { switch (nb_components) { - case 2u: return make_unique>(); break; - case 3u: return make_unique>(); break; - case 4u: return make_unique>(); break; + case 2u: return make_unique>(); break; + case 3u: return make_unique>(); break; + case 4u: return make_unique>(); break; default:break; } } else { @@ -272,9 +342,9 @@ std::unique_ptr> DataIOGen::newDataIO(const st { switch (nb_components) { - case 2u: return make_unique>(); break; - case 3u: return make_unique>(); break; - case 4u: return make_unique>(); break; + case 2u: return make_unique>(); break; + case 3u: return make_unique>(); break; + case 4u: return make_unique>(); break; default:break; } } else { @@ -282,9 +352,9 @@ std::unique_ptr> DataIOGen::newDataIO(const st { switch (nb_components) { - case 2u: return make_unique>(); break; - case 3u: return make_unique>(); break; - case 4u: return make_unique>(); break; + case 2u: return make_unique>(); break; + case 3u: return make_unique>(); break; + case 4u: return make_unique>(); break; default:break; } } @@ -292,7 +362,7 @@ std::unique_ptr> DataIOGen::newDataIO(const st } std::cerr << "DataIOGen::newDataIO : couldn't create a DataIO of type \"" << type_name << "\" with " << nb_components << " components." << std::endl; - return std::unique_ptr>(); + return std::unique_ptr>(); } } // namespace io diff --git a/cgogn/io/io_utils.h b/cgogn/io/io_utils.h index cbf1992f..286e12c3 100644 --- a/cgogn/io/io_utils.h +++ b/cgogn/io/io_utils.h @@ -65,9 +65,79 @@ inline FileType get_file_type(const std::string& filename) return FileType::FileType_UNKNOWN; } +enum DataType +{ + CHAR = 0, + INT8, + UINT8, + INT16, + UINT16, + INT32, + UINT32, + INT64, + UINT64, + FLOAT, + DOUBLE, + UNKNOWN +}; + +inline DataType get_data_type(const std::string& type_name) +{ + if (type_name == name_of_type(float())) + return DataType::FLOAT; + else if (type_name == name_of_type(double())) + return DataType::DOUBLE; + else if (type_name == name_of_type(char())) + return DataType::CHAR; + else if (type_name == name_of_type(std::int8_t())) + return DataType::INT8; + else if (type_name == name_of_type(std::uint8_t())) + return DataType::UINT8; + else if (type_name == name_of_type(std::int16_t())) + return DataType::INT16; + else if (type_name == name_of_type(std::uint16_t())) + return DataType::UINT16; + else if (type_name == name_of_type(std::int32_t())) + return DataType::INT32; + else if (type_name == name_of_type(std::uint32_t())) + return DataType::UINT32; + else if (type_name == name_of_type(std::int64_t())) + return DataType::INT64; + else if (type_name == name_of_type(std::uint64_t())) + return DataType::UINT64; + + return DataType::UNKNOWN; +} + namespace internal { +// #1 return default value when U and T don't have the same nb of components. +template +inline auto convert(const T&) -> typename std::enable_if::value>, std::integral_constant::value>>::value,U>::type +{ + std::cerr << "Cannot convert data of type\"" << name_of_type(T()) << "\" to type \"" << name_of_type(U()) << "\"." << std::endl; + return U(); +} + +// #2 cast x if both types have only one component. +template +inline auto convert(const T&x) -> typename std::enable_if<(std::is_arithmetic::value || std::is_floating_point::value) && (std::is_arithmetic::value || std::is_floating_point::value),U>::type +{ + return U(x); +} + +// #3 copy component by component if both type have the same number of components (>1) +template +inline auto convert(const T& x) -> typename std::enable_if::value && !std::is_floating_point::value && std::is_same< std::integral_constant::value>, std::integral_constant::value>>::value, U>::type +{ + U res; + for(unsigned int i = 0u; i < geometry::nb_components_traits::value ; ++i) + res[i] = typename geometry::vector_traits::Scalar(x[i]); + return res; +} + + template inline typename std::enable_if::value || std::is_floating_point::value, T>::type swap_endianness(const T& x) { diff --git a/cgogn/io/vtk_io.h b/cgogn/io/vtk_io.h index 41df7d0c..c0201137 100644 --- a/cgogn/io/vtk_io.h +++ b/cgogn/io/vtk_io.h @@ -75,21 +75,21 @@ public : }; using Self = VtkIO; - using DataIOGen = cgogn::io::DataIOGen; + using DataInputGen = cgogn::io::DataInputGen; template - using DataIO = cgogn::io::DataIO; + using DataInput = cgogn::io::DataInput; using Scalar = typename VEC3::Scalar; virtual ~VtkIO() {} protected : - std::unique_ptr positions_; - DataIO cells_; - DataIO cell_types_; + std::unique_ptr positions_; + DataInput cells_; + DataInput cell_types_; protected : - virtual void add_vertex_attribute(const DataIOGen& attribute_data, const std::string& attribute_name) = 0; - virtual void add_cell_attribute(const DataIOGen& attribute_data, const std::string& attribute_name) = 0; + virtual void add_vertex_attribute(const DataInputGen& attribute_data, const std::string& attribute_name) = 0; + virtual void add_cell_attribute(const DataInputGen& attribute_data, const std::string& attribute_name) = 0; bool parse_vtk_legacy_file(std::ifstream& fp) { @@ -141,7 +141,7 @@ protected : std::string type_str; sstream >> nb_vertices >> type_str; type_str = to_lower(type_str); - positions_ = DataIOGen::template newDataIO(type_str, 3); + positions_ = DataInputGen::template newDataIO(type_str, 3); positions_->read_n(fp, nb_vertices, !ascii_file, false); this->add_vertex_attribute(*positions_,"position"); } else { @@ -218,7 +218,7 @@ protected : fp.seekg(pos_before_lookup_table); // if there wasn't a lookup table we go back and start reading the numerical values } - std::unique_ptr att(DataIOGen::template newDataIO(att_type, num_comp)); + std::unique_ptr att(DataInputGen::template newDataIO(att_type, num_comp)); att->read_n(fp, nb_data, !ascii_file, false); if (cell_data) this->add_cell_attribute(*att, att_name); @@ -244,7 +244,7 @@ protected : std::string data_type; sstream >> data_name >> nb_comp >> nb_data >> data_type; std::cout << "reading field \"" << data_name << "\" of type " << data_type << " (" << nb_comp << " components)." << std::endl; - std::unique_ptr att(DataIOGen::template newDataIO(data_type, nb_comp)); + std::unique_ptr att(DataInputGen::template newDataIO(data_type, nb_comp)); att->read_n(fp, nb_data, !ascii_file, false); if (cell_data) this->add_cell_attribute(*att, data_name); @@ -260,11 +260,11 @@ protected : std::cout << "ignoring the definition of the lookuptable named \"" << table_name << "\"" << std::endl; if (ascii_file) { - DataIO trash; + DataInput trash; trash.skip_n(fp, nb_data, false); } else { - DataIO trash; + DataInput trash; trash.skip_n(fp, nb_data, true); } } @@ -326,9 +326,9 @@ class VtkSurfaceImport : public VtkIO: using Self = VtkSurfaceImport; using Inherit_Vtk = VtkIO::PRIM_SIZE, VEC3>; using Inherit_Import = SurfaceImport; - using DataIOGen = typename Inherit_Vtk::DataIOGen; + using DataInputGen = typename Inherit_Vtk::DataInputGen; template - using DataIO = typename Inherit_Vtk::template DataIO; + using DataInput = typename Inherit_Vtk::template DataInput; using VTK_CELL_TYPES = typename Inherit_Vtk::VTK_CELL_TYPES; virtual ~VtkSurfaceImport() override {} @@ -379,11 +379,11 @@ class VtkSurfaceImport : public VtkIO: return true; } - virtual void add_vertex_attribute(const DataIOGen& attribute_data, const std::string& attribute_name) override + virtual void add_vertex_attribute(const DataInputGen& attribute_data, const std::string& attribute_name) override { attribute_data.to_chunk_array(attribute_data.add_attribute(this->vertex_attributes_, attribute_name)); } - virtual void add_cell_attribute(const DataIOGen& attribute_data, const std::string& attribute_name) override + virtual void add_cell_attribute(const DataInputGen& attribute_data, const std::string& attribute_name) override { attribute_data.to_chunk_array(attribute_data.add_attribute(this->face_attributes_, attribute_name)); } @@ -405,9 +405,9 @@ class VtkVolumeImport : public VtkIO:: using Self = VtkVolumeImport; using Inherit_Vtk = VtkIO::PRIM_SIZE, VEC3>; using Inherit_Import = VolumeImport; - using DataIOGen = typename Inherit_Vtk::DataIOGen; + using DataInputGen = typename Inherit_Vtk::DataInputGen; template - using DataIO = typename Inherit_Vtk::template DataIO; + using DataInput = typename Inherit_Vtk::template DataInput; using VTK_CELL_TYPES = typename Inherit_Vtk::VTK_CELL_TYPES; template using ChunkArray = typename Inherit_Import::template ChunkArray; @@ -461,11 +461,11 @@ class VtkVolumeImport : public VtkIO:: return true; } - virtual void add_vertex_attribute(const DataIOGen& attribute_data, const std::string& attribute_name) override + virtual void add_vertex_attribute(const DataInputGen& attribute_data, const std::string& attribute_name) override { attribute_data.to_chunk_array(attribute_data.add_attribute(this->vertex_attributes_, attribute_name)); } - virtual void add_cell_attribute(const DataIOGen& attribute_data, const std::string& attribute_name) override + virtual void add_cell_attribute(const DataInputGen& attribute_data, const std::string& attribute_name) override { attribute_data.to_chunk_array(attribute_data.add_attribute(this->volume_attributes_, attribute_name)); } From 1063bed5934ec1759bb5ed509d79a52b24e1967f Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Mon, 7 Mar 2016 01:11:10 +0100 Subject: [PATCH 257/402] make_unique.h -> unique_ptr.h Added dynamic_cast_unique_ptr function. Signed-off-by: Etienne Schmitt --- cgogn/core/CMakeLists.txt | 2 +- cgogn/core/cmap/map_base.h | 2 +- cgogn/core/container/chunk_array_container.h | 2 +- cgogn/core/container/chunk_array_factory.h | 2 +- cgogn/core/utils/{make_unique.h => unique_ptr.h} | 10 ++++++++++ cgogn/io/data_io.h | 2 +- 6 files changed, 15 insertions(+), 5 deletions(-) rename cgogn/core/utils/{make_unique.h => unique_ptr.h} (92%) diff --git a/cgogn/core/CMakeLists.txt b/cgogn/core/CMakeLists.txt index 8a21eb6e..250e19fd 100644 --- a/cgogn/core/CMakeLists.txt +++ b/cgogn/core/CMakeLists.txt @@ -32,7 +32,7 @@ set(HEADER_FILES utils/buffers.h utils/definitions.h utils/endian.h - utils/make_unique.h + utils/unique_ptr.h utils/name_types.h utils/serialization.h utils/thread.h diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index d863e644..56bd42b6 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -35,7 +35,7 @@ #include #include -#include +#include namespace cgogn { diff --git a/cgogn/core/container/chunk_array_container.h b/cgogn/core/container/chunk_array_container.h index 94491770..3136d117 100644 --- a/cgogn/core/container/chunk_array_container.h +++ b/cgogn/core/container/chunk_array_container.h @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/cgogn/core/container/chunk_array_factory.h b/cgogn/core/container/chunk_array_factory.h index 9b7f2b8b..a8e33a74 100644 --- a/cgogn/core/container/chunk_array_factory.h +++ b/cgogn/core/container/chunk_array_factory.h @@ -24,7 +24,7 @@ #ifndef CORE_CONTAINER_CHUNK_ARRAY_FACTORY_H_ #define CORE_CONTAINER_CHUNK_ARRAY_FACTORY_H_ -#include +#include #include #include diff --git a/cgogn/core/utils/make_unique.h b/cgogn/core/utils/unique_ptr.h similarity index 92% rename from cgogn/core/utils/make_unique.h rename to cgogn/core/utils/unique_ptr.h index 61e5d7fc..b9748798 100644 --- a/cgogn/core/utils/make_unique.h +++ b/cgogn/core/utils/unique_ptr.h @@ -75,6 +75,16 @@ template typename _Unique_if::_Known_bound make_unique(Args&&...) = delete; + +template +inline std::unique_ptr dynamic_cast_unique_ptr(std::unique_ptr&& ptr) +{ + TO* const res = dynamic_cast(ptr.get()); + if (res != nullptr) + ptr.release(); + return std::unique_ptr(res); +} + } // namespace cgogn #endif // CORE_UTILS_MAKE_UNIQUE_H diff --git a/cgogn/io/data_io.h b/cgogn/io/data_io.h index fb1ff316..0420cf98 100644 --- a/cgogn/io/data_io.h +++ b/cgogn/io/data_io.h @@ -27,7 +27,7 @@ #include #include -#include +#include #include #include From 8d89f8860a5710f37c6f7c2a2fd456d0a39f24cc Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Mon, 7 Mar 2016 01:11:49 +0100 Subject: [PATCH 258/402] Removed base64 thirdparty Signed-off-by: Etienne Schmitt --- cgogn/io/CMakeLists.txt | 4 +- thirdparty/CMakeLists.txt | 1 - thirdparty/base64/CMakeLists.txt | 16 ---- thirdparty/base64/base64.cpp | 153 ------------------------------- thirdparty/base64/base64.h | 32 ------- 5 files changed, 2 insertions(+), 204 deletions(-) delete mode 100644 thirdparty/base64/CMakeLists.txt delete mode 100644 thirdparty/base64/base64.cpp delete mode 100644 thirdparty/base64/base64.h diff --git a/cgogn/io/CMakeLists.txt b/cgogn/io/CMakeLists.txt index 8d221a73..f35e8dd8 100644 --- a/cgogn/io/CMakeLists.txt +++ b/cgogn/io/CMakeLists.txt @@ -24,6 +24,7 @@ set(SOURCE_FILES volume_import.cpp import_ply_data.cpp mesh_io_gen.cpp + io_utils.cpp ) add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) @@ -35,11 +36,10 @@ target_include_directories(${PROJECT_NAME} PUBLIC $ $ $ - $ $ ) -target_link_libraries(${PROJECT_NAME} tinyxml2 cgogn_core cgogn_geometry ply base64) +target_link_libraries(${PROJECT_NAME} tinyxml2 cgogn_core cgogn_geometry ply) install(DIRECTORY . DESTINATION include/cgogn/io diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index 674f8700..c4a92db5 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -19,5 +19,4 @@ if (CGOGN_BUILD_BENCHS) endif(CGOGN_BUILD_BENCHS) add_subdirectory(ply) -add_subdirectory(base64) add_subdirectory(OffBinConverter) diff --git a/thirdparty/base64/CMakeLists.txt b/thirdparty/base64/CMakeLists.txt deleted file mode 100644 index 8de90045..00000000 --- a/thirdparty/base64/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -set(CGOGN_THIRDPARTY_BASE64_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE PATH "base64 include directory") - -project(base64 - LANGUAGES CXX - ) - -set(HEADER_FILES - base64.h - ) - -set(SOURCE_FILES - base64.cpp - ) - -add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) -set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "_d") diff --git a/thirdparty/base64/base64.cpp b/thirdparty/base64/base64.cpp deleted file mode 100644 index 152edfb0..00000000 --- a/thirdparty/base64/base64.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/******************************************************************************* -* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * -* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * -* * -* This library is free software; you can redistribute it and/or modify it * -* under the terms of the GNU Lesser General Public License as published by the * -* Free Software Foundation; either version 2.1 of the License, or (at your * -* option) any later version. * -* * -* This library is distributed in the hope that it will be useful, but WITHOUT * -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * -* for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with this library; if not, write to the Free Software Foundation, * -* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * -* * -* Web site: http://cgogn.unistra.fr/ * -* Contact information: cgogn@unistra.fr * -* * -*******************************************************************************/ - -/* - base64.cpp and base64.h - - Copyright (C) 2004-2008 René Nyffenegger - - This source code is provided 'as-is', without any express or implied - warranty. In no event will the author be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this source code must not be misrepresented; you must not - claim that you wrote the original source code. If you use this source code - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original source code. - - 3. This notice may not be removed or altered from any source distribution. - - René Nyffenegger rene.nyffenegger@adp-gmbh.ch - -*/ - -#include "base64.h" -#include - -namespace base64 -{ - - -static const std::string base64_chars = - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; - - -inline bool is_base64(unsigned char c) -{ - return (isalnum(c) || (c == '+') || (c == '/')); -} - -std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) { - std::string ret; - int i = 0; - int j = 0; - unsigned char char_array_3[3]; - unsigned char char_array_4[4]; - - while (in_len--) { - char_array_3[i++] = *(bytes_to_encode++); - if (i == 3) { - char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; - char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); - char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); - char_array_4[3] = char_array_3[2] & 0x3f; - - for(i = 0; (i <4) ; i++) - ret += base64_chars[char_array_4[i]]; - i = 0; - } - } - - if (i) - { - for(j = i; j < 3; j++) - char_array_3[j] = '\0'; - - char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; - char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); - char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); - char_array_4[3] = char_array_3[2] & 0x3f; - - for (j = 0; (j < i + 1); j++) - ret += base64_chars[char_array_4[j]]; - - while((i++ < 3)) - ret += '='; - - } - - return ret; - -} - -std::string base64_decode(std::string const& encoded_string) { - int in_len = encoded_string.size(); - int i = 0; - int j = 0; - int in_ = 0; - unsigned char char_array_4[4], char_array_3[3]; - std::string ret; - - while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { - char_array_4[i++] = encoded_string[in_]; in_++; - if (i ==4) { - for (i = 0; i <4; i++) - char_array_4[i] = base64_chars.find(char_array_4[i]); - - char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); - char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); - char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; - - for (i = 0; (i < 3); i++) - ret += char_array_3[i]; - i = 0; - } - } - - if (i) { - for (j = i; j <4; j++) - char_array_4[j] = 0; - - for (j = 0; j <4; j++) - char_array_4[j] = base64_chars.find(char_array_4[j]); - - char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); - char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); - char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; - - for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; - } - - return ret; -} - -} // namespace base64 diff --git a/thirdparty/base64/base64.h b/thirdparty/base64/base64.h deleted file mode 100644 index a6886a92..00000000 --- a/thirdparty/base64/base64.h +++ /dev/null @@ -1,32 +0,0 @@ -/******************************************************************************* -* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * -* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * -* * -* This library is free software; you can redistribute it and/or modify it * -* under the terms of the GNU Lesser General Public License as published by the * -* Free Software Foundation; either version 2.1 of the License, or (at your * -* option) any later version. * -* * -* This library is distributed in the hope that it will be useful, but WITHOUT * -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * -* for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with this library; if not, write to the Free Software Foundation, * -* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * -* * -* Web site: http://cgogn.unistra.fr/ * -* Contact information: cgogn@unistra.fr * -* * -*******************************************************************************/ - -#include - -namespace base64 -{ - -std::string base64_encode(unsigned char const* , unsigned int len); -std::string base64_decode(std::string const& s); - -} // namespace base64 From 67a5c66e72892e9e22543453fbc13c60cdf64ba7 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Mon, 7 Mar 2016 01:12:23 +0100 Subject: [PATCH 259/402] added base64_decode function. Signed-off-by: Etienne Schmitt --- cgogn/io/io_utils.cpp | 147 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 cgogn/io/io_utils.cpp diff --git a/cgogn/io/io_utils.cpp b/cgogn/io/io_utils.cpp new file mode 100644 index 00000000..2ce85028 --- /dev/null +++ b/cgogn/io/io_utils.cpp @@ -0,0 +1,147 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#define CGOGN_IO_DLL_EXPORT + +#include +#include + +#include +#include + +namespace cgogn +{ + +namespace io +{ + +CGOGN_IO_API std::vector base64_decode(std::string& input) +{ + input.erase(std::remove(input.begin(), input.end(), ' '), input.end()); + input.erase(std::remove(input.begin(), input.end(), '\n'), input.end()); + input.erase(std::remove(input.begin(), input.end(), '\t'), input.end()); + + const static char padCharacter('='); + if (input.length() % 4) //Sanity check + throw std::runtime_error("Non-Valid base64!"); + size_t padding = 0; + if (input.length()) + { + if (input[input.length()-1] == padCharacter) + padding++; + if (input[input.length()-2] == padCharacter) + padding++; + } + //Setup a vector to hold the result + std::vector decoded_chars; + decoded_chars.reserve(((input.length()/4)*3) - padding); + long int temp=0; //Holds decoded quanta + std::basic_string::const_iterator cursor = input.begin(); + while (cursor < input.end()) + { + for (size_t quantumPosition = 0; quantumPosition < 4; quantumPosition++) + { + temp <<= 6; + if (*cursor >= 0x41 && *cursor <= 0x5A) // This area will need tweaking if + temp |= *cursor - 0x41; // you are using an alternate alphabet + else if (*cursor >= 0x61 && *cursor <= 0x7A) + temp |= *cursor - 0x47; + else if (*cursor >= 0x30 && *cursor <= 0x39) + temp |= *cursor + 0x04; + else if (*cursor == 0x2B) + temp |= 0x3E; //change to 0x2D for URL alphabet + else if (*cursor == 0x2F) + temp |= 0x3F; //change to 0x5F for URL alphabet + else if (*cursor == padCharacter) //pad + { + switch( input.end() - cursor ) + { + case 1: //One pad character + decoded_chars.push_back((temp >> 16) & 0x000000FF); + decoded_chars.push_back((temp >> 8 ) & 0x000000FF); + return decoded_chars; + case 2: //Two pad characters + decoded_chars.push_back((temp >> 10) & 0x000000FF); + return decoded_chars; + default: + throw std::runtime_error("Invalid Padding in Base 64!"); + } + } else + throw std::runtime_error("Non-Valid Character in Base 64!"); + cursor++; + } + decoded_chars.push_back((temp >> 16) & 0x000000FF); + decoded_chars.push_back((temp >> 8 ) & 0x000000FF); + decoded_chars.push_back((temp ) & 0x000000FF); + } + return decoded_chars; +} + +CGOGN_IO_API FileType get_file_type(const std::string& filename) +{ + const std::string& extension = to_lower(get_extension(filename)); + if (extension == "off") + return FileType::FileType_OFF; + if (extension == "obj") + return FileType::FileType_OBJ; + if (extension == "ply") + return FileType::FileType_PLY; + if (extension == "vtk") + return FileType::FileType_VTK_LEGACY; + if (extension == "vtu") + return FileType::FileType_VTU; + return FileType::FileType_UNKNOWN; +} + +CGOGN_IO_API DataType get_data_type(const std::string& type_name) +{ + if (type_name == name_of_type(float())) + return DataType::FLOAT; + else if (type_name == name_of_type(double())) + return DataType::DOUBLE; + else if (type_name == name_of_type(char())) + return DataType::CHAR; + else if (type_name == name_of_type(std::int8_t())) + return DataType::INT8; + else if (type_name == name_of_type(std::uint8_t())) + return DataType::UINT8; + else if (type_name == name_of_type(std::int16_t())) + return DataType::INT16; + else if (type_name == name_of_type(std::uint16_t())) + return DataType::UINT16; + else if (type_name == name_of_type(std::int32_t())) + return DataType::INT32; + else if (type_name == name_of_type(std::uint32_t())) + return DataType::UINT32; + else if (type_name == name_of_type(std::int64_t())) + return DataType::INT64; + else if (type_name == name_of_type(std::uint64_t())) + return DataType::UINT64; + + return DataType::UNKNOWN; +} + +} // namespace io + +} // namespace cgogn + From b8ee7f903e7c8161d58f81f31e7a1f6afb643463 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Mon, 7 Mar 2016 01:13:32 +0100 Subject: [PATCH 260/402] fixed a bug when parsing std::(u)int8_t from a stringstrim and added DataInputGen::simplify method Signed-off-by: Etienne Schmitt --- cgogn/io/data_io.h | 46 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/cgogn/io/data_io.h b/cgogn/io/data_io.h index 0420cf98..74a83e9a 100644 --- a/cgogn/io/data_io.h +++ b/cgogn/io/data_io.h @@ -46,6 +46,7 @@ template class DataInputGen { public: + using Self = DataInputGen; using ChunkArrayGen = cgogn::ChunkArrayGen; using ChunkArrayContainer = cgogn::ChunkArrayContainer; @@ -55,6 +56,12 @@ class DataInputGen virtual const void* get_data() const = 0; virtual void reset() = 0; virtual std::size_t size() const = 0; + /** + * @brief simplify, transform a DataInput into a DataInput + * @return a DataInput with T = BUFFER_T + * WARNING : after a call to simplify, the data is moved to the returned DataInputGen, leaving an empty vector. + */ + virtual std::unique_ptr simplify() = 0; virtual void to_chunk_array(ChunkArrayGen* ca_gen) const = 0; virtual ChunkArrayGen* add_attribute(ChunkArrayContainer& cac, const std::string& att_name) const = 0; @@ -89,9 +96,28 @@ class DataInput : public DataInputGen DataInput() {} - DataInput(const Self&) = delete; - DataInput& operator =(const Self&) = delete; - DataInput(Self&&) = default; + inline DataInput(const Self& other) : + data_(other.data_) + {} + + inline DataInput(Self&& other) : + data_(std::move(other.data_)) + {} + + inline DataInput& operator =(const Self& other) + { + if (&other != this) + data_ = other.data_; + return *this; + } + + inline DataInput& operator =(Self&& other) + { + if (&other != this) + data_ = std::move(other.data_); + return *this; + } + virtual void read_n(std::istream& fp, std::size_t n, bool binary, bool big_endian) override { @@ -136,13 +162,14 @@ class DataInput : public DataInputGen bool no_error = true; std::getline(fp,line); std::istringstream line_stream(line); - BUFFER_T buff; + // we need to avoid the specialization of istringstream operator>> for chars + using type = typename std::conditional::type; + type buff; while (i < n && (no_error = static_cast(internal::parse(line_stream, buff)))) { data_[i+old_size] = internal::convert(buff); ++i; } - if (!no_error && (!line_stream.eof())) break; } @@ -225,6 +252,15 @@ class DataInput : public DataInputGen return data_.size(); } + virtual std::unique_ptr simplify() override + { + std::unique_ptr> res = make_unique>(); + std::vector& res_vec = *(static_cast*>(res->get_data())); + res_vec = std::move(this->data_); + this->data_ = std::vector(); + return res; + } + private: std::vector data_; }; From bd1ca36ed02d662aad0f8ae967307a4580bce598 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Mon, 7 Mar 2016 01:14:09 +0100 Subject: [PATCH 261/402] vtu import (both ascii and binary) is now working pretty well. Signed-off-by: Etienne Schmitt --- cgogn/io/io_utils.h | 48 +------ cgogn/io/vtk_io.h | 323 +++++++++++++++++++++++++------------------- 2 files changed, 186 insertions(+), 185 deletions(-) diff --git a/cgogn/io/io_utils.h b/cgogn/io/io_utils.h index 286e12c3..3a8c0e80 100644 --- a/cgogn/io/io_utils.h +++ b/cgogn/io/io_utils.h @@ -28,8 +28,8 @@ #include #include - #include +#include namespace cgogn { @@ -37,7 +37,7 @@ namespace cgogn namespace io { - +CGOGN_IO_API std::vector base64_decode(std::string& input); enum FileType { @@ -49,21 +49,7 @@ enum FileType FileType_VTU }; -inline FileType get_file_type(const std::string& filename) -{ - const std::string& extension = to_lower(get_extension(filename)); - if (extension == "off") - return FileType::FileType_OFF; - if (extension == "obj") - return FileType::FileType_OBJ; - if (extension == "ply") - return FileType::FileType_PLY; - if (extension == "vtk") - return FileType::FileType_VTK_LEGACY; - if (extension == "vtu") - return FileType::FileType_VTU; - return FileType::FileType_UNKNOWN; -} +CGOGN_IO_API FileType get_file_type(const std::string& filename); enum DataType { @@ -81,33 +67,7 @@ enum DataType UNKNOWN }; -inline DataType get_data_type(const std::string& type_name) -{ - if (type_name == name_of_type(float())) - return DataType::FLOAT; - else if (type_name == name_of_type(double())) - return DataType::DOUBLE; - else if (type_name == name_of_type(char())) - return DataType::CHAR; - else if (type_name == name_of_type(std::int8_t())) - return DataType::INT8; - else if (type_name == name_of_type(std::uint8_t())) - return DataType::UINT8; - else if (type_name == name_of_type(std::int16_t())) - return DataType::INT16; - else if (type_name == name_of_type(std::uint16_t())) - return DataType::UINT16; - else if (type_name == name_of_type(std::int32_t())) - return DataType::INT32; - else if (type_name == name_of_type(std::uint32_t())) - return DataType::UINT32; - else if (type_name == name_of_type(std::int64_t())) - return DataType::INT64; - else if (type_name == name_of_type(std::uint64_t())) - return DataType::UINT64; - - return DataType::UNKNOWN; -} +CGOGN_IO_API DataType get_data_type(const std::string& type_name); namespace internal { diff --git a/cgogn/io/vtk_io.h b/cgogn/io/vtk_io.h index c0201137..4b0e2e4b 100644 --- a/cgogn/io/vtk_io.h +++ b/cgogn/io/vtk_io.h @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -37,6 +38,8 @@ namespace cgogn namespace io { +CGOGN_IO_API std::vector base64_decode(const std::basic_string& input); + template class VtkIO { @@ -83,9 +86,10 @@ public : virtual ~VtkIO() {} protected : - std::unique_ptr positions_; - DataInput cells_; - DataInput cell_types_; + DataInput positions_; + DataInput cells_; + DataInput cell_types_; + DataInput offsets_; protected : virtual void add_vertex_attribute(const DataInputGen& attribute_data, const std::string& attribute_name) = 0; @@ -141,9 +145,10 @@ protected : std::string type_str; sstream >> nb_vertices >> type_str; type_str = to_lower(type_str); - positions_ = DataInputGen::template newDataIO(type_str, 3); - positions_->read_n(fp, nb_vertices, !ascii_file, false); - this->add_vertex_attribute(*positions_,"position"); + auto pos = DataInputGen::template newDataIO(type_str, 3); + pos->read_n(fp, nb_vertices, !ascii_file, false); + this->add_vertex_attribute(*pos,"position"); + this->positions_ = std::move(*dynamic_cast_unique_ptr>(pos->simplify())); } else { if (word == "CELLS" || word == "POLYGONS" || word == "TRIANGLE_STRIPS") { @@ -289,6 +294,154 @@ protected : return true; } + + bool parse_xml_vtu(const std::string& filename) + { + using tinyxml2::XMLDocument; + using tinyxml2::XMLError; + using tinyxml2::XML_NO_ERROR; + using tinyxml2::XMLElement; + + XMLDocument doc; + XMLError eResult = doc.LoadFile(filename.c_str()); + if (eResult != XML_NO_ERROR) + { + std::cerr << "Unable to load file \"" << filename << "\"." << std::endl; + return false; + } + + XMLElement* root_node = doc.RootElement(); + cgogn_assert(root_node != nullptr); + const bool little_endian = (to_lower(std::string(root_node->Attribute("byte_order"))) == "littleendian"); + + XMLElement* grid_node = root_node->FirstChildElement("UnstructuredGrid"); + cgogn_assert(grid_node != nullptr); + XMLElement* piece_node = grid_node->FirstChildElement("Piece"); + cgogn_assert(piece_node != nullptr); + + unsigned int nb_vertices = 0u; + unsigned int nb_cells = 0u; + + piece_node->QueryUnsignedAttribute("NumberOfPoints",&nb_vertices); + piece_node->QueryUnsignedAttribute("NumberOfCells",&nb_cells); + if (nb_vertices == 0u|| nb_cells == 0u) + return false; + + XMLElement* points_node = piece_node->FirstChildElement("Points"); + cgogn_assert(points_node != nullptr); + XMLElement* vertices_array_node = points_node->FirstChildElement("DataArray"); + cgogn_assert(vertices_array_node != nullptr); + + while (vertices_array_node) + { + const std::string& data_name = to_lower(std::string(vertices_array_node->Attribute("Name"))); + const bool binary = (to_lower(std::string(vertices_array_node->Attribute("format", nullptr))) == "binary"); + unsigned int nb_comp = 1; + vertices_array_node->QueryUnsignedAttribute("NumberOfComponents", &nb_comp); + const std::string type = vtk_data_type_to_cgogn_name_of_type(std::string(vertices_array_node->Attribute("type", nullptr))); + + if (data_name.empty()) + std::cerr << "import_VTU : Skipping a vertex DataArray without \"Name\" attribute." << std::endl; + else { + std::string text(vertices_array_node->GetText()); + if (binary) + { + std::vector decode = base64_decode(text); + const unsigned int length = *reinterpret_cast(&decode[0]); + text = std::string(reinterpret_cast(&decode[8]), length); + } + + std::istringstream ss(text); + if (data_name == "points") + { + cgogn_assert(nb_comp == 3); + auto pos = DataInputGen::template newDataIO(type, nb_comp); + pos->read_n(ss, nb_vertices,binary,true); + this->add_vertex_attribute(*pos,"position"); + this->positions_ = std::move(*dynamic_cast_unique_ptr>(pos->simplify())); + } + else { + std::unique_ptr vertex_att = DataInputGen::template newDataIO(type, nb_comp); + vertex_att->read_n(ss, nb_vertices,binary,!little_endian); + this->add_vertex_attribute(*vertex_att, data_name); + } + } + vertices_array_node = vertices_array_node->NextSiblingElement("DataArray"); + } + + + XMLElement* cell_node = piece_node->FirstChildElement("Cells"); + cgogn_assert(cell_node != nullptr); + XMLElement* cells_array_node = cell_node->FirstChildElement("DataArray"); + cgogn_assert(cells_array_node != nullptr); + + { + std::string cell_connectivity; + bool cell_connectivity_is_bin = false; + std::string cell_connectivity_type; + + while (cells_array_node) + { + const std::string& data_name = to_lower(std::string(cells_array_node->Attribute("Name"))); + const bool binary = (to_lower(std::string(cells_array_node->Attribute("format", nullptr))) == "binary"); + unsigned int nb_comp = 1; + cells_array_node->QueryUnsignedAttribute("NumberOfComponents", &nb_comp); + std::string type = vtk_data_type_to_cgogn_name_of_type(std::string(cells_array_node->Attribute("type", nullptr))); + + if (data_name.empty()) + std::cerr << "import_VTU : Skipping a cell DataArray without \"Name\" attribute." << std::endl; + else { + std::string text(cells_array_node->GetText()); + if (binary) + { + std::vector decode = base64_decode(text); + const unsigned int length = *reinterpret_cast(&decode[0]); + text = std::string(reinterpret_cast(&decode[8]), length); + } + + std::istringstream ss(text); + if (data_name == "connectivity") + { + cell_connectivity_is_bin = binary; + cell_connectivity_type = std::move(type); + cell_connectivity = std::move(text); + } + else { + if (data_name == "offsets") + { + auto offsets = DataInputGen::template newDataIO(type); + offsets->read_n(ss, nb_cells,binary,true); + this->offsets_ = std::move(*dynamic_cast_unique_ptr>(offsets->simplify())); + } + else { + if (data_name == "types") + { + auto types = DataInputGen::template newDataIO(type); + types->read_n(ss, nb_cells,binary,true); + this->cell_types_ = std::move(*dynamic_cast_unique_ptr>(types->simplify())); + } + else { + auto cell_att = DataInputGen::template newDataIO(type, nb_comp); + cell_att->read_n(ss, nb_cells,binary,true); + this->add_cell_attribute(*cell_att, data_name); + } + } + } + } + cells_array_node = cells_array_node->NextSiblingElement("DataArray"); + } + { + std::istringstream ss(cell_connectivity); + const unsigned int last_offset = this->offsets_.get_vec()->back(); + auto cells = DataInputGen::template newDataIO(cell_connectivity_type); + cells->read_n(ss, last_offset,cell_connectivity_is_bin,true); + this->cells_ = std::move(*dynamic_cast_unique_ptr>(cells->simplify())); + } + } + return true; + } + + static inline std::string vtk_data_type_to_cgogn_name_of_type(const std::string& vtk_type_str) { const std::string& data_type = to_lower(vtk_type_str); @@ -338,7 +491,7 @@ class VtkSurfaceImport : public VtkIO: if (!Inherit_Vtk::parse_vtk_legacy_file(fp)) return false; - this->nb_vertices_ = this->positions_->size(); + this->nb_vertices_ = this->positions_.size(); this->nb_faces_ = this->cell_types_.size(); auto cells_it = static_cast*>(this->cells_.get_data())->begin(); @@ -420,12 +573,11 @@ class VtkVolumeImport : public VtkIO:: if (!Inherit_Vtk::parse_vtk_legacy_file(fp)) return false; - this->nb_vertices_ = this->positions_->size(); + this->nb_vertices_ = this->positions_.size(); this->nb_volumes_ = this->cell_types_.size(); - const std::vector* cell_types_vec = this->cell_types_.get_vec(); - const std::vector* cells_vec =this->cells_.get_vec(); - + const std::vector* cell_types_vec = this->cell_types_.get_vec(); + const std::vector* cells_vec = this->cells_.get_vec(); std::vector cells_buffer; cells_buffer.reserve(cells_vec->size()); @@ -461,6 +613,22 @@ class VtkVolumeImport : public VtkIO:: return true; } + inline bool read_vtk_xml_file(const std::string& filename) + { + if (!Inherit_Vtk::parse_xml_vtu(filename)) + return false; + + this->nb_vertices_ = this->positions_.size(); + this->nb_volumes_ = this->cell_types_.size(); + + const std::vector* cell_types_vec = this->cell_types_.get_vec(); + const std::vector* cells_vec = this->cells_.get_vec(); + + add_vtk_volumes(*cells_vec,*cell_types_vec, *(this->vertex_attributes_.template get_attribute("position"))); + + return true; + } + virtual void add_vertex_attribute(const DataInputGen& attribute_data, const std::string& attribute_name) override { attribute_data.to_chunk_array(attribute_data.add_attribute(this->vertex_attributes_, attribute_name)); @@ -479,143 +647,15 @@ class VtkVolumeImport : public VtkIO:: std::ifstream fp(filename.c_str(), std::ios::in | std::ios::binary); return this->read_vtk_legacy_file(fp); } - case FileType::FileType_VTU: return this->import_VTU(filename); + case FileType::FileType_VTU: return this->read_vtk_xml_file(filename); default: std::cerr << "VtkVolumeImport does not handle the files of type \"" << get_extension(filename) << "\"." << std::endl; return false; } } - bool import_VTU(const std::string& filename) - { - using tinyxml2::XMLDocument; - using tinyxml2::XMLError; - using tinyxml2::XML_NO_ERROR; - using tinyxml2::XMLElement; - typename Inherit_Import::template ChunkArray* position = - this->vertex_attributes_.template add_attribute("position"); - cgogn_assert(position != nullptr); - - XMLDocument doc; - XMLError eResult = doc.LoadFile(filename.c_str()); - if (eResult != XML_NO_ERROR) - { - std::cerr << "unable loading file " << filename << std::endl; - return false; - } - - XMLElement* vtu_node = doc.RootElement(); - cgogn_assert(vtu_node != nullptr); - XMLElement* grid_node = vtu_node->FirstChildElement("UnstructuredGrid"); - cgogn_assert(grid_node != nullptr); - XMLElement* piece_node = grid_node->FirstChildElement("Piece"); - cgogn_assert(piece_node != nullptr); - - eResult = piece_node->QueryUnsignedAttribute("NumberOfPoints",&this->nb_vertices_); - if (eResult != XML_NO_ERROR) - { - std::cerr << "unreadable VTU file: " << filename << std::endl; - return false; - } - eResult = piece_node->QueryUnsignedAttribute("NumberOfCells",&this->nb_volumes_); - if (eResult != XML_NO_ERROR) - { - std::cerr << "unreadable VTU file: " << filename << std::endl; - return false; - } - - std::cout << "reading file " << filename << std::endl; - std::cout << "Number of vertices : " << this->nb_vertices_ << std::endl; - std::cout << "Number of volumes : " << this->nb_volumes_ << std::endl; - - XMLElement* points_node = piece_node->FirstChildElement("Points"); - cgogn_assert(points_node != nullptr); - XMLElement* array_node = points_node->FirstChildElement("DataArray"); - cgogn_assert(array_node != nullptr); - - std::stringstream ss(array_node->GetText()); - for (unsigned int i=0u; i< this->nb_vertices_; ++i) - { - VEC3 P; - ss >> P[0]; - ss >> P[1]; - ss >> P[2]; - unsigned int id = this->vertex_attributes_.template insert_lines<1>(); - position->operator [](id) = P; - cgogn_assert(id == i); - } - - XMLElement* cell_node = piece_node->FirstChildElement("Cells"); - cgogn_assert(cell_node != nullptr); - array_node = cell_node->FirstChildElement("DataArray"); - cgogn_assert(array_node != nullptr); - - std::vector typeVols; - typeVols.reserve(this->nb_volumes_); - std::vector offsets; - offsets.reserve(this->nb_volumes_); - std::vector indices; - indices.reserve(this->nb_volumes_*4u); - - while (array_node) - { - const std::string& propName = to_lower(std::string(array_node->Attribute("Name"))); - if (propName.empty()) - { - std::cerr << "Error reading VTU unreadable file: "<< filename << std::endl; - return false; - } - - if (propName == "connectivity") - { - std::stringstream ss(array_node->GetText()); - while (!ss.eof()) - { - unsigned int ind; - ss >> ind; - indices.push_back(ind); - } - } - if (propName == "offsets") - { - std::stringstream ss(array_node->GetText()); - for (unsigned int i=0u; i< this->nb_volumes_; ++i) - { - unsigned int o; - ss >> o; - offsets.push_back(o); - } - } - if (propName == "types") - { - bool unsupported = false; - std::stringstream ss(array_node->GetText()); - for (unsigned int i=0u; i< this->nb_volumes_; ++i) - { - unsigned int t; - ss >> t; - if (!(t == 10u || t == 12u)) - { - std::cerr << "error while parsing vtk file : volumes of type " << t << " are not supported" << std::endl; - unsupported = true; - } - typeVols.push_back(t); - } - if (unsupported) - { - std::cerr << "warning, some unsupported volume cell types"<< std::endl; - } - - } - array_node = array_node->NextSiblingElement("DataArray"); - } - - add_vtk_volumes(indices, typeVols, *position); - return true; - } - - inline void add_vtk_volumes(std::vector& ids, const std::vector& type_vol, ChunkArray const& pos) + inline void add_vtk_volumes(std::vector ids, const std::vector& type_vol, ChunkArray const& pos) { unsigned int curr_offset = 0; for (unsigned int i=0u; i< this->nb_volumes_; ++i) @@ -651,6 +691,7 @@ class VtkVolumeImport : public VtkIO:: } } }; + } // namespace io } // namespace cgogn From 8930a07a1a47e69a85eeaf5863745c8167ab44d6 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Mon, 7 Mar 2016 10:33:16 +0100 Subject: [PATCH 262/402] remove random loop (Pierre) + random surface generation --- cgogn/core/cmap/cmap2.h | 3 +- cgogn/core/cmap/cmap3.h | 1 + cgogn/core/tests/cmap/cmap1_test.cpp | 4 +-- cgogn/core/tests/cmap/cmap1_topo_test.cpp | 4 +-- cgogn/core/tests/cmap/cmap2_test.cpp | 4 +-- cgogn/core/tests/cmap/cmap2_topo_test.cpp | 41 +++++++++++++++-------- 6 files changed, 36 insertions(+), 21 deletions(-) diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 477923f6..eb558809 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -144,7 +144,8 @@ class CMap2_T : public CMap1_T inline bool check_integrity(Dart d) const { return (Inherit::check_integrity(d) && - phi2(phi2(d)) == d); + phi2(phi2(d)) == d && + phi2(d) != d); } /** diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index d464f8ea..9bfe0a29 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -157,6 +157,7 @@ class CMap3_T : public CMap2_T inline bool check_integrity(Dart d) const { return (Inherit::check_integrity(d) && phi3(phi3(d)) == d && + phi3(d) != d && phi3(this->phi1(phi3(this->phi1(d)))) == d); } diff --git a/cgogn/core/tests/cmap/cmap1_test.cpp b/cgogn/core/tests/cmap/cmap1_test.cpp index 8f5858d1..e3da3925 100644 --- a/cgogn/core/tests/cmap/cmap1_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_test.cpp @@ -80,8 +80,8 @@ class CMap1Test: public ::testing::Test Dart d = cmap_.add_face(n); count += n; - while (std::rand()%10 != 1) - d = cmap_.phi1(d); + n = std::rand() % 10; + while (n-- > 0) d = cmap_.phi1(d); darts_.push_back(d); } diff --git a/cgogn/core/tests/cmap/cmap1_topo_test.cpp b/cgogn/core/tests/cmap/cmap1_topo_test.cpp index 1e61c339..3e4b2bbe 100644 --- a/cgogn/core/tests/cmap/cmap1_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_topo_test.cpp @@ -83,8 +83,8 @@ class CMap1TopoTest : public CMap1, public ::testing::Test Dart d = add_face_topo(n); count += n; - while (std::rand()%10 != 1) - d = phi1(d); + n = std::rand() % 10; + while (n-- > 0) d = phi1(d); darts_.push_back(d); } diff --git a/cgogn/core/tests/cmap/cmap2_test.cpp b/cgogn/core/tests/cmap/cmap2_test.cpp index 7e13f16e..30d3bf19 100644 --- a/cgogn/core/tests/cmap/cmap2_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_test.cpp @@ -71,8 +71,8 @@ class CMap2Test: public ::testing::Test Dart d = cmap_.add_face(n); count += n; - while (std::rand()%10 != 1) - d = cmap_.phi1(d); + n = std::rand() % 10; + while (n-- > 0) d = cmap_.phi1(d); tdarts_[i] = d; } diff --git a/cgogn/core/tests/cmap/cmap2_topo_test.cpp b/cgogn/core/tests/cmap/cmap2_topo_test.cpp index 3171bab3..70f98aa7 100644 --- a/cgogn/core/tests/cmap/cmap2_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_topo_test.cpp @@ -43,6 +43,7 @@ class CMap2TopoTest: public CMap2, public ::testing::Test public: + using Inherit = CMap2; using Vertex = CMap2TopoTest::Vertex; using Edge = CMap2TopoTest::Edge; using Face = CMap2TopoTest::Face; @@ -78,8 +79,8 @@ class CMap2TopoTest: public CMap2, public ::testing::Test Dart d = add_face_topo(n); count += n; - while (std::rand()%10 != 1) - d = phi1(d); + n = std::rand() % 10; + while (n-- > 0) d = phi1(d); darts_.push_back(d); } @@ -91,16 +92,28 @@ class CMap2TopoTest: public CMap2, public ::testing::Test */ void makeSurface() { - for (unsigned int i = 0; i < NB_MAX; ++i) { - Face f1 = darts_[std::rand() % NB_MAX]; - while (std::rand()%10 != 1) f1 = phi1(f1.dart); - Face f2 = darts_[std::rand() % NB_MAX]; - while (std::rand()%10 != 1) f2 = phi1(f2.dart); + unsigned int n = 0; - foreach_dart_of_orbit_until(f1, [&] (Dart d) { + // Generate NB_MAX random 1-faces (with no boundary) + for (unsigned int i = 0; i < NB_MAX; ++i) + { + n = 1 + std::rand() % 10; + Dart d = Inherit::Inherit::add_face_topo(n); + darts_.push_back(d); + } + // Sew some pairs off 1-egdes + for (unsigned int i = 0; i < 3*NB_MAX; ++i) { + Dart e1 = darts_[std::rand() % NB_MAX]; + n = std::rand() % 10; + while (n-- > 0) e1 = phi1(e1); + Dart e2 = darts_[std::rand() % NB_MAX]; + n = std::rand() % 10; + while (n-- > 0) e2 = phi1(e2); + + foreach_dart_of_orbit_until(Face(e1), [&] (Dart d) { if (phi2(d) == d) { - if (phi2(f2.dart) == f2.dart) { - // sewfaces + if (phi2(e2) == e2 && e2 != d) { + phi2_sew(e2, d); return (std::rand()%3 == 1); } else @@ -110,6 +123,7 @@ class CMap2TopoTest: public CMap2, public ::testing::Test return false; }); } + close_map(); } }; @@ -128,7 +142,7 @@ TEST_F(CMap2TopoTest, Constructor) /*! * \brief Sewing and unsewing darts correctly changes the topological relations. * The test perfoms NB_MAX sewing and unsewing on randomly chosen dart of darts_. - * The map integrity is preserved. + * The map integrity is not preserved (this test creates fixed points for PHI2). */ TEST_F(CMap2TopoTest, phi2_sew_unsew) { @@ -150,8 +164,6 @@ TEST_F(CMap2TopoTest, phi2_sew_unsew) EXPECT_TRUE(phi2(d0) == e0); EXPECT_TRUE(phi2(e0) == d0); } - - EXPECT_TRUE(check_map_integrity()); } /*! @@ -217,7 +229,8 @@ TEST_F(CMap2TopoTest, testCutFace) for (int i = 0; i < NB_MAX; ++i) { Dart d = darts_[i]; Dart e = d; - while (std::rand()%10 != 1) e = phi1(e); + unsigned int j = std::rand() % 10; + while (j-- > 0) e = phi1(e); if (e == d) e = phi1(e); unsigned int k = degree(Face(d)); From fbd0da400cd28cbcf2cb47d63273f55e0b75ca14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Mon, 7 Mar 2016 11:52:45 +0100 Subject: [PATCH 263/402] Fixed Format -> format in liverHexa.vtu. Added binary version of the "nine hexas" mesh. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- data/meshes/liverHexa.vtu | 2 +- data/meshes/nine_hexas_bin.vtu | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 data/meshes/nine_hexas_bin.vtu diff --git a/data/meshes/liverHexa.vtu b/data/meshes/liverHexa.vtu index 7fc24b1c..b0748956 100644 --- a/data/meshes/liverHexa.vtu +++ b/data/meshes/liverHexa.vtu @@ -1532,7 +1532,7 @@ - + 1 1 1 diff --git a/data/meshes/nine_hexas_bin.vtu b/data/meshes/nine_hexas_bin.vtu new file mode 100644 index 00000000..67072b7b --- /dev/null +++ b/data/meshes/nine_hexas_bin.vtu @@ -0,0 +1,26 @@ + + + + + + + + + + AAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPA/AAAAAAAAAAAAAAAAAADwPwAAAAAAAPA/AAAAAAAAAAAAAAAAAAAAQAAAAAAAAPA/AAAAAAAAAAAAAAAAAAAIQAAAAAAAAPA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAADwPwAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAIQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhAAAAAAAAAAAAAAAAAAADwPwAAAAAAAAhAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAhAAAAAAAAAAAAAAAAAAAAIQAAAAAAAAAhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8D8AAAAAAADwPwAAAAAAAAAAAAAAAAAA8D8AAAAAAAAAQAAAAAAAAAAAAAAAAAAA8D8AAAAAAAAIQAAAAAAAAAAAAAAAAAAA8D8AAAAAAAAAAAAAAAAAAPA/AAAAAAAA8D8AAAAAAADwPwAAAAAAAPA/AAAAAAAA8D8AAAAAAAAAQAAAAAAAAPA/AAAAAAAA8D8AAAAAAAAIQAAAAAAAAPA/AAAAAAAA8D8AAAAAAAAAAAAAAAAAAABAAAAAAAAA8D8AAAAAAADwPwAAAAAAAABAAAAAAAAA8D8AAAAAAAAAQAAAAAAAAABAAAAAAAAA8D8AAAAAAAAIQAAAAAAAAABAAAAAAAAA8D8AAAAAAAAAAAAAAAAAAAhAAAAAAAAA8D8AAAAAAADwPwAAAAAAAAhAAAAAAAAA8D8AAAAAAAAAQAAAAAAAAAhAAAAAAAAA8D8AAAAAAAAIQAAAAAAAAAhAAAAAAAAA8D8= + + + + + QAIAAAAAAAAAAAAAAAAAAAEAAAAAAAAABQAAAAAAAAAEAAAAAAAAABAAAAAAAAAAEQAAAAAAAAAVAAAAAAAAABQAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAYAAAAAAAAABQAAAAAAAAARAAAAAAAAABIAAAAAAAAAFgAAAAAAAAAVAAAAAAAAAAIAAAAAAAAAAwAAAAAAAAAHAAAAAAAAAAYAAAAAAAAAEgAAAAAAAAATAAAAAAAAABcAAAAAAAAAFgAAAAAAAAAEAAAAAAAAAAUAAAAAAAAACQAAAAAAAAAIAAAAAAAAABQAAAAAAAAAFQAAAAAAAAAZAAAAAAAAABgAAAAAAAAABQAAAAAAAAAGAAAAAAAAAAoAAAAAAAAACQAAAAAAAAAVAAAAAAAAABYAAAAAAAAAGgAAAAAAAAAZAAAAAAAAAAYAAAAAAAAABwAAAAAAAAALAAAAAAAAAAoAAAAAAAAAFgAAAAAAAAAXAAAAAAAAABsAAAAAAAAAGgAAAAAAAAAIAAAAAAAAAAkAAAAAAAAADQAAAAAAAAAMAAAAAAAAABgAAAAAAAAAGQAAAAAAAAAdAAAAAAAAABwAAAAAAAAACQAAAAAAAAAKAAAAAAAAAA4AAAAAAAAADQAAAAAAAAAZAAAAAAAAABoAAAAAAAAAHgAAAAAAAAAdAAAAAAAAAAoAAAAAAAAACwAAAAAAAAAPAAAAAAAAAA4AAAAAAAAAGgAAAAAAAAAbAAAAAAAAAB8AAAAAAAAAHgAAAAAAAAA= + + + SAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAGAAAAAAAAAAgAAAAAAAAACgAAAAAAAAAMAAAAAAAAAA4AAAAAAAAAEAAAAAAAAAASAAAAAAAAAA= + + + CQAAAAAAAAAMDAwMDAwMDAw= + + + + + From 4fda26a72fbac3087a6c543efc87b8dafc278641 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Mon, 7 Mar 2016 11:54:35 +0100 Subject: [PATCH 264/402] fixed some details when importing VTU file. Every vertex or cell attribute is now added to the map during the mesh loading. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/surface_import.h | 1 + cgogn/io/volume_import.h | 4 +- cgogn/io/vtk_io.h | 87 ++++++++++++++++++++++++++++----------- 3 files changed, 67 insertions(+), 25 deletions(-) diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index 8acaf1e5..9aaf14ec 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -117,6 +117,7 @@ class SurfaceImport : public MeshImportGen mbuild.template create_embedding(); mbuild.template swap_chunk_array_container(this->vertex_attributes_); + mbuild.template swap_chunk_array_container(this->face_attributes_); typename Map::template VertexAttributeHandler> darts_per_vertex = map.template add_attribute, Vertex::ORBIT>("darts_per_vertex"); diff --git a/cgogn/io/volume_import.h b/cgogn/io/volume_import.h index 5c92d492..c68def69 100644 --- a/cgogn/io/volume_import.h +++ b/cgogn/io/volume_import.h @@ -53,6 +53,7 @@ class VolumeImport : public MeshImportGen using Inherit = MeshImportGen; using Map = CMap3; using Vertex = typename Map::Vertex; + using Volume = typename Map::Volume; static const unsigned int CHUNK_SIZE = MAP_TRAITS::CHUNK_SIZE; @@ -110,6 +111,7 @@ class VolumeImport : public MeshImportGen mbuild.template create_embedding(); mbuild.template swap_chunk_array_container(this->vertex_attributes_); + mbuild.template swap_chunk_array_container(this->volume_attributes_); typename Map::template VertexAttributeHandler> darts_per_vertex = map.template add_attribute, Vertex::ORBIT>("darts_per_vertex"); unsigned int index = 0u; @@ -248,8 +250,6 @@ class VolumeImport : public MeshImportGen } - std::cout << " elements created " << std::endl; - //reconstruct neighbourhood unsigned int nbBoundaryFaces = 0; for (Dart d : map) diff --git a/cgogn/io/vtk_io.h b/cgogn/io/vtk_io.h index 4b0e2e4b..b347b585 100644 --- a/cgogn/io/vtk_io.h +++ b/cgogn/io/vtk_io.h @@ -314,6 +314,12 @@ protected : cgogn_assert(root_node != nullptr); const bool little_endian = (to_lower(std::string(root_node->Attribute("byte_order"))) == "littleendian"); + std::string header_type("unsigned int"); + if (root_node->Attribute("header_type")) + header_type = vtk_data_type_to_cgogn_name_of_type(root_node->Attribute("header_type")); + const unsigned int header_size = (get_data_type(header_type) == DataType::UINT64)? 8u : 4u; + + XMLElement* grid_node = root_node->FirstChildElement("UnstructuredGrid"); cgogn_assert(grid_node != nullptr); XMLElement* piece_node = grid_node->FirstChildElement("Piece"); @@ -329,30 +335,44 @@ protected : XMLElement* points_node = piece_node->FirstChildElement("Points"); cgogn_assert(points_node != nullptr); - XMLElement* vertices_array_node = points_node->FirstChildElement("DataArray"); - cgogn_assert(vertices_array_node != nullptr); + XMLElement*const position_data_array_node = points_node->FirstChildElement("DataArray"); + cgogn_assert(position_data_array_node != nullptr); + XMLElement* point_data_node = piece_node->FirstChildElement("PointData"); + XMLElement* point_data_array_node = point_data_node ? point_data_node->FirstChildElement("DataArray") : nullptr; + std::vector vertices_nodes = {position_data_array_node}; + while (point_data_array_node) + { + vertices_nodes.push_back(point_data_array_node); + point_data_array_node = point_data_array_node->NextSiblingElement("DataArray"); + } - while (vertices_array_node) + for (XMLElement* vertex_data : vertices_nodes) { - const std::string& data_name = to_lower(std::string(vertices_array_node->Attribute("Name"))); - const bool binary = (to_lower(std::string(vertices_array_node->Attribute("format", nullptr))) == "binary"); + std::string data_name("cgogn_unnamed_vertex_data"); + if (vertex_data->Attribute("Name")) + data_name = to_lower(std::string(vertex_data->Attribute("Name"))); + const bool binary = (to_lower(std::string(vertex_data->Attribute("format", nullptr))) == "binary"); unsigned int nb_comp = 1; - vertices_array_node->QueryUnsignedAttribute("NumberOfComponents", &nb_comp); - const std::string type = vtk_data_type_to_cgogn_name_of_type(std::string(vertices_array_node->Attribute("type", nullptr))); + vertex_data->QueryUnsignedAttribute("NumberOfComponents", &nb_comp); + const std::string type = vtk_data_type_to_cgogn_name_of_type(std::string(vertex_data->Attribute("type", nullptr))); if (data_name.empty()) std::cerr << "import_VTU : Skipping a vertex DataArray without \"Name\" attribute." << std::endl; else { - std::string text(vertices_array_node->GetText()); + std::string text(vertex_data->GetText()); if (binary) { std::vector decode = base64_decode(text); - const unsigned int length = *reinterpret_cast(&decode[0]); - text = std::string(reinterpret_cast(&decode[8]), length); + unsigned int length = 0u; + if (header_size == 4u) + length = *reinterpret_cast(&decode[0]); + else + length = *reinterpret_cast(&decode[0]); + text = std::string(reinterpret_cast(&decode[header_size]), length); } std::istringstream ss(text); - if (data_name == "points") + if (vertex_data == position_data_array_node) { cgogn_assert(nb_comp == 3); auto pos = DataInputGen::template newDataIO(type, nb_comp); @@ -366,37 +386,55 @@ protected : this->add_vertex_attribute(*vertex_att, data_name); } } - vertices_array_node = vertices_array_node->NextSiblingElement("DataArray"); } - XMLElement* cell_node = piece_node->FirstChildElement("Cells"); + XMLElement* const cell_node = piece_node->FirstChildElement("Cells"); cgogn_assert(cell_node != nullptr); XMLElement* cells_array_node = cell_node->FirstChildElement("DataArray"); cgogn_assert(cells_array_node != nullptr); + std::vector cell_nodes; + while (cells_array_node) + { + cell_nodes.push_back(cells_array_node); + cells_array_node = cells_array_node->NextSiblingElement("DataArray"); + } + + XMLElement* const cell_data_node = piece_node->FirstChildElement("CellData"); + cells_array_node = cell_data_node ? cell_data_node->FirstChildElement("DataArray") : nullptr; + while (cells_array_node) + { + cell_nodes.push_back(cells_array_node); + cells_array_node = cells_array_node->NextSiblingElement("DataArray"); + } + { std::string cell_connectivity; bool cell_connectivity_is_bin = false; std::string cell_connectivity_type; - while (cells_array_node) + for (XMLElement* cell_data : cell_nodes) { - const std::string& data_name = to_lower(std::string(cells_array_node->Attribute("Name"))); - const bool binary = (to_lower(std::string(cells_array_node->Attribute("format", nullptr))) == "binary"); + const std::string& data_name = to_lower(std::string(cell_data->Attribute("Name"))); + const bool binary = (to_lower(std::string(cell_data->Attribute("format", nullptr))) == "binary"); unsigned int nb_comp = 1; - cells_array_node->QueryUnsignedAttribute("NumberOfComponents", &nb_comp); - std::string type = vtk_data_type_to_cgogn_name_of_type(std::string(cells_array_node->Attribute("type", nullptr))); + cell_data->QueryUnsignedAttribute("NumberOfComponents", &nb_comp); + std::string type = vtk_data_type_to_cgogn_name_of_type(std::string(cell_data->Attribute("type", nullptr))); if (data_name.empty()) std::cerr << "import_VTU : Skipping a cell DataArray without \"Name\" attribute." << std::endl; else { - std::string text(cells_array_node->GetText()); + std::string text(cell_data->GetText()); if (binary) { std::vector decode = base64_decode(text); - const unsigned int length = *reinterpret_cast(&decode[0]); - text = std::string(reinterpret_cast(&decode[8]), length); + unsigned int length = 0u; + if (header_size == 4u) + length = *reinterpret_cast(&decode[0]); + else + length = *reinterpret_cast(&decode[0]); + text = std::string(reinterpret_cast(&decode[header_size]), length); } std::istringstream ss(text); @@ -421,6 +459,7 @@ protected : this->cell_types_ = std::move(*dynamic_cast_unique_ptr>(types->simplify())); } else { + std::cout << "Reading cell attribute \"" << data_name << "\" of type " << type << "." << std::endl; auto cell_att = DataInputGen::template newDataIO(type, nb_comp); cell_att->read_n(ss, nb_cells,binary,true); this->add_cell_attribute(*cell_att, data_name); @@ -428,8 +467,8 @@ protected : } } } - cells_array_node = cells_array_node->NextSiblingElement("DataArray"); } + { std::istringstream ss(cell_connectivity); const unsigned int last_offset = this->offsets_.get_vec()->back(); @@ -624,7 +663,9 @@ class VtkVolumeImport : public VtkIO:: const std::vector* cell_types_vec = this->cell_types_.get_vec(); const std::vector* cells_vec = this->cells_.get_vec(); - add_vtk_volumes(*cells_vec,*cell_types_vec, *(this->vertex_attributes_.template get_attribute("position"))); + ChunkArray* pos = this->vertex_attributes_.template get_attribute("position"); + cgogn_assert(pos != nullptr); + add_vtk_volumes(*cells_vec,*cell_types_vec, *pos); return true; } From 2f35817d5d31678017098bee7d9fa6ae768e16df Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Mon, 7 Mar 2016 12:10:36 +0100 Subject: [PATCH 265/402] cut_edge --- cgogn/core/cmap/cmap2_builder.h | 11 ++ cgogn/core/tests/cmap/cmap2_test.cpp | 118 ++++++++++++++++---- cgogn/core/tests/cmap/cmap2_topo_test.cpp | 124 +++++++++++++--------- 3 files changed, 179 insertions(+), 74 deletions(-) diff --git a/cgogn/core/cmap/cmap2_builder.h b/cgogn/core/cmap/cmap2_builder.h index 37f20002..22d8d5be 100644 --- a/cgogn/core/cmap/cmap2_builder.h +++ b/cgogn/core/cmap/cmap2_builder.h @@ -68,6 +68,12 @@ class CMap2Builder_T map_.template set_embedding(d, emb); } + template + inline void new_orbit_embedding(CellType c) + { + map_.template new_orbit_embedding(c); + } + inline void phi2_sew(Dart d, Dart e) { return map_.phi2_sew(d,e); @@ -83,6 +89,11 @@ class CMap2Builder_T return map_.CMap2::Inherit::add_face_topo(nb_edges); } + inline void close_hole_topo(Dart d) + { + map_.close_hole_topo(d); + } + inline void close_map() { map_.close_map(); diff --git a/cgogn/core/tests/cmap/cmap2_test.cpp b/cgogn/core/tests/cmap/cmap2_test.cpp index 30d3bf19..f6958e23 100644 --- a/cgogn/core/tests/cmap/cmap2_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_test.cpp @@ -23,7 +23,7 @@ #include -#include +#include namespace cgogn { @@ -45,6 +45,8 @@ class CMap2Test: public ::testing::Test public: using testCMap2 = CMap2; + using MapBuilder = CMap2Builder_T; + using CDart = testCMap2::CDart; using Vertex = testCMap2::Vertex; using Edge = testCMap2::Edge; using Face = testCMap2::Face; @@ -54,53 +56,127 @@ class CMap2Test: public ::testing::Test testCMap2 cmap_; + /*! + * \brief A vector of darts on which the methods are tested. + */ + std::vector darts_; + CMap2Test() { std::srand(static_cast(std::time(0))); + cmap_.add_attribute("darts"); cmap_.add_attribute("vertices"); cmap_.add_attribute("edges"); cmap_.add_attribute("faces"); cmap_.add_attribute("volumes"); } - int randomFaces() { - int count = 0; - for (int i = 0; i < NB_MAX; ++i) { - int n = 1 + std::rand() % 100; + /*! + * \brief Generate a random set of faces and put them in darts_ + * \return The total number of added vertices. + * The face size ranges from 1 to 10. + * A random dart of each face is put in the darts_ array. + */ + unsigned int addFaces(unsigned int n) + { + unsigned int count = 0u; + for (unsigned int i = 0u; i < n; ++i) + { + unsigned int n = 1 + std::rand() % 10u; Dart d = cmap_.add_face(n); count += n; - n = std::rand() % 10; - while (n-- > 0) d = cmap_.phi1(d); + n = std::rand() % 10u; + while (n-- > 0u) d = cmap_.phi1(d); - tdarts_[i] = d; + darts_.push_back(d); } return count; } - std::array tdarts_; + /*! + * \brief Generate a closed surface from the set of faces in darts_ + */ + void makeSurface() + { + MapBuilder mbuild(cmap_); + unsigned int n = 0u; + + // Generate NB_MAX random 1-faces (without boundary) + for (unsigned int i = 0; i < NB_MAX; ++i) + { + n = 1 + std::rand() % 10u; + Dart d = mbuild.add_face_topo_parent(n); + darts_.push_back(d); + } + // Sew some pairs off egdes + for (unsigned int i = 0; i < 3*NB_MAX; ++i) { + Dart e1 = darts_[std::rand() % NB_MAX]; + n = std::rand()%10u; + while (n-- > 0u) e1 = cmap_.phi1(e1); + + Dart e2 = darts_[std::rand() % NB_MAX]; + n = std::rand()%10u; + while (n-- > 0u) e2 = cmap_.phi1(e2); + + n = 1+std::rand()%3u; + while (n-- > 0u) { + if (cmap_.phi2(e1) == e1) { + if (cmap_.phi2(e2) == e2 && e2 != e1) { + mbuild.phi2_sew(e2, e1); + e1 = cmap_.phi1(e1); + e2 = cmap_.phi_1(e2); + } + } + } + } + // Close the map (remove remaining boundary) + cmap_.foreach_dart( [&] (Dart d) { + if (cmap_.phi2(d) == d) mbuild.close_hole_topo(d); + }); + // Embed the map + cmap_.foreach_dart( [&] (Dart d) { + mbuild.new_orbit_embedding(CDart(d)); + }); + cmap_.foreach_cell( [&] (Vertex v) { + mbuild.new_orbit_embedding(v); + }); + cmap_.foreach_cell( [&] (Edge e) { + mbuild.new_orbit_embedding(e); + }); + cmap_.foreach_cell( [&] (Face f) { + mbuild.new_orbit_embedding(f); + }); + cmap_.foreach_cell( [&] (Volume w) { + mbuild.new_orbit_embedding(w); + }); + } }; -TEST_F(CMap2Test, testCMap2Constructor) -{ - EXPECT_EQ(cmap_.nb_cells(), 0u); - EXPECT_EQ(cmap_.nb_cells(), 0u); - EXPECT_EQ(cmap_.nb_cells(), 0u); - EXPECT_EQ(cmap_.nb_cells(), 0u); -} - -TEST_F(CMap2Test, addFace) +/*! + * \brief Adding faces preserves the cell indexation + */ +TEST_F(CMap2Test, add_face) { - int n = randomFaces(); + unsigned int countVertices = addFaces(NB_MAX); - EXPECT_EQ(cmap_.nb_cells(), n); - EXPECT_EQ(cmap_.nb_cells(), n); + EXPECT_EQ(cmap_.nb_cells(), countVertices); + EXPECT_EQ(cmap_.nb_cells(), countVertices); EXPECT_EQ(cmap_.nb_cells(), 2*NB_MAX); EXPECT_EQ(cmap_.nb_cells(), NB_MAX); EXPECT_TRUE(cmap_.check_map_integrity()); } +/*! + * \brief Adding faces preserves the cell indexation + */ +TEST_F(CMap2Test, cut_edge) +{ + makeSurface(); + EXPECT_TRUE(cmap_.check_map_integrity()); +} + #undef NB_MAX } // namespace cgogn diff --git a/cgogn/core/tests/cmap/cmap2_topo_test.cpp b/cgogn/core/tests/cmap/cmap2_topo_test.cpp index 70f98aa7..45c8fc7d 100644 --- a/cgogn/core/tests/cmap/cmap2_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_topo_test.cpp @@ -72,15 +72,15 @@ class CMap2TopoTest: public CMap2, public ::testing::Test */ unsigned int addFaces(unsigned int n) { - unsigned int count = 0; - for (unsigned int i = 0; i < n; ++i) + unsigned int count = 0u; + for (unsigned int i = 0u; i < n; ++i) { - unsigned int n = 1 + std::rand() % 10; + unsigned int n = 1 + std::rand() % 10u; Dart d = add_face_topo(n); count += n; - n = std::rand() % 10; - while (n-- > 0) d = phi1(d); + n = std::rand() % 10u; + while (n-- > 0u) d = phi1(d); darts_.push_back(d); } @@ -92,38 +92,40 @@ class CMap2TopoTest: public CMap2, public ::testing::Test */ void makeSurface() { - unsigned int n = 0; + unsigned int n = 0u; - // Generate NB_MAX random 1-faces (with no boundary) - for (unsigned int i = 0; i < NB_MAX; ++i) + // Generate NB_MAX random 1-faces (without boundary) + for (unsigned int i = 0u; i < NB_MAX; ++i) { n = 1 + std::rand() % 10; Dart d = Inherit::Inherit::add_face_topo(n); darts_.push_back(d); } // Sew some pairs off 1-egdes - for (unsigned int i = 0; i < 3*NB_MAX; ++i) { + for (unsigned int i = 0u; i < 3*NB_MAX; ++i) { Dart e1 = darts_[std::rand() % NB_MAX]; - n = std::rand() % 10; - while (n-- > 0) e1 = phi1(e1); + n = std::rand() % 10u; + while (n-- > 0u) e1 = phi1(e1); + Dart e2 = darts_[std::rand() % NB_MAX]; - n = std::rand() % 10; - while (n-- > 0) e2 = phi1(e2); - - foreach_dart_of_orbit_until(Face(e1), [&] (Dart d) { - if (phi2(d) == d) { - if (phi2(e2) == e2 && e2 != d) { - phi2_sew(e2, d); - return (std::rand()%3 == 1); + n = std::rand() % 10u; + while (n-- > 0u) e2 = phi1(e2); + + n = 1+std::rand()%3u; + while (n-- > 0u) { + if (phi2(e1) == e1) { + if (phi2(e2) == e2 && e2 != e1) { + phi2_sew(e2, e1); + e1 = phi1(e1); + e2 = phi_1(e2); } - else - return false; } - else - return false; - }); + } } - close_map(); + // Close the map (remove remaining boundary) + foreach_dart( [&] (Dart d) { + if (phi2(d) == d) close_hole_topo(d); + }); } }; @@ -150,7 +152,7 @@ TEST_F(CMap2TopoTest, phi2_sew_unsew) unsigned int countFaces = NB_MAX; unsigned int countVolumes = NB_MAX; - for (int i = 0; i < NB_MAX; ++i) { + for (unsigned int i = 0u; i < NB_MAX; ++i) { Dart d0 = darts_[std::rand() % NB_MAX]; Dart d2 = phi2(d0); phi2_unsew(d0); @@ -173,27 +175,27 @@ TEST_F(CMap2TopoTest, phi2_sew_unsew) */ TEST_F(CMap2TopoTest, add_face_topo) { - add_face_topo(1); - EXPECT_EQ(nb_darts(), 2); - EXPECT_EQ(nb_cells(), 1); - EXPECT_EQ(nb_cells(), 1); - EXPECT_EQ(nb_cells(), 2); - EXPECT_EQ(nb_cells(), 1); - - add_face_topo(10); - EXPECT_EQ(nb_darts(), 22); - EXPECT_EQ(nb_cells(), 11); - EXPECT_EQ(nb_cells(), 11); - EXPECT_EQ(nb_cells(), 4); - EXPECT_EQ(nb_cells(), 2); - - unsigned int countVertices = 11 + addFaces(NB_MAX); - - EXPECT_EQ(nb_darts(), 2*countVertices); + add_face_topo(1u); + EXPECT_EQ(nb_darts(), 2u); + EXPECT_EQ(nb_cells(), 1u); + EXPECT_EQ(nb_cells(), 1u); + EXPECT_EQ(nb_cells(), 2u); + EXPECT_EQ(nb_cells(), 1u); + + add_face_topo(10u); + EXPECT_EQ(nb_darts(), 22u); + EXPECT_EQ(nb_cells(), 11u); + EXPECT_EQ(nb_cells(), 11u); + EXPECT_EQ(nb_cells(), 4u); + EXPECT_EQ(nb_cells(), 2u); + + unsigned int countVertices = 11u + addFaces(NB_MAX); + + EXPECT_EQ(nb_darts(), 2u*countVertices); EXPECT_EQ(nb_cells(), countVertices); EXPECT_EQ(nb_cells(), countVertices); - EXPECT_EQ(nb_cells(), 2*(NB_MAX+2)); - EXPECT_EQ(nb_cells(), NB_MAX+2); + EXPECT_EQ(nb_cells(), 2u*(NB_MAX+2u)); + EXPECT_EQ(nb_cells(), NB_MAX+2u); EXPECT_TRUE(check_map_integrity()); } @@ -203,19 +205,35 @@ TEST_F(CMap2TopoTest, add_face_topo) */ TEST_F(CMap2TopoTest, testCutEdge) { - int n = addFaces(NB_MAX); + makeSurface(); + EXPECT_TRUE(check_map_integrity()); - for (int i = 0; i < NB_MAX; ++i) { + unsigned int countVertices = nb_cells(); + unsigned int countEdges = nb_cells(); + unsigned int countFaces = nb_cells(); + unsigned int countVolumes = nb_cells(); + + for (unsigned int i = 0u; i < NB_MAX; ++i) + { Dart d = darts_[i]; - unsigned int k = degree(Face(d)); + unsigned int k1 = degree(Face(d)); + unsigned int k2 = degree(Face(phi2(d))); cut_edge_topo(d); - EXPECT_EQ(degree(Face(d)), k+1); + if (same_cell(Face(d),Face(phi2(d)))) + { + EXPECT_EQ(degree(Face(d)), k1+2u); + } + else + { + EXPECT_EQ(degree(Face(d)), k1+1u); + EXPECT_EQ(degree(Face(phi2(d))), k2+1u); + } } - EXPECT_EQ(this->template nb_cells(), n+NB_MAX); - EXPECT_EQ(this->template nb_cells(), n+NB_MAX); - EXPECT_EQ(this->template nb_cells(), 2*NB_MAX); - EXPECT_EQ(this->template nb_cells(), NB_MAX); + EXPECT_EQ(this->template nb_cells(), countVertices+NB_MAX); + EXPECT_EQ(this->template nb_cells(), countEdges+NB_MAX); + EXPECT_EQ(this->template nb_cells(), countFaces); + EXPECT_EQ(this->template nb_cells(), countVolumes); EXPECT_TRUE(check_map_integrity()); } From 7e6d7c74efe0fa173155d015157b40073ae2f8a7 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Mon, 7 Mar 2016 16:05:59 +0100 Subject: [PATCH 266/402] embed cut_edge --- cgogn/core/tests/cmap/cmap2_test.cpp | 5 ++++- cgogn/core/tests/cmap/cmap2_topo_test.cpp | 4 +--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/cgogn/core/tests/cmap/cmap2_test.cpp b/cgogn/core/tests/cmap/cmap2_test.cpp index f6958e23..6e96749b 100644 --- a/cgogn/core/tests/cmap/cmap2_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_test.cpp @@ -169,11 +169,14 @@ TEST_F(CMap2Test, add_face) } /*! - * \brief Adding faces preserves the cell indexation + * \brief Cutting edges preserves the cell indexation */ TEST_F(CMap2Test, cut_edge) { makeSurface(); + + for (Dart d: darts_) cmap_.cut_edge(d); + EXPECT_TRUE(cmap_.check_map_integrity()); } diff --git a/cgogn/core/tests/cmap/cmap2_topo_test.cpp b/cgogn/core/tests/cmap/cmap2_topo_test.cpp index 45c8fc7d..beafc0f6 100644 --- a/cgogn/core/tests/cmap/cmap2_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_topo_test.cpp @@ -206,16 +206,14 @@ TEST_F(CMap2TopoTest, add_face_topo) TEST_F(CMap2TopoTest, testCutEdge) { makeSurface(); - EXPECT_TRUE(check_map_integrity()); unsigned int countVertices = nb_cells(); unsigned int countEdges = nb_cells(); unsigned int countFaces = nb_cells(); unsigned int countVolumes = nb_cells(); - for (unsigned int i = 0u; i < NB_MAX; ++i) + for (Dart d: darts_) { - Dart d = darts_[i]; unsigned int k1 = degree(Face(d)); unsigned int k2 = degree(Face(phi2(d))); cut_edge_topo(d); From d8dbe942954a39750945e469c578ffd184825f57 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Mon, 7 Mar 2016 18:21:12 +0100 Subject: [PATCH 267/402] close_map + code cleaning --- cgogn/core/cmap/map_base.h | 1 + cgogn/core/tests/cmap/cmap0_test.cpp | 17 ++- cgogn/core/tests/cmap/cmap0_topo_test.cpp | 28 ++-- cgogn/core/tests/cmap/cmap1_test.cpp | 50 ++++--- cgogn/core/tests/cmap/cmap1_topo_test.cpp | 96 +++++++------ cgogn/core/tests/cmap/cmap2_test.cpp | 81 ++++++++--- cgogn/core/tests/cmap/cmap2_topo_test.cpp | 158 ++++++++++++++-------- 7 files changed, 272 insertions(+), 159 deletions(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 16f47425..45e4894a 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -450,6 +450,7 @@ class MapBase : public MapBaseData } } } + remove_attribute(marker); return result; } diff --git a/cgogn/core/tests/cmap/cmap0_test.cpp b/cgogn/core/tests/cmap/cmap0_test.cpp index 6af55def..58dfb32b 100644 --- a/cgogn/core/tests/cmap/cmap0_test.cpp +++ b/cgogn/core/tests/cmap/cmap0_test.cpp @@ -63,6 +63,7 @@ class CMap0Test: public ::testing::Test */ CMap0Test() { + darts_.reserve(NB_MAX); std::srand(static_cast(std::time(0))); vertices_ = cmap_.add_attribute("vertices"); } @@ -71,19 +72,29 @@ class CMap0Test: public ::testing::Test * \brief Initialize the darts in darts_ with added vertices * \param n : the number of added darts or vertices */ - void addVertices(unsigned int n) + void add_vertices(unsigned int n) { + darts_.clear(); for (unsigned int i = 0; i < n; ++i) darts_.push_back(cmap_.add_vertex()); } }; +/*! + * \brief The random generated maps used in the tests are sound. + */ +TEST_F(CMap0Test, random_map_generators) +{ + add_vertices(NB_MAX); + EXPECT_TRUE(cmap_.check_map_integrity()); +} + /*! * \brief Adding vertices preserves the cell indexation */ TEST_F(CMap0Test, add_vertex) { - addVertices(NB_MAX); + add_vertices(NB_MAX); EXPECT_TRUE(cmap_.check_map_integrity()); } @@ -92,7 +103,7 @@ TEST_F(CMap0Test, add_vertex) */ TEST_F(CMap0Test, remove_vertex) { - addVertices(NB_MAX); + add_vertices(NB_MAX); for (Dart d: darts_) if (std::rand()%3 == 1) cmap_.remove_vertex(Vertex(d)); diff --git a/cgogn/core/tests/cmap/cmap0_topo_test.cpp b/cgogn/core/tests/cmap/cmap0_topo_test.cpp index d13081ab..9c3fa066 100644 --- a/cgogn/core/tests/cmap/cmap0_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap0_topo_test.cpp @@ -57,6 +57,7 @@ class CMap0TopoTest: public ::testing::Test CMap0TopoTest() { + darts_.reserve(NB_MAX); std::srand(static_cast(std::time(0))); } @@ -64,20 +65,23 @@ class CMap0TopoTest: public ::testing::Test * \brief Initialize the darts in darts_ with added vertices * \param n : the number of added darts or vertices */ - void addVertices(unsigned int n) + void add_vertices(unsigned int n) { + darts_.clear(); for (unsigned int i = 0; i < n; ++i) darts_.push_back(cmap_.add_vertex()); } }; /*! - * \brief An empty CMap0 contains no dart and no vertex + * \brief The random generated maps used in the tests are sound. */ TEST_F(CMap0TopoTest, Constructor) { EXPECT_EQ(cmap_.nb_darts(), 0u); - EXPECT_EQ(cmap_.nb_cells(), 0u); + + add_vertices(NB_MAX); + EXPECT_TRUE(cmap_.check_map_integrity()); } /*! @@ -90,7 +94,7 @@ TEST_F(CMap0TopoTest, add_vertex) EXPECT_EQ(cmap_.nb_darts(), 1u); EXPECT_EQ(cmap_.nb_cells(), 1u); - addVertices(NB_MAX); + add_vertices(NB_MAX); EXPECT_EQ(cmap_.nb_darts(), NB_MAX+1u); EXPECT_EQ(cmap_.nb_cells(), NB_MAX+1u); @@ -103,13 +107,13 @@ TEST_F(CMap0TopoTest, add_vertex) */ TEST_F(CMap0TopoTest, remove_vertex) { - addVertices(NB_MAX); - int countVertices = NB_MAX; + add_vertices(NB_MAX); + int count_vertices = NB_MAX; cmap_.remove_vertex(darts_.back()); - --countVertices; - EXPECT_EQ(cmap_.nb_darts(), countVertices); - EXPECT_EQ(cmap_.nb_cells(), countVertices); + --count_vertices; + EXPECT_EQ(cmap_.nb_darts(), count_vertices); + EXPECT_EQ(cmap_.nb_cells(), count_vertices); darts_.pop_back(); for (Dart d: darts_) @@ -117,11 +121,11 @@ TEST_F(CMap0TopoTest, remove_vertex) if (std::rand()%3 == 1) { cmap_.remove_vertex(d); - --countVertices; + --count_vertices; } } - EXPECT_EQ(cmap_.nb_darts(), countVertices); - EXPECT_EQ(cmap_.nb_cells(), countVertices); + EXPECT_EQ(cmap_.nb_darts(), count_vertices); + EXPECT_EQ(cmap_.nb_cells(), count_vertices); EXPECT_TRUE(cmap_.check_map_integrity()); } diff --git a/cgogn/core/tests/cmap/cmap1_test.cpp b/cgogn/core/tests/cmap/cmap1_test.cpp index e3da3925..47db2820 100644 --- a/cgogn/core/tests/cmap/cmap1_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_test.cpp @@ -59,6 +59,7 @@ class CMap1Test: public ::testing::Test CMap1Test() { + darts_.reserve(NB_MAX); std::srand(static_cast(std::time(0))); cmap_.add_attribute("vertices"); @@ -71,8 +72,9 @@ class CMap1Test: public ::testing::Test * The face size ranges from 1 to 10. * A random dart of each face is put in the darts_ array. */ - unsigned int addFaces(unsigned int n) + unsigned int add_faces(unsigned int n) { + darts_.clear(); unsigned int count = 0; for (unsigned int i = 0; i < n; ++i) { @@ -89,14 +91,23 @@ class CMap1Test: public ::testing::Test } }; +/*! + * \brief The random generated maps used in the tests are sound. + */ +TEST_F(CMap1Test, random_map_generators) +{ + add_faces(NB_MAX); + EXPECT_TRUE(cmap_.check_map_integrity()); +} + /*! * \brief Adding faces preserves the cell indexation */ TEST_F(CMap1Test, add_face) { - unsigned int countVertices = addFaces(NB_MAX); + unsigned int count_vertices = add_faces(NB_MAX); - EXPECT_EQ(cmap_.nb_cells(), countVertices); + EXPECT_EQ(cmap_.nb_cells(), count_vertices); EXPECT_EQ(cmap_.nb_cells(), NB_MAX); EXPECT_TRUE(cmap_.check_map_integrity()); } @@ -106,21 +117,22 @@ TEST_F(CMap1Test, add_face) */ TEST_F(CMap1Test, remove_face) { - unsigned int countVertices = addFaces(NB_MAX); - int countFaces = NB_MAX; + unsigned int count_vertices = add_faces(NB_MAX); + int count_faces = NB_MAX; for (Dart d: darts_) { - if (std::rand()%3 == 1) { + if (std::rand()%3 == 1) + { unsigned int k = cmap_.degree(d); cmap_.remove_face(d); - countVertices -= k; - --countFaces; + count_vertices -= k; + --count_faces; } } - EXPECT_EQ(cmap_.nb_cells(), countVertices); - EXPECT_EQ(cmap_.nb_cells(), countFaces); + EXPECT_EQ(cmap_.nb_cells(), count_vertices); + EXPECT_EQ(cmap_.nb_cells(), count_faces); EXPECT_TRUE(cmap_.check_map_integrity()); } @@ -129,15 +141,15 @@ TEST_F(CMap1Test, remove_face) */ TEST_F(CMap1Test, split_vertex) { - unsigned int countVertices = addFaces(NB_MAX); + unsigned int count_vertices = add_faces(NB_MAX); for (Dart d: darts_) { cmap_.split_vertex(d); - ++countVertices; + ++count_vertices; } - EXPECT_EQ(cmap_.nb_cells(), countVertices); + EXPECT_EQ(cmap_.nb_cells(), count_vertices); EXPECT_EQ(cmap_.nb_cells(), NB_MAX); EXPECT_TRUE(cmap_.check_map_integrity()); } @@ -147,19 +159,19 @@ TEST_F(CMap1Test, split_vertex) */ TEST_F(CMap1Test, remove_vertex) { - unsigned int countVertices = addFaces(NB_MAX); - unsigned int countFaces = NB_MAX; + unsigned int count_vertices = add_faces(NB_MAX); + unsigned int count_faces = NB_MAX; for (Dart d: darts_) { unsigned int k = cmap_.degree(Face(d)); cmap_.remove_vertex(Vertex(d)); - --countVertices; - if (k == 1) --countFaces; + --count_vertices; + if (k == 1) --count_faces; } - EXPECT_EQ(cmap_.nb_cells(), countVertices); - EXPECT_EQ(cmap_.nb_cells(), countFaces); + EXPECT_EQ(cmap_.nb_cells(), count_vertices); + EXPECT_EQ(cmap_.nb_cells(), count_faces); EXPECT_TRUE(cmap_.check_map_integrity()); } diff --git a/cgogn/core/tests/cmap/cmap1_topo_test.cpp b/cgogn/core/tests/cmap/cmap1_topo_test.cpp index 3e4b2bbe..b2301723 100644 --- a/cgogn/core/tests/cmap/cmap1_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_topo_test.cpp @@ -55,6 +55,7 @@ class CMap1TopoTest : public CMap1, public ::testing::Test CMap1TopoTest() { + darts_.reserve(NB_MAX); std::srand(static_cast(std::time(0))); } @@ -62,8 +63,9 @@ class CMap1TopoTest : public CMap1, public ::testing::Test * \brief Initialize the darts in darts_ with added vertices * \param n : the number of added darts or vertices */ - void addVertices(unsigned int n) + void add_vertices(unsigned int n) { + darts_.clear(); for (unsigned int i = 0; i < n; ++i) darts_.push_back(add_dart()); } @@ -74,8 +76,9 @@ class CMap1TopoTest : public CMap1, public ::testing::Test * The face size ranges from 1 to 10. * A random dart of each face is put in the darts_ array. */ - unsigned int addFaces(unsigned int n) + unsigned int add_faces(unsigned int n) { + darts_.clear(); unsigned int count = 0; for (unsigned int i = 0; i < n; ++i) { @@ -93,13 +96,17 @@ class CMap1TopoTest : public CMap1, public ::testing::Test }; /*! - * \brief An empty CMap1 contains no dart, no vertex and no face. + * \brief The random generated maps used in the tests are sound. */ -TEST_F(CMap1TopoTest, Constructor) +TEST_F(CMap1TopoTest, random_map_generators) { EXPECT_EQ(nb_darts(), 0u); - EXPECT_EQ(this->template nb_cells(), 0u); - EXPECT_EQ(this->template nb_cells(), 0u); + + add_vertices(NB_MAX); + EXPECT_TRUE(check_map_integrity()); + + add_faces(NB_MAX); + EXPECT_TRUE(check_map_integrity()); } /*! @@ -109,10 +116,11 @@ TEST_F(CMap1TopoTest, Constructor) */ TEST_F(CMap1TopoTest, phi1_sew_unsew) { - addVertices(NB_MAX); - int countFaces = NB_MAX; + add_vertices(NB_MAX); + int count_faces = NB_MAX; - for (unsigned int i = 0; i < NB_MAX; ++i) { + for (unsigned int i = 0; i < NB_MAX; ++i) + { Dart d = darts_[std::rand() % NB_MAX]; Dart e = darts_[std::rand() % NB_MAX]; Dart f = darts_[std::rand() % NB_MAX]; @@ -127,7 +135,6 @@ TEST_F(CMap1TopoTest, phi1_sew_unsew) EXPECT_TRUE(phi1(nf1) == nf1); EXPECT_TRUE(phi1(f) == nf2); } - EXPECT_TRUE(check_map_integrity()); } @@ -148,10 +155,10 @@ TEST_F(CMap1TopoTest, add_face_topo) EXPECT_EQ(nb_cells(), 11); EXPECT_EQ(nb_cells(), 2); - unsigned int countVertices = 11 + addFaces(NB_MAX); + unsigned int count_vertices = 11 + add_faces(NB_MAX); - EXPECT_EQ(nb_darts(), countVertices); - EXPECT_EQ(nb_cells(), countVertices); + EXPECT_EQ(nb_darts(), count_vertices); + EXPECT_EQ(nb_cells(), count_vertices); EXPECT_EQ(nb_cells(), NB_MAX+2); EXPECT_TRUE(check_map_integrity()); } @@ -162,22 +169,22 @@ TEST_F(CMap1TopoTest, add_face_topo) */ TEST_F(CMap1TopoTest, remove_face) { - unsigned int countVertices = addFaces(NB_MAX); - unsigned int countFaces = NB_MAX; + unsigned int count_vertices = add_faces(NB_MAX); + unsigned int count_faces = NB_MAX; for (Dart d: darts_) { - if (std::rand()%3 == 1) { + if (std::rand()%3 == 1) + { unsigned int k = degree(Face(d)); remove_face(d); - countVertices -= k; - --countFaces; + count_vertices -= k; + --count_faces; } } - - EXPECT_EQ(nb_darts(), countVertices); - EXPECT_EQ(nb_cells(), countVertices); - EXPECT_EQ(nb_cells(), countFaces); + EXPECT_EQ(nb_darts(), count_vertices); + EXPECT_EQ(nb_cells(), count_vertices); + EXPECT_EQ(nb_cells(), count_faces); EXPECT_TRUE(check_map_integrity()); } @@ -187,18 +194,17 @@ TEST_F(CMap1TopoTest, remove_face) */ TEST_F(CMap1TopoTest, split_vertex_topo) { - unsigned int countVertices = addFaces(NB_MAX); + unsigned int count_vertices = add_faces(NB_MAX); for (Dart d: darts_) { unsigned int k = degree(Face(d)); split_vertex_topo(d); - ++countVertices; + ++count_vertices; EXPECT_EQ(degree(Face(d)), k+1); } - - EXPECT_EQ(nb_darts(), countVertices); - EXPECT_EQ(nb_cells(), countVertices); + EXPECT_EQ(nb_darts(), count_vertices); + EXPECT_EQ(nb_cells(), count_vertices); EXPECT_EQ(nb_cells(), NB_MAX); EXPECT_TRUE(check_map_integrity()); } @@ -209,28 +215,29 @@ TEST_F(CMap1TopoTest, split_vertex_topo) */ TEST_F(CMap1TopoTest, remove_vertex) { - unsigned int countVertices = addFaces(NB_MAX); - unsigned int countFaces = NB_MAX; + unsigned int count_vertices = add_faces(NB_MAX); + unsigned int count_faces = NB_MAX; for (Dart d: darts_) { unsigned int k = degree(Face(d)); - if (k > 1) { + if (k > 1) + { Dart e = phi1(d); remove_vertex(Vertex(d)); - --countVertices; + --count_vertices; EXPECT_EQ(degree(Face(e)), k-1); } - else { + else + { remove_vertex(Vertex(d)); - --countFaces; - --countVertices; + --count_faces; + --count_vertices; } } - - EXPECT_EQ(nb_darts(), countVertices); - EXPECT_EQ(nb_cells(), countVertices); - EXPECT_EQ(nb_cells(), countFaces); + EXPECT_EQ(nb_darts(), count_vertices); + EXPECT_EQ(nb_cells(), count_vertices); + EXPECT_EQ(nb_cells(), count_faces); EXPECT_TRUE(check_map_integrity()); } @@ -240,7 +247,7 @@ TEST_F(CMap1TopoTest, remove_vertex) */ TEST_F(CMap1TopoTest, reverse_face_topo) { - unsigned int countVertices = addFaces(NB_MAX); + unsigned int count_vertices = add_faces(NB_MAX); for (Dart d: darts_) { @@ -248,7 +255,8 @@ TEST_F(CMap1TopoTest, reverse_face_topo) std::vector face_darts; face_darts.reserve(k); - foreach_dart_of_orbit(Face(d), [&] (Dart e) { + foreach_dart_of_orbit(Face(d), [&] (Dart e) + { face_darts.push_back(e); }); @@ -256,15 +264,15 @@ TEST_F(CMap1TopoTest, reverse_face_topo) EXPECT_EQ(degree(Face(d)), k); d = phi1(d); - foreach_dart_of_orbit(Face(d), [&] (Dart e) { + foreach_dart_of_orbit(Face(d), [&] (Dart e) + { EXPECT_TRUE(face_darts.back() == e); face_darts.pop_back(); }); EXPECT_TRUE(face_darts.empty()); } - - EXPECT_EQ(nb_darts(), countVertices); - EXPECT_EQ(nb_cells(), countVertices); + EXPECT_EQ(nb_darts(), count_vertices); + EXPECT_EQ(nb_cells(), count_vertices); EXPECT_EQ(nb_cells(), NB_MAX); EXPECT_TRUE(check_map_integrity()); } diff --git a/cgogn/core/tests/cmap/cmap2_test.cpp b/cgogn/core/tests/cmap/cmap2_test.cpp index 6e96749b..399167b5 100644 --- a/cgogn/core/tests/cmap/cmap2_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_test.cpp @@ -63,6 +63,7 @@ class CMap2Test: public ::testing::Test CMap2Test() { + darts_.reserve(NB_MAX); std::srand(static_cast(std::time(0))); cmap_.add_attribute("darts"); @@ -78,8 +79,9 @@ class CMap2Test: public ::testing::Test * The face size ranges from 1 to 10. * A random dart of each face is put in the darts_ array. */ - unsigned int addFaces(unsigned int n) + unsigned int add_faces(unsigned int n) { + darts_.clear(); unsigned int count = 0u; for (unsigned int i = 0u; i < n; ++i) { @@ -98,8 +100,9 @@ class CMap2Test: public ::testing::Test /*! * \brief Generate a closed surface from the set of faces in darts_ */ - void makeSurface() + void add_closed_surface() { + darts_.clear(); MapBuilder mbuild(cmap_); unsigned int n = 0u; @@ -111,24 +114,22 @@ class CMap2Test: public ::testing::Test darts_.push_back(d); } // Sew some pairs off egdes - for (unsigned int i = 0; i < 3*NB_MAX; ++i) { + for (unsigned int i = 0u; i < 3u*NB_MAX; ++i) + { Dart e1 = darts_[std::rand() % NB_MAX]; n = std::rand()%10u; - while (n-- > 0u) e1 = cmap_.phi1(e1); + while (n-- > 0u) e1 = cmap_.phi1(e1); Dart e2 = darts_[std::rand() % NB_MAX]; n = std::rand()%10u; - while (n-- > 0u) e2 = cmap_.phi1(e2); + while (n-- > 0u) e2 = cmap_.phi1(e2); n = 1+std::rand()%3u; - while (n-- > 0u) { - if (cmap_.phi2(e1) == e1) { - if (cmap_.phi2(e2) == e2 && e2 != e1) { - mbuild.phi2_sew(e2, e1); - e1 = cmap_.phi1(e1); - e2 = cmap_.phi_1(e2); - } - } + while (n-- > 0u && cmap_.phi2(e1) == e1 && cmap_.phi2(e2) == e2 && e2 != e1) + { + mbuild.phi2_sew(e2, e1); + e1 = cmap_.phi1(e1); + e2 = cmap_.phi_1(e2); } } // Close the map (remove remaining boundary) @@ -139,30 +140,46 @@ class CMap2Test: public ::testing::Test cmap_.foreach_dart( [&] (Dart d) { mbuild.new_orbit_embedding(CDart(d)); }); - cmap_.foreach_cell( [&] (Vertex v) { + cmap_.foreach_cell( [&] (Vertex v) + { mbuild.new_orbit_embedding(v); }); - cmap_.foreach_cell( [&] (Edge e) { + cmap_.foreach_cell( [&] (Edge e) + { mbuild.new_orbit_embedding(e); }); - cmap_.foreach_cell( [&] (Face f) { + cmap_.foreach_cell( [&] (Face f) + { mbuild.new_orbit_embedding(f); }); - cmap_.foreach_cell( [&] (Volume w) { + cmap_.foreach_cell( [&] (Volume w) + { mbuild.new_orbit_embedding(w); }); } }; +/*! + * \brief The random generated maps used in the tests are sound. + */ +TEST_F(CMap2Test, random_map_generators) +{ + add_faces(NB_MAX); + EXPECT_TRUE(cmap_.check_map_integrity()); + + add_closed_surface(); + EXPECT_TRUE(cmap_.check_map_integrity()); +} + /*! * \brief Adding faces preserves the cell indexation */ TEST_F(CMap2Test, add_face) { - unsigned int countVertices = addFaces(NB_MAX); + unsigned int count_vertices = add_faces(NB_MAX); - EXPECT_EQ(cmap_.nb_cells(), countVertices); - EXPECT_EQ(cmap_.nb_cells(), countVertices); + EXPECT_EQ(cmap_.nb_cells(), count_vertices); + EXPECT_EQ(cmap_.nb_cells(), count_vertices); EXPECT_EQ(cmap_.nb_cells(), 2*NB_MAX); EXPECT_EQ(cmap_.nb_cells(), NB_MAX); EXPECT_TRUE(cmap_.check_map_integrity()); @@ -173,13 +190,35 @@ TEST_F(CMap2Test, add_face) */ TEST_F(CMap2Test, cut_edge) { - makeSurface(); + add_closed_surface(); for (Dart d: darts_) cmap_.cut_edge(d); EXPECT_TRUE(cmap_.check_map_integrity()); } +/*! + * \brief Cutting faces preserves the cell indexation + */ +TEST_F(CMap2Test, cut_face) +{ + add_closed_surface(); + + for (Dart d: darts_) + { + if (cmap_.degree(Face(d)) > 1u) + { + Dart e = d; // find a second dart in the face of d (distinct from d) + unsigned int i = std::rand() % 10u; + while (i-- > 0u) e = cmap_.phi1(e); + if (e == d) e = cmap_.phi1(e); + + cmap_.cut_face(d, e); + } + } + EXPECT_TRUE(cmap_.check_map_integrity()); +} + #undef NB_MAX } // namespace cgogn diff --git a/cgogn/core/tests/cmap/cmap2_topo_test.cpp b/cgogn/core/tests/cmap/cmap2_topo_test.cpp index beafc0f6..d1cfb700 100644 --- a/cgogn/core/tests/cmap/cmap2_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_topo_test.cpp @@ -61,6 +61,7 @@ class CMap2TopoTest: public CMap2, public ::testing::Test */ CMap2TopoTest() { + darts_.reserve(NB_MAX); std::srand(static_cast(std::time(0))); } @@ -70,8 +71,9 @@ class CMap2TopoTest: public CMap2, public ::testing::Test * The face size ranges from 1 to 10. * A random dart of each face is put in the darts_ array. */ - unsigned int addFaces(unsigned int n) + unsigned int add_faces(unsigned int n) { + darts_.clear(); unsigned int count = 0u; for (unsigned int i = 0u; i < n; ++i) { @@ -88,10 +90,11 @@ class CMap2TopoTest: public CMap2, public ::testing::Test } /*! - * \brief Generate a closed surface from the set of faces in darts_ + * \brief Generate an open surface */ - void makeSurface() + void add_open_surface() { + darts_.clear(); unsigned int n = 0u; // Generate NB_MAX random 1-faces (without boundary) @@ -102,43 +105,50 @@ class CMap2TopoTest: public CMap2, public ::testing::Test darts_.push_back(d); } // Sew some pairs off 1-egdes - for (unsigned int i = 0u; i < 3*NB_MAX; ++i) { + for (unsigned int i = 0u; i < 3*NB_MAX; ++i) + { Dart e1 = darts_[std::rand() % NB_MAX]; n = std::rand() % 10u; - while (n-- > 0u) e1 = phi1(e1); + while (n-- > 0u) e1 = phi1(e1); Dart e2 = darts_[std::rand() % NB_MAX]; n = std::rand() % 10u; - while (n-- > 0u) e2 = phi1(e2); + while (n-- > 0u) e2 = phi1(e2); n = 1+std::rand()%3u; - while (n-- > 0u) { - if (phi2(e1) == e1) { - if (phi2(e2) == e2 && e2 != e1) { - phi2_sew(e2, e1); - e1 = phi1(e1); - e2 = phi_1(e2); - } - } + while (n-- > 0u && phi2(e1) == e1 && phi2(e2) == e2 && e2 != e1) + { + phi2_sew(e2, e1); + e1 = phi1(e1); + e2 = phi_1(e2); } } - // Close the map (remove remaining boundary) - foreach_dart( [&] (Dart d) { + } + + /*! + * \brief Generate a closed surface + */ + void add_closed_surface() { + add_open_surface(); + foreach_dart( [&] (Dart d) + { if (phi2(d) == d) close_hole_topo(d); }); } }; /*! - * \brief An empty CMap2 contains no dart and no cells. + * \brief The random generated maps used in the tests are sound. */ -TEST_F(CMap2TopoTest, Constructor) +TEST_F(CMap2TopoTest, random_map_generators) { EXPECT_EQ(nb_darts(), 0u); - EXPECT_EQ(this->template nb_cells(), 0u); - EXPECT_EQ(this->template nb_cells(), 0u); - EXPECT_EQ(this->template nb_cells(), 0u); - EXPECT_EQ(this->template nb_cells(), 0u); + + add_faces(NB_MAX); + EXPECT_TRUE(check_map_integrity()); + + add_closed_surface(); + EXPECT_TRUE(check_map_integrity()); } /*! @@ -148,11 +158,12 @@ TEST_F(CMap2TopoTest, Constructor) */ TEST_F(CMap2TopoTest, phi2_sew_unsew) { - unsigned int countVertices = addFaces(NB_MAX); - unsigned int countFaces = NB_MAX; - unsigned int countVolumes = NB_MAX; + unsigned int count_vertices = add_faces(NB_MAX); + unsigned int count_faces = NB_MAX; + unsigned int count_volumes = NB_MAX; - for (unsigned int i = 0u; i < NB_MAX; ++i) { + for (unsigned int i = 0u; i < NB_MAX; ++i) + { Dart d0 = darts_[std::rand() % NB_MAX]; Dart d2 = phi2(d0); phi2_unsew(d0); @@ -189,11 +200,11 @@ TEST_F(CMap2TopoTest, add_face_topo) EXPECT_EQ(nb_cells(), 4u); EXPECT_EQ(nb_cells(), 2u); - unsigned int countVertices = 11u + addFaces(NB_MAX); + unsigned int count_vertices = 11u + add_faces(NB_MAX); - EXPECT_EQ(nb_darts(), 2u*countVertices); - EXPECT_EQ(nb_cells(), countVertices); - EXPECT_EQ(nb_cells(), countVertices); + EXPECT_EQ(nb_darts(), 2u*count_vertices); + EXPECT_EQ(nb_cells(), count_vertices); + EXPECT_EQ(nb_cells(), count_vertices); EXPECT_EQ(nb_cells(), 2u*(NB_MAX+2u)); EXPECT_EQ(nb_cells(), NB_MAX+2u); EXPECT_TRUE(check_map_integrity()); @@ -203,14 +214,14 @@ TEST_F(CMap2TopoTest, add_face_topo) * The test performs NB_MAX edge cutting on edges of randomly generated faces. * The number of generated cells is correct and the map integrity is preserved. */ -TEST_F(CMap2TopoTest, testCutEdge) +TEST_F(CMap2TopoTest, cut_edge_topo) { - makeSurface(); + add_closed_surface(); - unsigned int countVertices = nb_cells(); - unsigned int countEdges = nb_cells(); - unsigned int countFaces = nb_cells(); - unsigned int countVolumes = nb_cells(); + unsigned int count_vertices = nb_cells(); + unsigned int count_edges = nb_cells(); + unsigned int count_faces = nb_cells(); + unsigned int count_volumes = nb_cells(); for (Dart d: darts_) { @@ -227,45 +238,72 @@ TEST_F(CMap2TopoTest, testCutEdge) EXPECT_EQ(degree(Face(phi2(d))), k2+1u); } } - - EXPECT_EQ(this->template nb_cells(), countVertices+NB_MAX); - EXPECT_EQ(this->template nb_cells(), countEdges+NB_MAX); - EXPECT_EQ(this->template nb_cells(), countFaces); - EXPECT_EQ(this->template nb_cells(), countVolumes); + EXPECT_EQ(nb_cells(), count_vertices+NB_MAX); + EXPECT_EQ(nb_cells(), count_edges+NB_MAX); + EXPECT_EQ(nb_cells(), count_faces); + EXPECT_EQ(nb_cells(), count_volumes); EXPECT_TRUE(check_map_integrity()); } -TEST_F(CMap2TopoTest, testCutFace) +/*! \brief Cutting a face add an edge and replace a face of degree K, + * with two subfaces whose degrees K1 and K2 verify K1+K2 = K+2. + * The test performs NB_MAX face cuts between vertices of a randomly generated surface. + * The number of generated cells is correct and the map integrity is preserved. + */ +TEST_F(CMap2TopoTest, cut_face_topo) { - int n = addFaces(NB_MAX); - - int countEdges = n; - int countFaces = 2*NB_MAX; + add_closed_surface(); - for (int i = 0; i < NB_MAX; ++i) { - Dart d = darts_[i]; - Dart e = d; - unsigned int j = std::rand() % 10; - while (j-- > 0) e = phi1(e); - if (e == d) e = phi1(e); + unsigned int count_vertices = nb_cells(); + unsigned int count_edges = nb_cells(); + unsigned int count_faces = nb_cells(); + unsigned int count_volumes = nb_cells(); + for (Dart d: darts_) + { unsigned int k = degree(Face(d)); - if (k>1) { + if (k>1u) + { + Dart e = d; // find a second dart in the face of d (distinct from d) + unsigned int i = std::rand() % 10u; + while (i-- > 0u) e = phi1(e); + if (e == d) e = phi1(e); + cut_face_topo(d, e); - ++countEdges; - ++countFaces; + ++count_edges; + ++count_faces; EXPECT_EQ(degree(Face(d))+degree(Face(e)), k+2); } } + EXPECT_EQ(nb_cells(), count_vertices); + EXPECT_EQ(nb_cells(), count_edges); + EXPECT_EQ(nb_cells(), count_faces); + EXPECT_EQ(nb_cells(), count_volumes); + EXPECT_TRUE(check_map_integrity()); +} + +/*! \brief Closing a map add one face per holes. + * The test closes the holes of a randomly generated open surface. + * The number of generated cells is correct and the map integrity is preserved. + * And closing a map soundly complete the cell indexation + */ +TEST_F(CMap2TopoTest, close_map) +{ + add_open_surface(); + + // add attributes +// add_attribute("darts"); +// add_attribute("vertices"); +// add_attribute("edges"); +// add_attribute("faces"); +// add_attribute("volumes"); +// EXPECT_TRUE(check_map_integrity()); - EXPECT_EQ(this->template nb_cells(), n); - EXPECT_EQ(this->template nb_cells(), countEdges); - EXPECT_EQ(this->template nb_cells(), countFaces); - EXPECT_EQ(this->template nb_cells(), NB_MAX); + close_map(); EXPECT_TRUE(check_map_integrity()); } -TEST_F(CMap2TopoTest, testFaceDegree) +TEST_F(CMap2TopoTest, degree) { Face f = this->add_face_topo(10); From 11e687ee4a4bc139615a5288a2a12727b97ca67a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Mon, 7 Mar 2016 19:18:08 +0100 Subject: [PATCH 268/402] testing zlib decompression of vtk xml meshes. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/CMakeLists.txt | 6 +++- cgogn/io/io_utils.cpp | 80 ++++++++++++++++++++++++++++++++++++++++- cgogn/io/io_utils.h | 9 +++-- cgogn/io/vtk_io.h | 41 +++++++++++---------- 4 files changed, 110 insertions(+), 26 deletions(-) diff --git a/cgogn/io/CMakeLists.txt b/cgogn/io/CMakeLists.txt index f35e8dd8..cd18574d 100644 --- a/cgogn/io/CMakeLists.txt +++ b/cgogn/io/CMakeLists.txt @@ -2,6 +2,9 @@ project(cgogn_io LANGUAGES CXX ) +find_package(ZLIB) +add_definitions("-DZLIB_CONST") + set(HEADER_FILES surface_import.h volume_import.h @@ -36,10 +39,11 @@ target_include_directories(${PROJECT_NAME} PUBLIC $ $ $ + $ $ ) -target_link_libraries(${PROJECT_NAME} tinyxml2 cgogn_core cgogn_geometry ply) +target_link_libraries(${PROJECT_NAME} tinyxml2 cgogn_core cgogn_geometry ply ${ZLIB_LIBRARIES}) install(DIRECTORY . DESTINATION include/cgogn/io diff --git a/cgogn/io/io_utils.cpp b/cgogn/io/io_utils.cpp index 2ce85028..878c8fb1 100644 --- a/cgogn/io/io_utils.cpp +++ b/cgogn/io/io_utils.cpp @@ -26,6 +26,8 @@ #include #include +#include + #include #include @@ -35,12 +37,88 @@ namespace cgogn namespace io { -CGOGN_IO_API std::vector base64_decode(std::string& input) +CGOGN_IO_API void zlib_decompress(std::string& input, DataType header_type) { input.erase(std::remove(input.begin(), input.end(), ' '), input.end()); input.erase(std::remove(input.begin(), input.end(), '\n'), input.end()); input.erase(std::remove(input.begin(), input.end(), '\t'), input.end()); + std::uint64_t nb_blocks = UINT64_MAX; + std::uint64_t uncompressed_block_size = UINT64_MAX; + std::uint64_t last_block_size = UINT64_MAX; + std::vector compressed_size; + + unsigned int word_size = 4u; + std::string header; + std::vector header_data; + if (header_type == DataType::UINT64) + { + word_size = 8u; + // we read the first 3 uint64 + header = input.substr(0, 24); + header_data = base64_decode(header); + nb_blocks = *reinterpret_cast(&header_data[0]); + uncompressed_block_size = *reinterpret_cast(&header_data[8]); + last_block_size = *reinterpret_cast(&header_data[16]); + compressed_size.resize(nb_blocks); + } else + { + header = input.substr(0, 12); + header_data = base64_decode(header); + nb_blocks = *reinterpret_cast(&header_data[0]); + uncompressed_block_size = *reinterpret_cast(&header_data[4]); + last_block_size = *reinterpret_cast(&header_data[8]); + compressed_size.resize(nb_blocks); + } + + std::size_t header_end = 4ul *word_size; +std:size_t length = nb_blocks* word_size *4ul; + while ((length % 12ul != 0ul)) + ++length; + length/=3ul; + header = input.substr(header_end, length); + header_data = base64_decode(header); + if (header_type == DataType::UINT64) + { + for (unsigned int i = 0; i < nb_blocks; ++i) + compressed_size[i] = *reinterpret_cast(&header_data[8u*i]); + } else + { + for (unsigned int i = 0; i < nb_blocks; ++i) + compressed_size[i] = *reinterpret_cast(&header_data[4u*i]); + } + + std::string data_str(input.substr(header_end +length, std::string::npos)); + + std::vector data = base64_decode(data_str); + std::vector res; + res.resize(uncompressed_block_size*(nb_blocks-1u) + last_block_size); + + // zlib init + int ret; + z_stream zstream; + zstream.zalloc = Z_NULL; + zstream.zfree = Z_NULL; + zstream.opaque = Z_NULL; + unsigned int in_data_it = 0u; + unsigned int out_data_it = 0u; + for (unsigned int i = 0; i < nb_blocks; ++i) + { + ret = inflateInit(&zstream); + zstream.avail_in = compressed_size[i]; + zstream.next_in = &data[in_data_it]; + zstream.avail_out = (i == nb_blocks -1u) ? last_block_size : uncompressed_block_size; + zstream.next_out = &res[out_data_it]; + ret = inflate(&zstream, Z_NO_FLUSH); + ret = inflateEnd(&zstream); + in_data_it += compressed_size[i]; + out_data_it+=uncompressed_block_size; + } + input = std::string(reinterpret_cast(&res[0]), res.size()); +} + +CGOGN_IO_API std::vector base64_decode(std::string& input) +{ const static char padCharacter('='); if (input.length() % 4) //Sanity check throw std::runtime_error("Non-Valid base64!"); diff --git a/cgogn/io/io_utils.h b/cgogn/io/io_utils.h index 3a8c0e80..39bd8337 100644 --- a/cgogn/io/io_utils.h +++ b/cgogn/io/io_utils.h @@ -37,8 +37,6 @@ namespace cgogn namespace io { -CGOGN_IO_API std::vector base64_decode(std::string& input); - enum FileType { FileType_UNKNOWN = 0, @@ -49,8 +47,6 @@ enum FileType FileType_VTU }; -CGOGN_IO_API FileType get_file_type(const std::string& filename); - enum DataType { CHAR = 0, @@ -66,8 +62,11 @@ enum DataType DOUBLE, UNKNOWN }; - +CGOGN_IO_API FileType get_file_type(const std::string& filename); CGOGN_IO_API DataType get_data_type(const std::string& type_name); +CGOGN_IO_API std::vector base64_decode(std::string& input); +CGOGN_IO_API void zlib_decompress(std::string& input, DataType header_type); + namespace internal { diff --git a/cgogn/io/vtk_io.h b/cgogn/io/vtk_io.h index b347b585..38c09dcf 100644 --- a/cgogn/io/vtk_io.h +++ b/cgogn/io/vtk_io.h @@ -32,14 +32,13 @@ #include #include + namespace cgogn { namespace io { -CGOGN_IO_API std::vector base64_decode(const std::basic_string& input); - template class VtkIO { @@ -95,6 +94,23 @@ protected : virtual void add_vertex_attribute(const DataInputGen& attribute_data, const std::string& attribute_name) = 0; virtual void add_cell_attribute(const DataInputGen& attribute_data, const std::string& attribute_name) = 0; + inline void read_binary_xml_data(std::string& data_str, bool is_compressed, DataType header_type) + { + if (!is_compressed) + { + std::vector decode = base64_decode(data_str); + std::size_t length = 0ul; + if (header_type == DataType::UINT32) + length = *reinterpret_cast(&decode[0]); + else + length = *reinterpret_cast(&decode[0]); + data_str = std::string(reinterpret_cast(&decode[header_type == DataType::UINT32 ? 4u : 8u]), length); + } + else { + zlib_decompress(data_str, header_type); + } + } + bool parse_vtk_legacy_file(std::ifstream& fp) { VTK_MESH_TYPE vtk_type(VTK_MESH_TYPE::UNKNOWN); @@ -317,8 +333,9 @@ protected : std::string header_type("unsigned int"); if (root_node->Attribute("header_type")) header_type = vtk_data_type_to_cgogn_name_of_type(root_node->Attribute("header_type")); - const unsigned int header_size = (get_data_type(header_type) == DataType::UINT64)? 8u : 4u; +// const unsigned int header_size = (get_data_type(header_type) == DataType::UINT64)? 8u : 4u; + const bool compressed = (root_node->Attribute("compressor") && (std::string(root_node->Attribute("compressor")) == "vtkZLibDataCompressor")); XMLElement* grid_node = root_node->FirstChildElement("UnstructuredGrid"); cgogn_assert(grid_node != nullptr); @@ -362,13 +379,7 @@ protected : std::string text(vertex_data->GetText()); if (binary) { - std::vector decode = base64_decode(text); - unsigned int length = 0u; - if (header_size == 4u) - length = *reinterpret_cast(&decode[0]); - else - length = *reinterpret_cast(&decode[0]); - text = std::string(reinterpret_cast(&decode[header_size]), length); + this->read_binary_xml_data(text,compressed, get_data_type(header_type)); } std::istringstream ss(text); @@ -427,15 +438,7 @@ protected : else { std::string text(cell_data->GetText()); if (binary) - { - std::vector decode = base64_decode(text); - unsigned int length = 0u; - if (header_size == 4u) - length = *reinterpret_cast(&decode[0]); - else - length = *reinterpret_cast(&decode[0]); - text = std::string(reinterpret_cast(&decode[header_size]), length); - } + this->read_binary_xml_data(text,compressed, get_data_type(header_type)); std::istringstream ss(text); if (data_name == "connectivity") From 6ca6749129f304c2b7588069b178d8cd99053993 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Tue, 8 Mar 2016 10:27:57 +0100 Subject: [PATCH 269/402] begin of picking --- cgogn/geometry/CMakeLists.txt | 3 + cgogn/geometry/algos/picking.h | 103 ++++++++ cgogn/geometry/functions/distance.h | 76 ++++++ cgogn/geometry/functions/intersection.h | 100 ++++++++ cgogn/geometry/tests/CMakeLists.txt | 2 + .../tests/functions/distance_test.cpp | 65 +++++ .../tests/functions/intersection_test.cpp | 67 ++++++ cgogn/rendering/examples/CMakeLists.txt | 2 + cgogn/rendering/examples/picking_viewer.cpp | 226 ++++++++++++++++++ 9 files changed, 644 insertions(+) create mode 100644 cgogn/geometry/algos/picking.h create mode 100644 cgogn/geometry/functions/distance.h create mode 100644 cgogn/geometry/functions/intersection.h create mode 100644 cgogn/geometry/tests/functions/distance_test.cpp create mode 100644 cgogn/geometry/tests/functions/intersection_test.cpp create mode 100644 cgogn/rendering/examples/picking_viewer.cpp diff --git a/cgogn/geometry/CMakeLists.txt b/cgogn/geometry/CMakeLists.txt index de5d3707..2b3c6f67 100644 --- a/cgogn/geometry/CMakeLists.txt +++ b/cgogn/geometry/CMakeLists.txt @@ -9,10 +9,13 @@ set(HEADER_FILES algos/centroid.h algos/normal.h algos/ear_triangulation.h + algos/picking.h functions/area.h functions/normal.h functions/orientation.h functions/inclusion.h + functions/intersection.h + functions/distance.h types/bounding_box.h types/eigen.h types/geometry_traits.h diff --git a/cgogn/geometry/algos/picking.h b/cgogn/geometry/algos/picking.h new file mode 100644 index 00000000..442e6dbf --- /dev/null +++ b/cgogn/geometry/algos/picking.h @@ -0,0 +1,103 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef GEOMETRY_ALGOS_PICKING_H_ +#define GEOMETRY_ALGOS_PICKING_H_ + +#include +#include + +#include +#include +#include +#include +#include + +namespace cgogn +{ + +namespace geometry +{ + +//template +//inline void picking_vertices(MAP& map, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename VEC3::Scalar dist, typename std::vector selected) +//{ +// VEC3 AB = B - A ; +// cgogn_message_assert(AB.squaredNorm()>0.0,"line must be defined by 2 different points"); +// AB.normalize(); + +// selected.clear(); +// map.foreach_cell([&] (typename MAP::Vertex v) +// { +// if(squared_distance_normalized_line_point(A,AB,position[v])< dist*dist) +// selected.push_back(v); +// }); +//} + +template +inline void picking_face(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector selected) +{ + using Vertex = typename MAP::Vertex; + using Face = typename MAP::Face; + VEC3 AB = B - A ; + cgogn_message_assert(AB.squaredNorm()>0.0,"line must be defined by 2 different points"); + AB.normalize(); + + selected.clear(); + std::vector ear_indices; + ear_indices.reserve(256); + + m.foreach_cell([&] (Face f) + { + if (m.has_degree(f,3)) + { + const VEC3& p1 = position[Vertex(f.dart)]; + const VEC3& p2 = position[Vertex(m.phi1(f.dart))]; + const VEC3& p3 = position[Vertex(m.phi1(m.phi1(f.dart)))]; + if (intersection_ray_triangle(A,AB,p1,p2,p3)) + selected.push_back(f); + } + else + { + cgogn::geometry::compute_ear_triangulation(m,f,position,ear_indices); + for(unsigned int i=0; i(A,AB,p1,p2,p3)) + { + selected.push_back(f); + i = ear_indices.size(); + } + } + } + }); +} + + +} // namespace geometry + +} // namespace cgogn + +#endif // GEOMETRY_ALGOS_PICKING_H_ diff --git a/cgogn/geometry/functions/distance.h b/cgogn/geometry/functions/distance.h new file mode 100644 index 00000000..7981b745 --- /dev/null +++ b/cgogn/geometry/functions/distance.h @@ -0,0 +1,76 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef GEOMETRY_FUNCTIONS_DISTANCE_H_ +#define GEOMETRY_FUNCTIONS_DISTANCE_H_ + +#include + +namespace cgogn +{ + +namespace geometry +{ + + +/** + * @brief squared distance line point (optimized version for testing many points with the same line + * @param A one point of line + * @param AB normalized vector or line + * @param P point o compute distance to line + * @return distance + */ +template +inline typename VEC3_T::Scalar squared_distance_normalized_line_point(const VEC3_T& A, const VEC3_T& AB_norm, const VEC3_T& P) +{ + VEC3_T V = A - P ; + VEC3_T W = V.cross(AB_norm) ; + return W.squaredNorm() ; +} + +/** + * @brief squared distance line point + * @param A one point of line + * @param B second point of line + * @param P point o compute distance to line + * @return distance + */ +template +inline typename VEC3_T::Scalar squared_distance_line_point(const VEC3_T& A, const VEC3_T& B, const VEC3_T& P) +{ + VEC3_T AB = B - A ; + cgogn_message_assert(AB.squaredNorm()>0.0,"line must be defined by 2 different points"); + AB.normalize(); + return squared_distance_normalized_line_point(A, AB, P) ; +} + + + + + + +} // namespace geometry + +} // namespace cgogn + +#endif // GEOMETRY_FUNCTIONS_DISTANCE_H_ diff --git a/cgogn/geometry/functions/intersection.h b/cgogn/geometry/functions/intersection.h new file mode 100644 index 00000000..e5678cf6 --- /dev/null +++ b/cgogn/geometry/functions/intersection.h @@ -0,0 +1,100 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef GEOMETRY_FUNCTIONS_INTERSECTION_H_ +#define GEOMETRY_FUNCTIONS_INTERSECTION_H_ + +namespace cgogn +{ + +namespace geometry +{ + + +enum Intersection +{ + NO_INTERSECTION = 0, + VERTEX_INTERSECTION = 1, + EDGE_INTERSECTION = 2, + FACE_INTERSECTION = 3 +}; + +template +Intersection intersection_ray_triangle(const VEC3_T& P, const VEC3_T& Dir, const VEC3_T& Ta, const VEC3_T& Tb, const VEC3_T& Tc, VEC3_T* inter=nullptr) +{ + using Scalar = typename VEC3_T::Scalar; + + VEC3_T u = Ta - P ; + VEC3_T v = Tb - P ; + VEC3_T w = Tc - P ; + + Scalar x = Dir.dot(u.cross(v));//tripleProduct(Dir, u, v) ; + Scalar y = Dir.dot(v.cross(w));//tripleProduct(Dir, v, w) ; + Scalar z = Dir.dot(w.cross(u));//tripleProduct(Dir, w, u) ; + + unsigned int np = 0 ; + unsigned int nn = 0 ; + unsigned int nz = 0 ; + + if (x >Scalar(0)) + ++np ; + else if (x Scalar(0)) + ++np ; + else if (y Scalar(0)) + ++np ; + else if (z +#include +#include +#include +#include + +#include + +using StdArrayf = cgogn::geometry::Vec_T>; +using StdArrayd = cgogn::geometry::Vec_T>; +using EigenVec3f = Eigen::Vector3f; +using EigenVec3d = Eigen::Vector3d; +using VecTypes = testing::Types; + +template +class Distance_TEST : public testing::Test +{}; + +TYPED_TEST_CASE(Distance_TEST, VecTypes ); + + +TYPED_TEST(Distance_TEST, PointLineDistance) +{ + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + TypeParam A(Scalar(-4), Scalar(-4), Scalar(-4)); + TypeParam B(Scalar(3), Scalar(3), Scalar(3)); + + TypeParam P0(Scalar(1), Scalar(1), Scalar(1)); + TypeParam P1(Scalar(20), Scalar(20), Scalar(20)); + TypeParam P2(Scalar(1), Scalar(1), Scalar(0)); + + EXPECT_DOUBLE_EQ(cgogn::geometry::squared_distance_line_point(A,B,P0), Scalar(0)); + EXPECT_DOUBLE_EQ(cgogn::geometry::squared_distance_line_point(A,B,P1), Scalar(0)); + +// EXPECT_TRUE(cgogn::almost_equal_relative(cgogn::geometry::squared_distance_line_point(A,B,P2), Scalar(2.0/3.0))); + + const Scalar tolerence = std::is_same::value ? Scalar(1e-8) : Scalar(1e-4f); +EXPECT_NEAR(cgogn::geometry::squared_distance_line_point(A,B,P2), Scalar(2.0/3.0), tolerence); + + + +} diff --git a/cgogn/geometry/tests/functions/intersection_test.cpp b/cgogn/geometry/tests/functions/intersection_test.cpp new file mode 100644 index 00000000..9f2d3457 --- /dev/null +++ b/cgogn/geometry/tests/functions/intersection_test.cpp @@ -0,0 +1,67 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#include +#include +#include +#include + +#include + +using StdArrayf = cgogn::geometry::Vec_T>; +using StdArrayd = cgogn::geometry::Vec_T>; +using EigenVec3f = Eigen::Vector3f; +using EigenVec3d = Eigen::Vector3d; +using VecTypes = testing::Types; + +template +class Intesection_TEST : public testing::Test +{ +}; + + +TYPED_TEST_CASE(Intesection_TEST, VecTypes ); + +TYPED_TEST(Intesection_TEST, IntersectionLineTriangle) +{ + using Scalar = typename cgogn::geometry::vector_traits::Scalar; + TypeParam p0(Scalar(1), Scalar(1), Scalar(6.1)); + TypeParam p1(Scalar(5), Scalar(1), Scalar(6.3)); + TypeParam p2(Scalar(3), Scalar(5), Scalar(6.2)); + + TypeParam A0(Scalar(3), Scalar(3), Scalar(0)); + TypeParam D0(Scalar(0.001), Scalar(0.001), Scalar(1.0)); + + TypeParam A1(Scalar(3), Scalar(1), Scalar(0)); + TypeParam D1(Scalar(0), Scalar(0), Scalar(1.0)); + TypeParam A2(Scalar(5), Scalar(1), Scalar(0)); + TypeParam A3(Scalar(9), Scalar(5), Scalar(0)); + + EXPECT_TRUE(cgogn::geometry::intersection_ray_triangle(A0,D0,p0,p1,p2) == cgogn::geometry::FACE_INTERSECTION); + EXPECT_TRUE(cgogn::geometry::intersection_ray_triangle(A1,D1,p0,p1,p2) == cgogn::geometry::EDGE_INTERSECTION); + EXPECT_TRUE(cgogn::geometry::intersection_ray_triangle(A2,D1,p0,p1,p2) == cgogn::geometry::VERTEX_INTERSECTION); + EXPECT_TRUE(cgogn::geometry::intersection_ray_triangle(A3,D0,p0,p1,p2) == cgogn::geometry::NO_INTERSECTION); + + +// EXPECT_DOUBLE_EQ(cgogn::geometry::intersection_ray_triangle(p0,p1,p2), Scalar(2)); +} diff --git a/cgogn/rendering/examples/CMakeLists.txt b/cgogn/rendering/examples/CMakeLists.txt index 8e4a85d2..4bf634b3 100644 --- a/cgogn/rendering/examples/CMakeLists.txt +++ b/cgogn/rendering/examples/CMakeLists.txt @@ -16,6 +16,8 @@ add_executable(simple_viewer simple_viewer.cpp) target_link_libraries(simple_viewer cgogn_core cgogn_io cgogn_rendering QOGLViewer) +add_executable(picking_viewer picking_viewer.cpp) +target_link_libraries(picking_viewer cgogn_core cgogn_io cgogn_rendering QOGLViewer) diff --git a/cgogn/rendering/examples/picking_viewer.cpp b/cgogn/rendering/examples/picking_viewer.cpp new file mode 100644 index 00000000..3a61d4c0 --- /dev/null +++ b/cgogn/rendering/examples/picking_viewer.cpp @@ -0,0 +1,226 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#include +#include + +#include +#include + +#include + +#include + +#include + +#include +#include +#include + + +#include + +#define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) + +using Map2 = cgogn::CMap2; +using Vec3 = Eigen::Vector3d; +//using Vec3 = cgogn::geometry::Vec_T>; + +template +using VertexAttributeHandler = Map2::VertexAttributeHandler; + + +class Viewer : public QOGLViewer +{ +public: + Viewer(); + Viewer(const Viewer&) = delete; + Viewer& operator=(const Viewer&) = delete; + + virtual void draw(); + virtual void init(); + virtual void mousePressEvent(QMouseEvent *e); + virtual void resizeGL(int w, int h); + + void import(const std::string& surfaceMesh); + + virtual ~Viewer(); + + + +private: + QRect viewport_; + QMatrix4x4 proj_; + QMatrix4x4 view_; + + Map2 map_; + VertexAttributeHandler vertex_position_; + + cgogn::geometry::BoundingBox bb_; + + cgogn::rendering::MapRender* render_; + + cgogn::rendering::VBO* vbo_pos_; + + cgogn::rendering::ShaderFlat* shader2_; + +}; + + +// +// IMPLEMENTATION +// + + +void Viewer::import(const std::string& surfaceMesh) +{ + cgogn::io::import_surface(map_, surfaceMesh); + + vertex_position_ = map_.get_attribute("position"); + + cgogn::geometry::compute_bounding_box(vertex_position_, bb_); + + setSceneRadius(bb_.diag_size()); + Vec3 center = bb_.center(); + setSceneCenter(qoglviewer::Vec(center[0], center[1], center[2])); + showEntireScene(); +} + +Viewer::~Viewer() +{ + delete render_; + delete vbo_pos_; + delete shader2_; +} + +Viewer::Viewer() : + map_(), + vertex_position_(), + bb_(), + render_(nullptr), + vbo_pos_(nullptr), + shader2_(nullptr) +{} + +void Viewer::draw() +{ +// QMatrix4x4 proj; +// QMatrix4x4 view; + camera()->getProjectionMatrix(proj_); + camera()->getModelViewMatrix(view_); + + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1.0f, 1.0f); + + shader2_->bind(); + shader2_->set_matrices(proj_,view_); + shader2_->bind_vao(0); + render_->draw(cgogn::rendering::TRIANGLES); + shader2_->release_vao(0); + shader2_->release(); +} + +void Viewer::init() +{ + glClearColor(0.1f,0.1f,0.3f,0.0f); + + vbo_pos_ = new cgogn::rendering::VBO; + cgogn::rendering::update_vbo(vertex_position_, *vbo_pos_); + render_ = new cgogn::rendering::MapRender(); + + render_->init_primitives(map_, cgogn::rendering::TRIANGLES, vertex_position_); + + shader2_ = new cgogn::rendering::ShaderFlat; + shader2_->add_vao(); + shader2_->set_vao(0, vbo_pos_); + + shader2_->bind(); + shader2_->set_front_color(QColor(0,200,0)); + shader2_->set_back_color(QColor(0,0,200)); + shader2_->set_ambiant_color(QColor(5,5,5)); + shader2_->release(); +} + +void Viewer::mousePressEvent(QMouseEvent* event) +{ + +// camera()->getProjectionMatrix(proj_); +// camera()->getModelViewMatrix(view_); + + + unsigned int x = event->x()*devicePixelRatio(); + unsigned int y = this->height() - event->y()*devicePixelRatio(); + QVector3D wp(x,y,0); + QVector3D wq(x,y,0.99); + QVector3D P = wp.unproject(view_,proj_,viewport_); + QVector3D Q = wq.unproject(view_,proj_,viewport_); + + Vec3 A(P[0],P[1],P[2]); + Vec3 B(Q[0],Q[1],Q[2]); + + + +// std::cout< selected; + cgogn::geometry::picking_face(map_,vertex_position_,A,B,selected); + + std::cout << selected.size()<< std::endl; + + + + QOGLViewer::mousePressEvent(event); +} + +void Viewer::resizeGL(int w, int h) +{ + int vp[4]; + glGetIntegerv(GL_VIEWPORT, vp); + viewport_= QRect(vp[0],vp[1],vp[2],vp[3]); + std::cout << "viewport"<< std::endl; +} + +int main(int argc, char** argv) +{ + std::string surfaceMesh; + if (argc < 2) + { + std::cout << "USAGE: " << argv[0] << " [filename]" << std::endl; + surfaceMesh = std::string(DEFAULT_MESH_PATH) + std::string("aneurysm3D_1.off"); + std::cout << "Using default mesh : " << surfaceMesh << std::endl; + } + else + surfaceMesh = std::string(argv[1]); + + QApplication application(argc, argv); + qoglviewer::init_ogl_context(); + + // Instantiate the viewer. + Viewer viewer; + viewer.setWindowTitle("simpleViewer"); + viewer.import(surfaceMesh); + viewer.show(); + + // Run main loop. + return application.exec(); +} From 1f3a7949f3ea7958dbd854bd7ff14f77c1d0ee35 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Tue, 8 Mar 2016 11:00:40 +0100 Subject: [PATCH 270/402] snake case --- cgogn/rendering/drawer.cpp | 2 +- cgogn/rendering/drawer.h | 10 +- cgogn/rendering/examples/drawing.cpp | 14 +- cgogn/rendering/examples/simple_viewer.cpp | 8 +- cgogn/rendering/examples/viewer_topo.cpp | 2 +- cgogn/rendering/map_render.h | 4 +- cgogn/rendering/map_render.h.orig | 196 ------------------ .../rendering/shaders/shader_point_sprite.cpp | 26 +-- 8 files changed, 33 insertions(+), 229 deletions(-) delete mode 100644 cgogn/rendering/map_render.h.orig diff --git a/cgogn/rendering/drawer.cpp b/cgogn/rendering/drawer.cpp index df1acf92..62d137f5 100644 --- a/cgogn/rendering/drawer.cpp +++ b/cgogn/rendering/drawer.cpp @@ -190,7 +190,7 @@ void Drawer::end_list() data_col_.shrink_to_fit(); } -void Drawer::callList(const QMatrix4x4& projection, const QMatrix4x4& modelview) +void Drawer::call_list(const QMatrix4x4& projection, const QMatrix4x4& modelview) { //classic rendering diff --git a/cgogn/rendering/drawer.h b/cgogn/rendering/drawer.h index 8d8158eb..830603c3 100644 --- a/cgogn/rendering/drawer.h +++ b/cgogn/rendering/drawer.h @@ -170,18 +170,18 @@ class CGOGN_RENDERING_API Drawer * @param projection projection matrix * @param modelview modelview matrix */ - void callList(const QMatrix4x4& projection, const QMatrix4x4& modelview); + void call_list(const QMatrix4x4& projection, const QMatrix4x4& modelview); /** * usr as glPointSize */ - inline void pointSize(float ps) + inline void point_size(float ps) { current_aa_ = false; current_size_ = ps; } - inline void pointSizeAA(float ps) + inline void point_size_aa(float ps) { current_aa_ = true; current_size_ = ps; @@ -190,13 +190,13 @@ class CGOGN_RENDERING_API Drawer /** * usr as glLineWidth */ - inline void lineWidth(float lw) + inline void line_width(float lw) { current_aa_ = false; current_size_ = lw; } - inline void lineWidthAA(float lw) + inline void line_width_AA(float lw) { current_aa_ = true; current_size_ = 2.0*lw; diff --git a/cgogn/rendering/examples/drawing.cpp b/cgogn/rendering/examples/drawing.cpp index 5cdab8e1..b8cdb21b 100644 --- a/cgogn/rendering/examples/drawing.cpp +++ b/cgogn/rendering/examples/drawing.cpp @@ -75,8 +75,8 @@ void Drawing::draw() camera()->getProjectionMatrix(proj); camera()->getModelViewMatrix(view); - drawer_->callList(proj,view); - drawer2_->callList(proj,view); + drawer_->call_list(proj,view); + drawer2_->call_list(proj,view); } void Drawing::init() @@ -90,7 +90,7 @@ void Drawing::init() // drawer for simple old-school g1 rendering drawer_ = new cgogn::rendering::Drawer(this); drawer_->new_list(); - drawer_->lineWidth(2.0); + drawer_->line_width(2.0); drawer_->begin(GL_LINE_LOOP); drawer_->color3f(1.0,0.0,0.0); drawer_->vertex3f(0,0,0); @@ -101,8 +101,8 @@ void Drawing::init() drawer_->color3f(1.0,1.0,0.0); drawer_->vertex3f(0,1,0); drawer_->end(); -// drawer_->pointSize(10.0); - drawer_->lineWidthAA(3.0); +// drawer_->point_size(10.0); + drawer_->line_width_AA(3.0); drawer_->begin(GL_LINES); drawer_->color3f(1.0,1.0,1.0); drawer_->vertex3fv(Vec3(-1,-1,0)); @@ -120,7 +120,7 @@ void Drawing::init() drawer_->vertex3fv({{2.5,1,0}}); drawer_->end(); - drawer_->pointSizeAA(7.0); + drawer_->point_size_aa(7.0); drawer_->begin(GL_POINTS); for (float a=0.0f; a < 1.0f; a+= 0.1f) { @@ -135,7 +135,7 @@ void Drawing::init() drawer2_ = new cgogn::rendering::Drawer(this); drawer2_->new_list(); - drawer2_->pointSizeAA(5.0); + drawer2_->point_size_aa(5.0); drawer2_->begin(GL_POINTS); drawer2_->color3f(1.0,1.0,1.0); for (float z=-1.0f; z < 1.0f; z+= 0.1f) diff --git a/cgogn/rendering/examples/simple_viewer.cpp b/cgogn/rendering/examples/simple_viewer.cpp index 5b2b2e2c..de863bb7 100644 --- a/cgogn/rendering/examples/simple_viewer.cpp +++ b/cgogn/rendering/examples/simple_viewer.cpp @@ -138,7 +138,7 @@ void Viewer::closeEvent(QCloseEvent*) delete vbo_norm_; delete vbo_color_; delete vbo_sphere_sz_; -// delete shader_vertex_; + delete shader_edge_; delete shader_flat_; delete shader_normal_; delete shader_phong_; @@ -156,7 +156,7 @@ Viewer::Viewer() : vbo_norm_(nullptr), vbo_color_(nullptr), vbo_sphere_sz_(nullptr), -// shader_vertex_(nullptr), + shader_edge_(nullptr), shader_flat_(nullptr), shader_normal_(nullptr), shader_phong_(nullptr), @@ -271,7 +271,7 @@ void Viewer::draw() } if (bb_rendering_) - drawer_->callList(proj,view); + drawer_->call_list(proj,view); } void Viewer::init() @@ -353,7 +353,7 @@ void Viewer::init() // drawer for simple old-school g1 rendering drawer_ = new cgogn::rendering::Drawer(this); drawer_->new_list(); - drawer_->lineWidthAA(2.0); + drawer_->line_width_AA(2.0); drawer_->begin(GL_LINE_LOOP); drawer_->color3f(1.0,1.0,1.0); drawer_->vertex3f(bb_.min()[0],bb_.min()[1],bb_.min()[2]); diff --git a/cgogn/rendering/examples/viewer_topo.cpp b/cgogn/rendering/examples/viewer_topo.cpp index 8b93001d..be14bb61 100644 --- a/cgogn/rendering/examples/viewer_topo.cpp +++ b/cgogn/rendering/examples/viewer_topo.cpp @@ -159,7 +159,7 @@ void Viewer::draw() } if (topo_rendering_) - drawer_topo->callList(proj,view); + drawer_topo->call_list(proj,view); } diff --git a/cgogn/rendering/map_render.h b/cgogn/rendering/map_render.h index 68aa7c36..eb38c400 100644 --- a/cgogn/rendering/map_render.h +++ b/cgogn/rendering/map_render.h @@ -279,13 +279,13 @@ void create_drawer_topo2(MAP& m, const typename MAP::template VertexAttributeHan // TODO phi1 - dr.pointSize(4.0); + dr.point_size(4.0); dr.begin(GL_POINTS); dr.color3f(1.0f,1.0f,1.0f); for (unsigned int i=0; i -#include - -#include // impossible to include directly attribute_handler.h ! -#include - -namespace cgogn -{ - -namespace rendering -{ - -enum DrawingType -{ - POINTS = 0, - LINES, - TRIANGLES, - SIZE_BUFFER -}; - -class MapRender -{ -protected: - - QOpenGLBuffer* indices_buffers_[SIZE_BUFFER]; - bool indices_buffers_uptodate_[SIZE_BUFFER]; - unsigned int nb_indices_[SIZE_BUFFER]; - -public: - - inline MapRender() - { - for (unsigned int i = 0u; i < SIZE_BUFFER; ++i) - { - indices_buffers_[i] = new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer); - indices_buffers_[i]->setUsagePattern(QOpenGLBuffer::StaticDraw); - } - } - - inline ~MapRender() - { - for (unsigned int i = 0u; i < SIZE_BUFFER; ++i) - delete indices_buffers_[i]; - } - - inline bool is_primitive_uptodate(DrawingType prim) { return indices_buffers_uptodate_[prim]; } - - template - void init_points(MAP& m, std::vector& table_indices) - { -// table_indices.reserve(m.get_nb_darts()/6); - m.foreach_cell([&] (typename MAP::Vertex v) - { - table_indices.push_back(m.get_embedding(v)); - }); - } - - template - void init_lines(MAP& m, std::vector& table_indices) - { -// table_indices.reserve(m.get_nb_darts()/2); - m.foreach_cell([&] (typename MAP::Edge e) - { - table_indices.push_back(m.template get_embedding(e.dart)); - table_indices.push_back(m.template get_embedding(m.phi1(e.dart))); - }); - } - - template - void init_triangles(MAP& m, std::vector& table_indices, const typename MAP::template VertexAttributeHandler& position) - { - // reserve more ? -// table_indices.reserve(m.get_nb_darts()/3); - m.foreach_cell([&] (typename MAP::Face f) - { -<<<<<<< HEAD - Dart d = f; - Dart d1 = m.phi1(d); - Dart d2 = m.phi1(d1); - unsigned int d_e = m.template get_embedding(d); - unsigned int d1_e = m.template get_embedding(d1); - unsigned int d2_e; - do - { - d2_e = m.template get_embedding(d2); - - table_indices.push_back(d_e); - table_indices.push_back(d1_e); - table_indices.push_back(d2_e); - - d1 = d2; - d2 = m.phi1(d1); - d1_e = d2_e; - - } while (d2 != d); -======= - if (m.has_degree(f,3)) - { - table_indices.push_back(m.template get_embedding(f.dart)); - table_indices.push_back(m.template get_embedding(m.phi1(f.dart))); - table_indices.push_back(m.template get_embedding(m.phi1(m.phi1(f.dart)))); - } - else - { -cgogn::geometry::compute_ear_triangulation(m,f,position,table_indices); - } ->>>>>>> cgogn/develop - }); - } - - template - void init_primitives(MAP& m, DrawingType prim, const typename MAP::template VertexAttributeHandler& position) - { - std::vector table_indices; - - switch (prim) - { - case POINTS: - init_points(m, table_indices); - break; - case LINES: - init_lines(m, table_indices); - break; - case TRIANGLES: - init_triangles(m, table_indices, position); - break; - default: - break; - } - - if (!indices_buffers_[prim]->isCreated()) - indices_buffers_[prim]->create(); - - indices_buffers_uptodate_[prim] = true; - nb_indices_[prim] = table_indices.size(); - indices_buffers_[prim]->bind(); - indices_buffers_[prim]->allocate(&(table_indices[0]), nb_indices_[prim] * sizeof(unsigned int)); - indices_buffers_[prim]->release(); - } - - inline void draw(DrawingType prim) - { - QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); - - indices_buffers_[prim]->bind(); - switch (prim) - { - case POINTS: - ogl->glDrawElements(GL_POINTS, nb_indices_[POINTS], GL_UNSIGNED_INT, 0); - break; - case LINES: - ogl->glDrawElements(GL_LINES, nb_indices_[LINES], GL_UNSIGNED_INT, 0); - break; - case TRIANGLES: - ogl->glDrawElements(GL_TRIANGLES, nb_indices_[TRIANGLES], GL_UNSIGNED_INT, 0); - break; - default: - break; - } - - indices_buffers_[prim]->release(); - } -}; - -} // namespace rendering - -} // namespace cgogn - -#endif // RENDERING_MAP_RENDER_H_ diff --git a/cgogn/rendering/shaders/shader_point_sprite.cpp b/cgogn/rendering/shaders/shader_point_sprite.cpp index 23f8b721..9ec7de65 100644 --- a/cgogn/rendering/shaders/shader_point_sprite.cpp +++ b/cgogn/rendering/shaders/shader_point_sprite.cpp @@ -49,13 +49,13 @@ const char* ShaderPointSprite::geometry_shader_source_ = "layout (triangle_strip, max_vertices=4) out;\n" "uniform mat4 projection_matrix;\n" "uniform mat4 model_view_matrix;\n" -"uniform float pointSize;\n" +"uniform float point_size;\n" "out vec2 spriteCoord;\n" "out vec3 sphereCenter;\n" "void corner(vec4 center, float x, float y)\n" "{\n" " spriteCoord = vec2(x,y);\n" -" vec4 pos = center + vec4(pointSize*x, pointSize*y, 0.0, 0.0);\n" +" vec4 pos = center + vec4(point_size*x, point_size*y, 0.0, 0.0);\n" " gl_Position = projection_matrix * pos;\n" " EmitVertex();\n" "}\n" @@ -78,15 +78,15 @@ const char* ShaderPointSprite::fragment_shader_source_ = "uniform vec4 color;\n" "uniform vec4 ambiant;\n" "uniform vec3 lightPos;\n" -"uniform float pointSize;\n" +"uniform float point_size;\n" "in vec2 spriteCoord;\n" "in vec3 sphereCenter;\n" "out vec3 fragColor;\n" "void main() {\n" -" vec3 billboard_frag_pos = sphereCenter + vec3(spriteCoord, 0.0) * pointSize;\n" +" vec3 billboard_frag_pos = sphereCenter + vec3(spriteCoord, 0.0) * point_size;\n" " vec3 ray_direction = normalize(billboard_frag_pos);\n" " float TD = -dot(ray_direction,sphereCenter);\n" -" float c = dot(sphereCenter, sphereCenter) - pointSize * pointSize;\n" +" float c = dot(sphereCenter, sphereCenter) - point_size * point_size;\n" " float arg = TD * TD - c;\n" " if (arg < 0.0)\n" " discard;\n" @@ -140,7 +140,7 @@ const char* ShaderPointSprite::geometry_shader_source2_ = "in float size_v[];\n" "out float size_f;\n" "#else\n" -"uniform float pointSize;\n" +"uniform float point_size;\n" "#endif\n" "out vec2 spriteCoord;\n" @@ -161,7 +161,7 @@ const char* ShaderPointSprite::geometry_shader_source2_ = "void corner(vec4 center, float x, float y)\n" "{\n" " spriteCoord = vec2(x,y);\n" -" vec4 pos = center + vec4(pointSize*x, pointSize*y, 0.0, 0.0);\n" +" vec4 pos = center + vec4(point_size*x, point_size*y, 0.0, 0.0);\n" " color_f = color_v[0];\n" " gl_Position = projection_matrix * pos;\n" " EmitVertex();\n" @@ -181,7 +181,7 @@ const char* ShaderPointSprite::geometry_shader_source2_ = "void corner(vec4 center, float x, float y)\n" "{\n" " spriteCoord = vec2(x,y);\n" -" vec4 pos = center + vec4(pointSize*x, pointSize*y, 0.0, 0.0);\n" +" vec4 pos = center + vec4(point_size*x, point_size*y, 0.0, 0.0);\n" " gl_Position = projection_matrix * pos;\n" " EmitVertex();\n" "}\n" @@ -206,7 +206,7 @@ const char* ShaderPointSprite::fragment_shader_source2_ = "#if WITH_SIZE == 1\n" "in float size_f;\n" "#else\n" -"uniform float pointSize;\n" +"uniform float point_size;\n" "#endif\n" "#if WITH_COLOR == 1\n" "in vec3 color_f;\n" @@ -219,12 +219,12 @@ const char* ShaderPointSprite::fragment_shader_source2_ = "void main() {\n" " #if WITH_SIZE == 1\n" -" float pointSize=size_f;\n" +" float point_size=size_f;\n" " #endif\n" -" vec3 billboard_frag_pos = sphereCenter + vec3(spriteCoord, 0.0) * pointSize;\n" +" vec3 billboard_frag_pos = sphereCenter + vec3(spriteCoord, 0.0) * point_size;\n" " vec3 ray_direction = normalize(billboard_frag_pos);\n" " float TD = -dot(ray_direction,sphereCenter);\n" -" float c = dot(sphereCenter, sphereCenter) - pointSize * pointSize;\n" +" float c = dot(sphereCenter, sphereCenter) - point_size * point_size;\n" " float arg = TD * TD - c;\n" " if (arg < 0.0)\n" " discard;\n" @@ -298,7 +298,7 @@ ShaderPointSprite::ShaderPointSprite(bool color_per_vertex, bool size_per_vertex unif_color_ = prg_.uniformLocation("color"); unif_ambiant_ = prg_.uniformLocation("ambiant"); unif_light_pos_ = prg_.uniformLocation("lightPos"); - unif_size_ = prg_.uniformLocation("pointSize"); + unif_size_ = prg_.uniformLocation("point_size"); set_color(QColor(250,0,0)); From a1bc108fdca9fb483baddd43c01ff0095cdd62a5 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Tue, 8 Mar 2016 11:05:24 +0100 Subject: [PATCH 271/402] close_map and random holes generation --- cgogn/core/cmap/cmap0.h | 3 +- cgogn/core/cmap/cmap2.h | 3 +- cgogn/core/cmap/cmap3.h | 3 +- cgogn/core/cmap/map_base.h | 5 ++ cgogn/core/tests/cmap/cmap2_test.cpp | 8 +-- cgogn/core/tests/cmap/cmap2_topo_test.cpp | 59 ++++++++++++++--------- 6 files changed, 51 insertions(+), 30 deletions(-) diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index ee9f8107..f1c5ab1f 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -102,7 +102,8 @@ class CMap0_T : public MapBase { } - inline bool check_integrity(Dart /*d*/) const { + inline bool check_integrity(Dart /*d*/) const + { return true; } /******************************************************************************* diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index eb558809..c2206fe3 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -142,7 +142,8 @@ class CMap2_T : public CMap1_T (*phi2_)[d.index] = d; } - inline bool check_integrity(Dart d) const { + inline bool check_integrity(Dart d) const + { return (Inherit::check_integrity(d) && phi2(phi2(d)) == d && phi2(d) != d); diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 9bfe0a29..648a406d 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -154,7 +154,8 @@ class CMap3_T : public CMap2_T (*phi3_)[d.index] = d; } - inline bool check_integrity(Dart d) const { + inline bool check_integrity(Dart d) const + { return (Inherit::check_integrity(d) && phi3(phi3(d)) == d && phi3(d) != d && diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 45e4894a..461fc387 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -419,6 +419,7 @@ class MapBase : public MapBaseData if (marker[this->template get_embedding(c.dart)] > 0) { result = false; + std::cerr << "Two cells with same index in orbit " << orbit_name(ORBIT) << std::endl; return false; } marker[this->template get_embedding(c.dart)] = 1; @@ -427,12 +428,15 @@ class MapBase : public MapBaseData if (idx == EMBNULL) { result = false; + std::cerr << "EMBNULL found in orbit " << orbit_name(ORBIT) << std::endl; return false; } // check all darts of the cell use the same index (distinct to EMBNULL) cmap->foreach_dart_of_orbit_until(c, [&] (Dart d) { if (this->template get_embedding(d) != idx) result = false; + if (!result) + std::cerr << "Different indices in orbit " << orbit_name(ORBIT) << std::endl; return result; }); @@ -446,6 +450,7 @@ class MapBase : public MapBaseData if (marker[i] == 0) { result = false; + std::cerr << "Some cells are not used in orbit " << orbit_name(ORBIT) << std::endl; break; } } diff --git a/cgogn/core/tests/cmap/cmap2_test.cpp b/cgogn/core/tests/cmap/cmap2_test.cpp index 399167b5..3aa6541c 100644 --- a/cgogn/core/tests/cmap/cmap2_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_test.cpp @@ -100,7 +100,7 @@ class CMap2Test: public ::testing::Test /*! * \brief Generate a closed surface from the set of faces in darts_ */ - void add_closed_surface() + void add_closed_surfaces() { darts_.clear(); MapBuilder mbuild(cmap_); @@ -167,7 +167,7 @@ TEST_F(CMap2Test, random_map_generators) add_faces(NB_MAX); EXPECT_TRUE(cmap_.check_map_integrity()); - add_closed_surface(); + add_closed_surfaces(); EXPECT_TRUE(cmap_.check_map_integrity()); } @@ -190,7 +190,7 @@ TEST_F(CMap2Test, add_face) */ TEST_F(CMap2Test, cut_edge) { - add_closed_surface(); + add_closed_surfaces(); for (Dart d: darts_) cmap_.cut_edge(d); @@ -202,7 +202,7 @@ TEST_F(CMap2Test, cut_edge) */ TEST_F(CMap2Test, cut_face) { - add_closed_surface(); + add_closed_surfaces(); for (Dart d: darts_) { diff --git a/cgogn/core/tests/cmap/cmap2_topo_test.cpp b/cgogn/core/tests/cmap/cmap2_topo_test.cpp index d1cfb700..5d45f2ff 100644 --- a/cgogn/core/tests/cmap/cmap2_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_topo_test.cpp @@ -90,9 +90,9 @@ class CMap2TopoTest: public CMap2, public ::testing::Test } /*! - * \brief Generate an open surface + * \brief Generate a set of closed surfaces with arbitrary genius. */ - void add_open_surface() + void add_closed_surfaces() { darts_.clear(); unsigned int n = 0u; @@ -100,12 +100,12 @@ class CMap2TopoTest: public CMap2, public ::testing::Test // Generate NB_MAX random 1-faces (without boundary) for (unsigned int i = 0u; i < NB_MAX; ++i) { - n = 1 + std::rand() % 10; + n = 1u + std::rand() % 10; Dart d = Inherit::Inherit::add_face_topo(n); darts_.push_back(d); } // Sew some pairs off 1-egdes - for (unsigned int i = 0u; i < 3*NB_MAX; ++i) + for (unsigned int i = 0u; i < 3u*NB_MAX; ++i) { Dart e1 = darts_[std::rand() % NB_MAX]; n = std::rand() % 10u; @@ -123,13 +123,7 @@ class CMap2TopoTest: public CMap2, public ::testing::Test e2 = phi_1(e2); } } - } - - /*! - * \brief Generate a closed surface - */ - void add_closed_surface() { - add_open_surface(); + // Close de map foreach_dart( [&] (Dart d) { if (phi2(d) == d) close_hole_topo(d); @@ -147,7 +141,7 @@ TEST_F(CMap2TopoTest, random_map_generators) add_faces(NB_MAX); EXPECT_TRUE(check_map_integrity()); - add_closed_surface(); + add_closed_surfaces(); EXPECT_TRUE(check_map_integrity()); } @@ -216,7 +210,7 @@ TEST_F(CMap2TopoTest, add_face_topo) */ TEST_F(CMap2TopoTest, cut_edge_topo) { - add_closed_surface(); + add_closed_surfaces(); unsigned int count_vertices = nb_cells(); unsigned int count_edges = nb_cells(); @@ -252,7 +246,7 @@ TEST_F(CMap2TopoTest, cut_edge_topo) */ TEST_F(CMap2TopoTest, cut_face_topo) { - add_closed_surface(); + add_closed_surfaces(); unsigned int count_vertices = nb_cells(); unsigned int count_edges = nb_cells(); @@ -289,15 +283,34 @@ TEST_F(CMap2TopoTest, cut_face_topo) */ TEST_F(CMap2TopoTest, close_map) { - add_open_surface(); - - // add attributes -// add_attribute("darts"); -// add_attribute("vertices"); -// add_attribute("edges"); -// add_attribute("faces"); -// add_attribute("volumes"); -// EXPECT_TRUE(check_map_integrity()); + add_closed_surfaces(); + + // add attributes to initialize the indexation + add_attribute("darts"); + add_attribute("vertices"); + add_attribute("edges"); + add_attribute("faces"); + add_attribute("volumes"); + EXPECT_TRUE(check_map_integrity()); + + // create some random holes + for (Dart d: darts_) + { + if (std::rand()%2 ==1) { + foreach_dart_of_orbit(Face(d), [&] (Dart e) { + phi2_unsew(e); + }); + Dart e = d; + Dart it = phi1(e); + while (it != e) { + Dart next = phi1(it); + this->remove_dart(it); + it = next; + } + this->remove_dart(e); + } + } + // add code for partial holes => phi2_unsew some darts of a face without deleting the face close_map(); EXPECT_TRUE(check_map_integrity()); From 473fe76234ae0de3a2427d64c48d6c755e7776cc Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Tue, 8 Mar 2016 11:07:06 +0100 Subject: [PATCH 272/402] _AA -> _aa --- cgogn/rendering/drawer.h | 3 +-- cgogn/rendering/examples/drawing.cpp | 2 +- cgogn/rendering/examples/simple_viewer.cpp | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/cgogn/rendering/drawer.h b/cgogn/rendering/drawer.h index 830603c3..660ecf58 100644 --- a/cgogn/rendering/drawer.h +++ b/cgogn/rendering/drawer.h @@ -86,7 +86,6 @@ class CGOGN_RENDERING_API Drawer /** * constructor, init all buffers (data and OpenGL) and shader - * @param lineMode 0:simple thin Line / 1:line with possible width /2:3D Lines * @Warning need OpenGL context */ Drawer(QOpenGLFunctions_3_3_Core* ogl33); @@ -196,7 +195,7 @@ class CGOGN_RENDERING_API Drawer current_size_ = lw; } - inline void line_width_AA(float lw) + inline void line_width_aa(float lw) { current_aa_ = true; current_size_ = 2.0*lw; diff --git a/cgogn/rendering/examples/drawing.cpp b/cgogn/rendering/examples/drawing.cpp index b8cdb21b..7d99096e 100644 --- a/cgogn/rendering/examples/drawing.cpp +++ b/cgogn/rendering/examples/drawing.cpp @@ -102,7 +102,7 @@ void Drawing::init() drawer_->vertex3f(0,1,0); drawer_->end(); // drawer_->point_size(10.0); - drawer_->line_width_AA(3.0); + drawer_->line_width_aa(3.0); drawer_->begin(GL_LINES); drawer_->color3f(1.0,1.0,1.0); drawer_->vertex3fv(Vec3(-1,-1,0)); diff --git a/cgogn/rendering/examples/simple_viewer.cpp b/cgogn/rendering/examples/simple_viewer.cpp index de863bb7..0e7434fa 100644 --- a/cgogn/rendering/examples/simple_viewer.cpp +++ b/cgogn/rendering/examples/simple_viewer.cpp @@ -353,7 +353,7 @@ void Viewer::init() // drawer for simple old-school g1 rendering drawer_ = new cgogn::rendering::Drawer(this); drawer_->new_list(); - drawer_->line_width_AA(2.0); + drawer_->line_width_aa(2.0); drawer_->begin(GL_LINE_LOOP); drawer_->color3f(1.0,1.0,1.0); drawer_->vertex3f(bb_.min()[0],bb_.min()[1],bb_.min()[2]); From 995542c5ab23b648aebeb53f85e333f01287081c Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Tue, 8 Mar 2016 13:35:55 +0100 Subject: [PATCH 273/402] close_map test completed --- cgogn/core/tests/cmap/cmap2_topo_test.cpp | 101 +++++++++++++++++++--- 1 file changed, 91 insertions(+), 10 deletions(-) diff --git a/cgogn/core/tests/cmap/cmap2_topo_test.cpp b/cgogn/core/tests/cmap/cmap2_topo_test.cpp index 5d45f2ff..b237ca6c 100644 --- a/cgogn/core/tests/cmap/cmap2_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_topo_test.cpp @@ -48,6 +48,7 @@ class CMap2TopoTest: public CMap2, public ::testing::Test using Edge = CMap2TopoTest::Edge; using Face = CMap2TopoTest::Face; using Volume = CMap2TopoTest::Volume; + using VertexMarker = CMap2TopoTest::CellMarker; protected: @@ -65,6 +66,65 @@ class CMap2TopoTest: public CMap2, public ::testing::Test std::srand(static_cast(std::time(0))); } + /*! + * \brief Tests if the open vertex of d contains a specified dart e. + * The method supposes that the given dart d is the first dart + * of the open PHI21 orbit (i.e. phi2(d) == d) + */ + bool same_open_vertex(Dart d, Dart e) + { + cgogn_assert(phi2(d) == d); + Dart it = d; + Dart it1 = phi_1(it); + + while (it != e && phi2(it1) != it1) + { + it = phi2(it1); + it1 = phi_1(it); + } + if (it == e) return true; + return false; + } + + /*! + * \brief Tests if the volume of d contains a specified dart e. + * The method does not exploit the indexing information + */ + bool same_volume(Dart d, Dart e) + { + bool result = false; + + foreach_dart_of_orbit_until(Volume(d), [&result,&e] (Dart vit) + { + if (vit == e) result = true; + return !result; + }); + + return result; + } + + /*! + * \brief Embed an open vertex d on a new attribute. + * The method supposes that the given dart d is the first dart + * of the open PHI21 orbit (i.e. phi2(d) == d) + */ + void new_open_vertex_embedding(Dart d) + { + cgogn_assert(phi2(d) == d); + const unsigned int emb = add_attribute_element(); + + Dart it = d; + Dart it1 = phi_1(it); + + set_embedding(it, emb); + while (phi2(it1) != it1) + { + it = phi2(it1); + it1 = phi_1(it); + set_embedding(it, emb); + } + } + /*! * \brief Generate a random set of faces and put them in darts_ * \return The total number of added vertices. @@ -293,24 +353,45 @@ TEST_F(CMap2TopoTest, close_map) add_attribute("volumes"); EXPECT_TRUE(check_map_integrity()); - // create some random holes + // create some random holes (full removalor partial unsewing of faces) for (Dart d: darts_) { if (std::rand()%2 ==1) { - foreach_dart_of_orbit(Face(d), [&] (Dart e) { + unsigned int n = std::rand()%10; + unsigned int k = degree(Face(d)); + + foreach_dart_of_orbit_until(Face(d), [&] (Dart e) + { + Dart e2 = phi2(e); phi2_unsew(e); + // correct indexation of vertices + if (!same_open_vertex(e2, phi1(e))) new_open_vertex_embedding(e2); + if (!same_open_vertex(e, phi1(e2))) new_open_vertex_embedding(e); + // correct indexation of edges + new_orbit_embedding(Edge(e2)); + // correct indexation of volumes + if (!same_volume(e2,e)) new_orbit_embedding(Volume(e)); + // interrupt the face unsewing after n steps + if (n-- <= 0) return false; + // control if a partial or full face unsewing has been done + --k; + return true; }); - Dart e = d; - Dart it = phi1(e); - while (it != e) { - Dart next = phi1(it); - this->remove_dart(it); - it = next; + // if the face is completely unsewed randomly removes it + if (k == 0 && std::rand()%2 == 1) + { + Dart e = d; + Dart it = phi1(e); + while (it != e) + { + Dart next = phi1(it); + this->remove_dart(it); + it = next; + } + this->remove_dart(e); } - this->remove_dart(e); } } - // add code for partial holes => phi2_unsew some darts of a face without deleting the face close_map(); EXPECT_TRUE(check_map_integrity()); From d0ab66c967a54a5a8d83fade258151e58439e2f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 8 Mar 2016 16:06:59 +0100 Subject: [PATCH 274/402] zlib_decompress function is only available if Zlib is found. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/CMakeLists.txt | 7 ++++++- cgogn/io/io_utils.cpp | 2 ++ cgogn/io/io_utils.h | 6 ++++-- cgogn/io/vtk_io.h | 5 +++++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/cgogn/io/CMakeLists.txt b/cgogn/io/CMakeLists.txt index cd18574d..4cb73230 100644 --- a/cgogn/io/CMakeLists.txt +++ b/cgogn/io/CMakeLists.txt @@ -3,7 +3,12 @@ project(cgogn_io ) find_package(ZLIB) -add_definitions("-DZLIB_CONST") +if (${ZLIB_FOUND}) + add_definitions("-DZLIB_CONST") + add_definitions("-DCGOGN_WITH_ZLIB") +endif() + + set(HEADER_FILES surface_import.h diff --git a/cgogn/io/io_utils.cpp b/cgogn/io/io_utils.cpp index 878c8fb1..4233f7e5 100644 --- a/cgogn/io/io_utils.cpp +++ b/cgogn/io/io_utils.cpp @@ -26,7 +26,9 @@ #include #include +#ifdef CGOGN_WITH_ZLIB #include +#endif #include #include diff --git a/cgogn/io/io_utils.h b/cgogn/io/io_utils.h index 39bd8337..28130b92 100644 --- a/cgogn/io/io_utils.h +++ b/cgogn/io/io_utils.h @@ -64,9 +64,11 @@ enum DataType }; CGOGN_IO_API FileType get_file_type(const std::string& filename); CGOGN_IO_API DataType get_data_type(const std::string& type_name); -CGOGN_IO_API std::vector base64_decode(std::string& input); -CGOGN_IO_API void zlib_decompress(std::string& input, DataType header_type); +CGOGN_IO_API std::vector base64_decode(const std::string& input); +#ifdef CGOGN_WITH_ZLIB +CGOGN_IO_API std::vector zlib_decompress(const char*& input, DataType header_type); +#endif namespace internal { diff --git a/cgogn/io/vtk_io.h b/cgogn/io/vtk_io.h index 38c09dcf..dce4bdc4 100644 --- a/cgogn/io/vtk_io.h +++ b/cgogn/io/vtk_io.h @@ -107,7 +107,12 @@ protected : data_str = std::string(reinterpret_cast(&decode[header_type == DataType::UINT32 ? 4u : 8u]), length); } else { +#ifdef CGOGN_WITH_ZLIB zlib_decompress(data_str, header_type); +#else + std::cerr << "read_binary_xml_data : unable to decompress the data : Zlib was not found." << std::endl; + std::exit(EXIT_FAILURE); +#endif } } From 80b312fdf683a33ed81dbf826a254b3a035bc298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 8 Mar 2016 16:10:09 +0100 Subject: [PATCH 275/402] added some doc about dynamic_cast_unique_ptr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/utils/unique_ptr.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cgogn/core/utils/unique_ptr.h b/cgogn/core/utils/unique_ptr.h index b9748798..a9af63ff 100644 --- a/cgogn/core/utils/unique_ptr.h +++ b/cgogn/core/utils/unique_ptr.h @@ -76,6 +76,12 @@ typename _Unique_if::_Known_bound make_unique(Args&&...) = delete; +/** + * @brief dynamic_cast_unique_ptr + * @param ptr, a unique_ptr that might loose the ownership. + * @return nullptr if the cast wasn't successfull, a valid unique_ptr otherwise + * Warning : if the cast is successfull, the unique_ptr "ptr" loses the ownership (ptr.release() is called), whereas if the cast fails ptr still has the ownership. + */ template inline std::unique_ptr dynamic_cast_unique_ptr(std::unique_ptr&& ptr) { From 72805dffdcb57c5b33d619ff97381e4ab4e9afe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 8 Mar 2016 16:13:19 +0100 Subject: [PATCH 276/402] small changes in zlib_decompress and base64_decode. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/data_io.h | 3 +- cgogn/io/io_utils.cpp | 64 ++++++++++++++++++++++--------------------- cgogn/io/io_utils.h | 4 +-- cgogn/io/vtk_io.h | 34 ++++++++++++----------- 4 files changed, 54 insertions(+), 51 deletions(-) diff --git a/cgogn/io/data_io.h b/cgogn/io/data_io.h index 74a83e9a..6449173d 100644 --- a/cgogn/io/data_io.h +++ b/cgogn/io/data_io.h @@ -111,14 +111,13 @@ class DataInput : public DataInputGen return *this; } - inline DataInput& operator =(Self&& other) + inline DataInput& operator =(Self&& other) { if (&other != this) data_ = std::move(other.data_); return *this; } - virtual void read_n(std::istream& fp, std::size_t n, bool binary, bool big_endian) override { const std::size_t old_size = data_.size(); diff --git a/cgogn/io/io_utils.cpp b/cgogn/io/io_utils.cpp index 4233f7e5..08e07b91 100644 --- a/cgogn/io/io_utils.cpp +++ b/cgogn/io/io_utils.cpp @@ -39,11 +39,9 @@ namespace cgogn namespace io { -CGOGN_IO_API void zlib_decompress(std::string& input, DataType header_type) +#ifdef CGOGN_WITH_ZLIB +CGOGN_IO_API std::vector zlib_decompress(const std::string& input, DataType header_type) { - input.erase(std::remove(input.begin(), input.end(), ' '), input.end()); - input.erase(std::remove(input.begin(), input.end(), '\n'), input.end()); - input.erase(std::remove(input.begin(), input.end(), '\t'), input.end()); std::uint64_t nb_blocks = UINT64_MAX; std::uint64_t uncompressed_block_size = UINT64_MAX; @@ -57,29 +55,26 @@ CGOGN_IO_API void zlib_decompress(std::string& input, DataType header_type) { word_size = 8u; // we read the first 3 uint64 - header = input.substr(0, 24); - header_data = base64_decode(header); + header_data = base64_decode(input, 0, 24); nb_blocks = *reinterpret_cast(&header_data[0]); uncompressed_block_size = *reinterpret_cast(&header_data[8]); last_block_size = *reinterpret_cast(&header_data[16]); compressed_size.resize(nb_blocks); } else { - header = input.substr(0, 12); - header_data = base64_decode(header); + header_data = base64_decode(header, 0, 12); nb_blocks = *reinterpret_cast(&header_data[0]); uncompressed_block_size = *reinterpret_cast(&header_data[4]); last_block_size = *reinterpret_cast(&header_data[8]); compressed_size.resize(nb_blocks); } - std::size_t header_end = 4ul *word_size; -std:size_t length = nb_blocks* word_size *4ul; + std::size_t header_end = 4ul * word_size; + std::size_t length = nb_blocks * word_size *4ul; while ((length % 12ul != 0ul)) ++length; length/=3ul; - header = input.substr(header_end, length); - header_data = base64_decode(header); + header_data = base64_decode(input, header_end, length); if (header_type == DataType::UINT64) { for (unsigned int i = 0; i < nb_blocks; ++i) @@ -90,11 +85,8 @@ std:size_t length = nb_blocks* word_size *4ul; compressed_size[i] = *reinterpret_cast(&header_data[4u*i]); } - std::string data_str(input.substr(header_end +length, std::string::npos)); - - std::vector data = base64_decode(data_str); - std::vector res; - res.resize(uncompressed_block_size*(nb_blocks-1u) + last_block_size); + std::vector data = base64_decode(input, header_end +length, input.size() - header_end - length); + std::vector res(uncompressed_block_size*(nb_blocks-1u) + last_block_size); // zlib init int ret; @@ -116,28 +108,34 @@ std:size_t length = nb_blocks* word_size *4ul; in_data_it += compressed_size[i]; out_data_it+=uncompressed_block_size; } - input = std::string(reinterpret_cast(&res[0]), res.size()); + return res; } +#endif -CGOGN_IO_API std::vector base64_decode(std::string& input) +CGOGN_IO_API std::vector base64_decode(const std::string& input, std::size_t begin, std::size_t length) { const static char padCharacter('='); - if (input.length() % 4) //Sanity check - throw std::runtime_error("Non-Valid base64!"); + if (length % 4ul) //Sanity check + { + std::cerr << "base64_decode : Error : the given length (" << length << ") is not a multiple of 4. This is not valid." << std::endl; + std::exit(EXIT_FAILURE); + } + size_t padding = 0; - if (input.length()) + if (length) { - if (input[input.length()-1] == padCharacter) + if (input[begin + length-1] == padCharacter) padding++; - if (input[input.length()-2] == padCharacter) + if (input[begin + length-2] == padCharacter) padding++; } //Setup a vector to hold the result std::vector decoded_chars; - decoded_chars.reserve(((input.length()/4)*3) - padding); + decoded_chars.reserve(((length/4ul)*3ul) - padding); long int temp=0; //Holds decoded quanta - std::basic_string::const_iterator cursor = input.begin(); - while (cursor < input.end()) + std::string::const_iterator cursor = input.begin() + begin; + const std::string::const_iterator end = input.begin() + begin +length; + while (cursor != end) { for (size_t quantumPosition = 0; quantumPosition < 4; quantumPosition++) { @@ -154,7 +152,7 @@ CGOGN_IO_API std::vector base64_decode(std::string& input) temp |= 0x3F; //change to 0x5F for URL alphabet else if (*cursor == padCharacter) //pad { - switch( input.end() - cursor ) + switch( end - cursor ) { case 1: //One pad character decoded_chars.push_back((temp >> 16) & 0x000000FF); @@ -164,10 +162,14 @@ CGOGN_IO_API std::vector base64_decode(std::string& input) decoded_chars.push_back((temp >> 10) & 0x000000FF); return decoded_chars; default: - throw std::runtime_error("Invalid Padding in Base 64!"); + std::cerr << "base64_decode : Error : Invalid Padding." << std::endl; + std::exit(EXIT_FAILURE); } - } else - throw std::runtime_error("Non-Valid Character in Base 64!"); + } else + { + std::cerr << "base64_decode : Error : Non-Valid Character." << std::endl; + std::exit(EXIT_FAILURE); + } cursor++; } decoded_chars.push_back((temp >> 16) & 0x000000FF); diff --git a/cgogn/io/io_utils.h b/cgogn/io/io_utils.h index 28130b92..8070693a 100644 --- a/cgogn/io/io_utils.h +++ b/cgogn/io/io_utils.h @@ -64,10 +64,10 @@ enum DataType }; CGOGN_IO_API FileType get_file_type(const std::string& filename); CGOGN_IO_API DataType get_data_type(const std::string& type_name); -CGOGN_IO_API std::vector base64_decode(const std::string& input); +CGOGN_IO_API std::vector base64_decode(const std::string& input, std::size_t begin, std::size_t length); #ifdef CGOGN_WITH_ZLIB -CGOGN_IO_API std::vector zlib_decompress(const char*& input, DataType header_type); +CGOGN_IO_API std::vector zlib_decompress(const std::string& input, DataType header_type); #endif namespace internal diff --git a/cgogn/io/vtk_io.h b/cgogn/io/vtk_io.h index dce4bdc4..d6f3b57b 100644 --- a/cgogn/io/vtk_io.h +++ b/cgogn/io/vtk_io.h @@ -94,21 +94,19 @@ protected : virtual void add_vertex_attribute(const DataInputGen& attribute_data, const std::string& attribute_name) = 0; virtual void add_cell_attribute(const DataInputGen& attribute_data, const std::string& attribute_name) = 0; - inline void read_binary_xml_data(std::string& data_str, bool is_compressed, DataType header_type) + inline std::vector read_binary_xml_data(std::string& data_str, bool is_compressed, DataType header_type) { + data_str.erase(std::remove_if(data_str.begin(), data_str.end(), [](char c) { return std::isspace(c); }), data_str.end()); if (!is_compressed) { - std::vector decode = base64_decode(data_str); - std::size_t length = 0ul; - if (header_type == DataType::UINT32) - length = *reinterpret_cast(&decode[0]); - else - length = *reinterpret_cast(&decode[0]); - data_str = std::string(reinterpret_cast(&decode[header_type == DataType::UINT32 ? 4u : 8u]), length); + std::vector decode = base64_decode(data_str, 0, data_str.size()); + decode.erase(decode.begin(), decode.begin() + (header_type == DataType::UINT32 ? 4u : 8u)); + return decode; } else { #ifdef CGOGN_WITH_ZLIB - zlib_decompress(data_str, header_type); + return zlib_decompress(data_str, header_type); + #else std::cerr << "read_binary_xml_data : unable to decompress the data : Zlib was not found." << std::endl; std::exit(EXIT_FAILURE); @@ -169,7 +167,7 @@ protected : auto pos = DataInputGen::template newDataIO(type_str, 3); pos->read_n(fp, nb_vertices, !ascii_file, false); this->add_vertex_attribute(*pos,"position"); - this->positions_ = std::move(*dynamic_cast_unique_ptr>(pos->simplify())); + this->positions_ = *dynamic_cast_unique_ptr>(pos->simplify()); } else { if (word == "CELLS" || word == "POLYGONS" || word == "TRIANGLE_STRIPS") { @@ -384,7 +382,8 @@ protected : std::string text(vertex_data->GetText()); if (binary) { - this->read_binary_xml_data(text,compressed, get_data_type(header_type)); + std::vector data= this->read_binary_xml_data(text,compressed, get_data_type(header_type)); + text = std::string(reinterpret_cast(&data[0]), data.size()); } std::istringstream ss(text); @@ -394,7 +393,7 @@ protected : auto pos = DataInputGen::template newDataIO(type, nb_comp); pos->read_n(ss, nb_vertices,binary,true); this->add_vertex_attribute(*pos,"position"); - this->positions_ = std::move(*dynamic_cast_unique_ptr>(pos->simplify())); + this->positions_ = *dynamic_cast_unique_ptr>(pos->simplify()); } else { std::unique_ptr vertex_att = DataInputGen::template newDataIO(type, nb_comp); @@ -443,7 +442,10 @@ protected : else { std::string text(cell_data->GetText()); if (binary) - this->read_binary_xml_data(text,compressed, get_data_type(header_type)); + { + std::vector data= this->read_binary_xml_data(text,compressed, get_data_type(header_type)); + text = std::string(reinterpret_cast(&data[0]), data.size()); + } std::istringstream ss(text); if (data_name == "connectivity") @@ -457,14 +459,14 @@ protected : { auto offsets = DataInputGen::template newDataIO(type); offsets->read_n(ss, nb_cells,binary,true); - this->offsets_ = std::move(*dynamic_cast_unique_ptr>(offsets->simplify())); + this->offsets_ = *dynamic_cast_unique_ptr>(offsets->simplify()); } else { if (data_name == "types") { auto types = DataInputGen::template newDataIO(type); types->read_n(ss, nb_cells,binary,true); - this->cell_types_ = std::move(*dynamic_cast_unique_ptr>(types->simplify())); + this->cell_types_ = *dynamic_cast_unique_ptr>(types->simplify()); } else { std::cout << "Reading cell attribute \"" << data_name << "\" of type " << type << "." << std::endl; @@ -482,7 +484,7 @@ protected : const unsigned int last_offset = this->offsets_.get_vec()->back(); auto cells = DataInputGen::template newDataIO(cell_connectivity_type); cells->read_n(ss, last_offset,cell_connectivity_is_bin,true); - this->cells_ = std::move(*dynamic_cast_unique_ptr>(cells->simplify())); + this->cells_ = *dynamic_cast_unique_ptr>(cells->simplify()); } } return true; From bbd189237400b62c736213de75da74ffcc6409d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 8 Mar 2016 16:14:08 +0100 Subject: [PATCH 277/402] added a small example of a compressed binary vtu mesh. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- data/meshes/nine_hexas_zlib.vtu | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 data/meshes/nine_hexas_zlib.vtu diff --git a/data/meshes/nine_hexas_zlib.vtu b/data/meshes/nine_hexas_zlib.vtu new file mode 100644 index 00000000..53deecfe --- /dev/null +++ b/data/meshes/nine_hexas_zlib.vtu @@ -0,0 +1,26 @@ + + + + + + + + + + AQAAAAAAAAAAgAAAAAAAAAADAAAAAAAAYgAAAAAAAAA=eJyNkrERwDAIAynZytp/Go+QKi6E3gmNzw8HQnbVLfaChDJu4NTvvY85yryBk65T57qUeQMfees/9lbmDdyDfKF9SMeX33S6/97/77tRP/d/6Pf6us8f/0KZu/97PfbqLmE= + + + + + AQAAAAAAAAAAgAAAAAAAAEACAAAAAAAAegAAAAAAAAA=eJxdjjkCggAQxBAUEA/wAlTU///SgkmTbVIls0Wx3ibchdtwCC/hI7zLK8NaHbxrOKqDV4WNOni3cFKHP9nbh63+ZO8ZzvLY69TBY++lDh5/H9TB4++3OvzJ3ik86k/2PuEij72zOnjsfdXB4+9eHTz+/qnzBzbsBF0= + + + AQAAAAAAAAAAgAAAAAAAAEgAAAAAAAAAIAAAAAAAAAA=eJzjYIAAASgtAaUVoLQGlDaA0hZQ2gFKe0BpACmIAWk= + + + AQAAAAAAAAAAgAAAAAAAAAkAAAAAAAAACwAAAAAAAAA=eJzj4YECAAIlAG0= + + + + + From 631dde5c1d95c0efb2800dc84aedc6a24586f7ba Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Tue, 8 Mar 2016 17:09:40 +0100 Subject: [PATCH 278/402] code cleaning --- cgogn/core/tests/cmap/cmap0_test.cpp | 11 ++-- cgogn/core/tests/cmap/cmap0_topo_test.cpp | 10 +-- cgogn/core/tests/cmap/cmap1_test.cpp | 16 ++--- cgogn/core/tests/cmap/cmap1_topo_test.cpp | 65 ++++++++++--------- cgogn/core/tests/cmap/cmap2_test.cpp | 72 +++++++++++---------- cgogn/core/tests/cmap/cmap2_topo_test.cpp | 78 +++++++++++------------ 6 files changed, 125 insertions(+), 127 deletions(-) diff --git a/cgogn/core/tests/cmap/cmap0_test.cpp b/cgogn/core/tests/cmap/cmap0_test.cpp index 58dfb32b..2d21cd04 100644 --- a/cgogn/core/tests/cmap/cmap0_test.cpp +++ b/cgogn/core/tests/cmap/cmap0_test.cpp @@ -33,13 +33,13 @@ namespace cgogn /*! * \brief The CMap0Test class implements tests on embedded CMap0 * It contains a CMap0 to which a vertex attribute is added - * to enforce the indexation mecanism in cell traversals. + * to enforce the indexation mechanism in cell traversals. * * Note that pure topological operations have already been tested, - * in CMap0TopoTest, thus only the indexation mecanism used for the + * in CMap0TopoTest, thus only the indexation mechanism used for the * embedding of cells is tested here. */ -class CMap0Test: public ::testing::Test +class CMap0Test : public ::testing::Test { public: @@ -51,7 +51,6 @@ class CMap0Test: public ::testing::Test protected: testCMap0 cmap_; - VertexAttributeHandler vertices_; /*! * \brief A vector of darts on which the methods are tested. @@ -65,7 +64,7 @@ class CMap0Test: public ::testing::Test { darts_.reserve(NB_MAX); std::srand(static_cast(std::time(0))); - vertices_ = cmap_.add_attribute("vertices"); + cmap_.add_attribute("vertices"); } /*! @@ -106,7 +105,7 @@ TEST_F(CMap0Test, remove_vertex) add_vertices(NB_MAX); for (Dart d: darts_) - if (std::rand()%3 == 1) cmap_.remove_vertex(Vertex(d)); + if (std::rand() % 3 == 1) cmap_.remove_vertex(Vertex(d)); EXPECT_TRUE(cmap_.check_map_integrity()); } diff --git a/cgogn/core/tests/cmap/cmap0_topo_test.cpp b/cgogn/core/tests/cmap/cmap0_topo_test.cpp index 9c3fa066..354b1734 100644 --- a/cgogn/core/tests/cmap/cmap0_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap0_topo_test.cpp @@ -32,13 +32,13 @@ namespace cgogn /*! * \brief The CMap0TopoTest class implements topological tests on CMap0 - * It contains a CMap0 with no attribute avoiding the indexation mecanism. + * It contains a CMap0 with no attribute avoiding the indexation mechanism. * * Note that these tests, check that the topological operators perform as wanted * but do neither tests the containers (refs_, used_, etc.) or the iterators. * These last tests are implemented in another test suite. */ -class CMap0TopoTest: public ::testing::Test +class CMap0TopoTest : public ::testing::Test { public: @@ -95,8 +95,8 @@ TEST_F(CMap0TopoTest, add_vertex) EXPECT_EQ(cmap_.nb_cells(), 1u); add_vertices(NB_MAX); - EXPECT_EQ(cmap_.nb_darts(), NB_MAX+1u); - EXPECT_EQ(cmap_.nb_cells(), NB_MAX+1u); + EXPECT_EQ(cmap_.nb_darts(), NB_MAX + 1u); + EXPECT_EQ(cmap_.nb_cells(), NB_MAX + 1u); EXPECT_TRUE(cmap_.check_map_integrity()); } @@ -118,7 +118,7 @@ TEST_F(CMap0TopoTest, remove_vertex) darts_.pop_back(); for (Dart d: darts_) { - if (std::rand()%3 == 1) + if (std::rand() % 3 == 1) { cmap_.remove_vertex(d); --count_vertices; diff --git a/cgogn/core/tests/cmap/cmap1_test.cpp b/cgogn/core/tests/cmap/cmap1_test.cpp index 47db2820..84b6d117 100644 --- a/cgogn/core/tests/cmap/cmap1_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_test.cpp @@ -39,7 +39,7 @@ namespace cgogn * in CMap1TopoTest, thus only the indexation mecanism used for the * embedding of cells is tested here. */ -class CMap1Test: public ::testing::Test +class CMap1Test : public ::testing::Test { public: @@ -75,15 +75,15 @@ class CMap1Test: public ::testing::Test unsigned int add_faces(unsigned int n) { darts_.clear(); - unsigned int count = 0; - for (unsigned int i = 0; i < n; ++i) + unsigned int count = 0u; + for (unsigned int i = 0u; i < n; ++i) { - unsigned int n = 1 + std::rand() % 10; + unsigned int n = 1u + std::rand() % 10; Dart d = cmap_.add_face(n); count += n; - n = std::rand() % 10; - while (n-- > 0) d = cmap_.phi1(d); + n = std::rand() % 10u; + while (n-- > 0u) d = cmap_.phi1(d); darts_.push_back(d); } @@ -122,7 +122,7 @@ TEST_F(CMap1Test, remove_face) for (Dart d: darts_) { - if (std::rand()%3 == 1) + if (std::rand() % 3 == 1) { unsigned int k = cmap_.degree(d); cmap_.remove_face(d); @@ -167,7 +167,7 @@ TEST_F(CMap1Test, remove_vertex) unsigned int k = cmap_.degree(Face(d)); cmap_.remove_vertex(Vertex(d)); --count_vertices; - if (k == 1) --count_faces; + if (k == 1u) --count_faces; } EXPECT_EQ(cmap_.nb_cells(), count_vertices); diff --git a/cgogn/core/tests/cmap/cmap1_topo_test.cpp b/cgogn/core/tests/cmap/cmap1_topo_test.cpp index b2301723..7de090c8 100644 --- a/cgogn/core/tests/cmap/cmap1_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_topo_test.cpp @@ -66,7 +66,7 @@ class CMap1TopoTest : public CMap1, public ::testing::Test void add_vertices(unsigned int n) { darts_.clear(); - for (unsigned int i = 0; i < n; ++i) + for (unsigned int i = 0u; i < n; ++i) darts_.push_back(add_dart()); } @@ -79,15 +79,15 @@ class CMap1TopoTest : public CMap1, public ::testing::Test unsigned int add_faces(unsigned int n) { darts_.clear(); - unsigned int count = 0; - for (unsigned int i = 0; i < n; ++i) + unsigned int count = 0u; + for (unsigned int i = 0u; i < n; ++i) { - unsigned int n = 1 + std::rand() % 10; + unsigned int n = 1u + std::rand() % 10u; Dart d = add_face_topo(n); count += n; - n = std::rand() % 10; - while (n-- > 0) d = phi1(d); + n = std::rand() % 10u; + while (n-- > 0u) d = phi1(d); darts_.push_back(d); } @@ -111,15 +111,14 @@ TEST_F(CMap1TopoTest, random_map_generators) /*! * \brief Sewing and unsewing darts correctly changes the topological relations. - * The test perfoms NB_MAX sewing and unsewing on randomly chosen dart of darts_. + * The test performs NB_MAX sewing and unsewing on randomly chosen dart of darts_. * The map integrity is preserved. */ TEST_F(CMap1TopoTest, phi1_sew_unsew) { add_vertices(NB_MAX); - int count_faces = NB_MAX; - for (unsigned int i = 0; i < NB_MAX; ++i) + for (unsigned int i = 0u; i < NB_MAX; ++i) { Dart d = darts_[std::rand() % NB_MAX]; Dart e = darts_[std::rand() % NB_MAX]; @@ -145,21 +144,21 @@ TEST_F(CMap1TopoTest, phi1_sew_unsew) */ TEST_F(CMap1TopoTest, add_face_topo) { - add_face_topo(1); - EXPECT_EQ(nb_darts(), 1); - EXPECT_EQ(nb_cells(), 1); - EXPECT_EQ(nb_cells(), 1); + add_face_topo(1u); + EXPECT_EQ(nb_darts(), 1u); + EXPECT_EQ(nb_cells(), 1u); + EXPECT_EQ(nb_cells(), 1u); - add_face_topo(10); - EXPECT_EQ(nb_darts(), 11); - EXPECT_EQ(nb_cells(), 11); - EXPECT_EQ(nb_cells(), 2); + add_face_topo(10u); + EXPECT_EQ(nb_darts(), 11u); + EXPECT_EQ(nb_cells(), 11u); + EXPECT_EQ(nb_cells(), 2u); - unsigned int count_vertices = 11 + add_faces(NB_MAX); + unsigned int count_vertices = 11u + add_faces(NB_MAX); EXPECT_EQ(nb_darts(), count_vertices); EXPECT_EQ(nb_cells(), count_vertices); - EXPECT_EQ(nb_cells(), NB_MAX+2); + EXPECT_EQ(nb_cells(), NB_MAX + 2u); EXPECT_TRUE(check_map_integrity()); } @@ -174,7 +173,7 @@ TEST_F(CMap1TopoTest, remove_face) for (Dart d: darts_) { - if (std::rand()%3 == 1) + if (std::rand() % 3 == 1) { unsigned int k = degree(Face(d)); remove_face(d); @@ -188,8 +187,8 @@ TEST_F(CMap1TopoTest, remove_face) EXPECT_TRUE(check_map_integrity()); } -/*! \brief Spliting a vertex increases the size of its face. - * The test performs NB_MAX vertex spliting on vertices of randomly generated faces. +/*! \brief Splitting a vertex increases the size of its face. + * The test performs NB_MAX vertex splitting on vertices of randomly generated faces. * The number of generated cells is correct and the map integrity is preserved. */ TEST_F(CMap1TopoTest, split_vertex_topo) @@ -201,7 +200,7 @@ TEST_F(CMap1TopoTest, split_vertex_topo) unsigned int k = degree(Face(d)); split_vertex_topo(d); ++count_vertices; - EXPECT_EQ(degree(Face(d)), k+1); + EXPECT_EQ(degree(Face(d)), k + 1); } EXPECT_EQ(nb_darts(), count_vertices); EXPECT_EQ(nb_cells(), count_vertices); @@ -226,7 +225,7 @@ TEST_F(CMap1TopoTest, remove_vertex) Dart e = phi1(d); remove_vertex(Vertex(d)); --count_vertices; - EXPECT_EQ(degree(Face(e)), k-1); + EXPECT_EQ(degree(Face(e)), k - 1); } else { @@ -255,7 +254,7 @@ TEST_F(CMap1TopoTest, reverse_face_topo) std::vector face_darts; face_darts.reserve(k); - foreach_dart_of_orbit(Face(d), [&] (Dart e) + foreach_dart_of_orbit(Face(d), [&](Dart e) { face_darts.push_back(e); }); @@ -264,7 +263,7 @@ TEST_F(CMap1TopoTest, reverse_face_topo) EXPECT_EQ(degree(Face(d)), k); d = phi1(d); - foreach_dart_of_orbit(Face(d), [&] (Dart e) + foreach_dart_of_orbit(Face(d), [&](Dart e) { EXPECT_TRUE(face_darts.back() == e); face_darts.pop_back(); @@ -281,21 +280,21 @@ TEST_F(CMap1TopoTest, reverse_face_topo) */ TEST_F(CMap1TopoTest, degree) { - Face f = this->add_face_topo(10); + Face f = this->add_face_topo(10u); - EXPECT_EQ(degree(f),10); + EXPECT_EQ(degree(f), 10u); } /*! \brief The degree of a face is correctly tested. */ TEST_F(CMap1TopoTest, has_degree) { - Face f = this->add_face_topo(10); + Face f = this->add_face_topo(10u); - EXPECT_TRUE(has_degree(f,10)); - EXPECT_FALSE(has_degree(f,0)); - EXPECT_FALSE(has_degree(f,9)); - EXPECT_FALSE(has_degree(f,11)); + EXPECT_TRUE(has_degree(f, 10u)); + EXPECT_FALSE(has_degree(f, 0u)); + EXPECT_FALSE(has_degree(f, 9u)); + EXPECT_FALSE(has_degree(f, 11u)); } #undef NB_MAX diff --git a/cgogn/core/tests/cmap/cmap2_test.cpp b/cgogn/core/tests/cmap/cmap2_test.cpp index 3aa6541c..b32c0459 100644 --- a/cgogn/core/tests/cmap/cmap2_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_test.cpp @@ -33,13 +33,13 @@ namespace cgogn /*! * \brief The CMap2Test class implements tests on embedded CMap2 * It contains a CMap2 to which vertex, edge, face and volume attribute - * are added to enforce the indexation mecanism in cell traversals. + * are added to enforce the indexation mechanism in cell traversals. * * Note that pure topological operations have already been tested, - * in CMap2TopoTest, thus only the indexation mecanism used for the + * in CMap2TopoTest, thus only the indexation mechanism used for the * embedding of cells is tested here. */ -class CMap2Test: public ::testing::Test +class CMap2Test : public ::testing::Test { public: @@ -85,7 +85,7 @@ class CMap2Test: public ::testing::Test unsigned int count = 0u; for (unsigned int i = 0u; i < n; ++i) { - unsigned int n = 1 + std::rand() % 10u; + unsigned int n = 1u + std::rand() % 10u; Dart d = cmap_.add_face(n); count += n; @@ -104,27 +104,27 @@ class CMap2Test: public ::testing::Test { darts_.clear(); MapBuilder mbuild(cmap_); - unsigned int n = 0u; + unsigned int n; // Generate NB_MAX random 1-faces (without boundary) - for (unsigned int i = 0; i < NB_MAX; ++i) + for (unsigned int i = 0u; i < NB_MAX; ++i) { - n = 1 + std::rand() % 10u; + n = 1u + std::rand() % 10u; Dart d = mbuild.add_face_topo_parent(n); darts_.push_back(d); } - // Sew some pairs off egdes - for (unsigned int i = 0u; i < 3u*NB_MAX; ++i) + // Sew some pairs off edges + for (unsigned int i = 0u; i < 3u * NB_MAX; ++i) { Dart e1 = darts_[std::rand() % NB_MAX]; - n = std::rand()%10u; + n = std::rand() % 10u; while (n-- > 0u) e1 = cmap_.phi1(e1); Dart e2 = darts_[std::rand() % NB_MAX]; - n = std::rand()%10u; + n = std::rand() % 10u; while (n-- > 0u) e2 = cmap_.phi1(e2); - n = 1+std::rand()%3u; + n = 1 + std::rand() % 3u; while (n-- > 0u && cmap_.phi2(e1) == e1 && cmap_.phi2(e2) == e2 && e2 != e1) { mbuild.phi2_sew(e2, e1); @@ -133,29 +133,31 @@ class CMap2Test: public ::testing::Test } } // Close the map (remove remaining boundary) - cmap_.foreach_dart( [&] (Dart d) { - if (cmap_.phi2(d) == d) mbuild.close_hole_topo(d); - }); + cmap_.foreach_dart([&](Dart d) + { + if (cmap_.phi2(d) == d) mbuild.close_hole_topo(d); + }); // Embed the map - cmap_.foreach_dart( [&] (Dart d) { - mbuild.new_orbit_embedding(CDart(d)); - }); - cmap_.foreach_cell( [&] (Vertex v) - { - mbuild.new_orbit_embedding(v); - }); - cmap_.foreach_cell( [&] (Edge e) - { - mbuild.new_orbit_embedding(e); - }); - cmap_.foreach_cell( [&] (Face f) - { - mbuild.new_orbit_embedding(f); - }); - cmap_.foreach_cell( [&] (Volume w) - { - mbuild.new_orbit_embedding(w); - }); + cmap_.foreach_dart([&](Dart d) + { + mbuild.new_orbit_embedding(CDart(d)); + }); + cmap_.foreach_cell([&](Vertex v) + { + mbuild.new_orbit_embedding(v); + }); + cmap_.foreach_cell([&](Edge e) + { + mbuild.new_orbit_embedding(e); + }); + cmap_.foreach_cell([&](Face f) + { + mbuild.new_orbit_embedding(f); + }); + cmap_.foreach_cell([&](Volume w) + { + mbuild.new_orbit_embedding(w); + }); } }; @@ -180,7 +182,7 @@ TEST_F(CMap2Test, add_face) EXPECT_EQ(cmap_.nb_cells(), count_vertices); EXPECT_EQ(cmap_.nb_cells(), count_vertices); - EXPECT_EQ(cmap_.nb_cells(), 2*NB_MAX); + EXPECT_EQ(cmap_.nb_cells(), 2 * NB_MAX); EXPECT_EQ(cmap_.nb_cells(), NB_MAX); EXPECT_TRUE(cmap_.check_map_integrity()); } diff --git a/cgogn/core/tests/cmap/cmap2_topo_test.cpp b/cgogn/core/tests/cmap/cmap2_topo_test.cpp index b237ca6c..dc6df2b9 100644 --- a/cgogn/core/tests/cmap/cmap2_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_topo_test.cpp @@ -38,7 +38,7 @@ namespace cgogn * but do neither tests the containers (refs_, used_, etc.) or the iterators. * These last tests are implemented in another test suite. */ -class CMap2TopoTest: public CMap2, public ::testing::Test +class CMap2TopoTest : public CMap2, public ::testing::Test { public: @@ -94,7 +94,7 @@ class CMap2TopoTest: public CMap2, public ::testing::Test { bool result = false; - foreach_dart_of_orbit_until(Volume(d), [&result,&e] (Dart vit) + foreach_dart_of_orbit_until(Volume(d), [&](Dart vit) { if (vit == e) result = true; return !result; @@ -137,7 +137,7 @@ class CMap2TopoTest: public CMap2, public ::testing::Test unsigned int count = 0u; for (unsigned int i = 0u; i < n; ++i) { - unsigned int n = 1 + std::rand() % 10u; + unsigned int n = 1u + std::rand() % 10u; Dart d = add_face_topo(n); count += n; @@ -155,7 +155,7 @@ class CMap2TopoTest: public CMap2, public ::testing::Test void add_closed_surfaces() { darts_.clear(); - unsigned int n = 0u; + unsigned int n; // Generate NB_MAX random 1-faces (without boundary) for (unsigned int i = 0u; i < NB_MAX; ++i) @@ -164,8 +164,8 @@ class CMap2TopoTest: public CMap2, public ::testing::Test Dart d = Inherit::Inherit::add_face_topo(n); darts_.push_back(d); } - // Sew some pairs off 1-egdes - for (unsigned int i = 0u; i < 3u*NB_MAX; ++i) + // Sew some pairs off 1-edges + for (unsigned int i = 0u; i < 3u * NB_MAX; ++i) { Dart e1 = darts_[std::rand() % NB_MAX]; n = std::rand() % 10u; @@ -175,7 +175,7 @@ class CMap2TopoTest: public CMap2, public ::testing::Test n = std::rand() % 10u; while (n-- > 0u) e2 = phi1(e2); - n = 1+std::rand()%3u; + n = 1 + std::rand() % 3u; while (n-- > 0u && phi2(e1) == e1 && phi2(e2) == e2 && e2 != e1) { phi2_sew(e2, e1); @@ -184,10 +184,10 @@ class CMap2TopoTest: public CMap2, public ::testing::Test } } // Close de map - foreach_dart( [&] (Dart d) - { - if (phi2(d) == d) close_hole_topo(d); - }); + foreach_dart([&](Dart d) + { + if (phi2(d) == d) close_hole_topo(d); + }); } }; @@ -207,14 +207,12 @@ TEST_F(CMap2TopoTest, random_map_generators) /*! * \brief Sewing and unsewing darts correctly changes the topological relations. - * The test perfoms NB_MAX sewing and unsewing on randomly chosen dart of darts_. + * The test performs NB_MAX sewing and unsewing on randomly chosen dart of darts_. * The map integrity is not preserved (this test creates fixed points for PHI2). */ TEST_F(CMap2TopoTest, phi2_sew_unsew) { - unsigned int count_vertices = add_faces(NB_MAX); - unsigned int count_faces = NB_MAX; - unsigned int count_volumes = NB_MAX; + add_faces(NB_MAX); for (unsigned int i = 0u; i < NB_MAX; ++i) { @@ -227,7 +225,7 @@ TEST_F(CMap2TopoTest, phi2_sew_unsew) while (e0 == d0) e0 = darts_[std::rand() % NB_MAX]; phi2_unsew(e0); - phi2_sew(d0,e0); + phi2_sew(d0, e0); EXPECT_TRUE(phi2(d0) == e0); EXPECT_TRUE(phi2(e0) == d0); } @@ -256,11 +254,11 @@ TEST_F(CMap2TopoTest, add_face_topo) unsigned int count_vertices = 11u + add_faces(NB_MAX); - EXPECT_EQ(nb_darts(), 2u*count_vertices); + EXPECT_EQ(nb_darts(), 2u * count_vertices); EXPECT_EQ(nb_cells(), count_vertices); EXPECT_EQ(nb_cells(), count_vertices); - EXPECT_EQ(nb_cells(), 2u*(NB_MAX+2u)); - EXPECT_EQ(nb_cells(), NB_MAX+2u); + EXPECT_EQ(nb_cells(), 2u * (NB_MAX + 2u)); + EXPECT_EQ(nb_cells(), NB_MAX + 2u); EXPECT_TRUE(check_map_integrity()); } @@ -282,18 +280,18 @@ TEST_F(CMap2TopoTest, cut_edge_topo) unsigned int k1 = degree(Face(d)); unsigned int k2 = degree(Face(phi2(d))); cut_edge_topo(d); - if (same_cell(Face(d),Face(phi2(d)))) + if (same_cell(Face(d), Face(phi2(d)))) { - EXPECT_EQ(degree(Face(d)), k1+2u); + EXPECT_EQ(degree(Face(d)), k1 + 2u); } else { - EXPECT_EQ(degree(Face(d)), k1+1u); - EXPECT_EQ(degree(Face(phi2(d))), k2+1u); + EXPECT_EQ(degree(Face(d)), k1 + 1u); + EXPECT_EQ(degree(Face(phi2(d))), k2 + 1u); } } - EXPECT_EQ(nb_cells(), count_vertices+NB_MAX); - EXPECT_EQ(nb_cells(), count_edges+NB_MAX); + EXPECT_EQ(nb_cells(), count_vertices + NB_MAX); + EXPECT_EQ(nb_cells(), count_edges + NB_MAX); EXPECT_EQ(nb_cells(), count_faces); EXPECT_EQ(nb_cells(), count_volumes); EXPECT_TRUE(check_map_integrity()); @@ -316,7 +314,7 @@ TEST_F(CMap2TopoTest, cut_face_topo) for (Dart d: darts_) { unsigned int k = degree(Face(d)); - if (k>1u) + if (k > 1u) { Dart e = d; // find a second dart in the face of d (distinct from d) unsigned int i = std::rand() % 10u; @@ -326,7 +324,7 @@ TEST_F(CMap2TopoTest, cut_face_topo) cut_face_topo(d, e); ++count_edges; ++count_faces; - EXPECT_EQ(degree(Face(d))+degree(Face(e)), k+2); + EXPECT_EQ(degree(Face(d)) + degree(Face(e)), k + 2); } } EXPECT_EQ(nb_cells(), count_vertices); @@ -338,8 +336,7 @@ TEST_F(CMap2TopoTest, cut_face_topo) /*! \brief Closing a map add one face per holes. * The test closes the holes of a randomly generated open surface. - * The number of generated cells is correct and the map integrity is preserved. - * And closing a map soundly complete the cell indexation + * The map integrity is preserved and the cell indexation is soundly completed */ TEST_F(CMap2TopoTest, close_map) { @@ -353,32 +350,33 @@ TEST_F(CMap2TopoTest, close_map) add_attribute("volumes"); EXPECT_TRUE(check_map_integrity()); - // create some random holes (full removalor partial unsewing of faces) + // create some random holes (full removal or partial unsewing of faces) for (Dart d: darts_) { - if (std::rand()%2 ==1) { - unsigned int n = std::rand()%10; + if (std::rand() % 2 == 1) + { + unsigned int n = std::rand() % 10u; unsigned int k = degree(Face(d)); - foreach_dart_of_orbit_until(Face(d), [&] (Dart e) + foreach_dart_of_orbit_until(Face(d), [&](Dart e) { Dart e2 = phi2(e); phi2_unsew(e); // correct indexation of vertices - if (!same_open_vertex(e2, phi1(e))) new_open_vertex_embedding(e2); - if (!same_open_vertex(e, phi1(e2))) new_open_vertex_embedding(e); + if (!same_open_vertex(e2, phi1(e))) new_open_vertex_embedding(e2); + if (!same_open_vertex(e, phi1(e2))) new_open_vertex_embedding(e); // correct indexation of edges new_orbit_embedding(Edge(e2)); // correct indexation of volumes - if (!same_volume(e2,e)) new_orbit_embedding(Volume(e)); + if (!same_volume(e2, e)) new_orbit_embedding(Volume(e)); // interrupt the face unsewing after n steps if (n-- <= 0) return false; // control if a partial or full face unsewing has been done --k; return true; }); - // if the face is completely unsewed randomly removes it - if (k == 0 && std::rand()%2 == 1) + // if the face is completely unsewn randomly removes it + if (k == 0u && std::rand() % 2 == 1) { Dart e = d; Dart it = phi1(e); @@ -399,9 +397,9 @@ TEST_F(CMap2TopoTest, close_map) TEST_F(CMap2TopoTest, degree) { - Face f = this->add_face_topo(10); + Face f = this->add_face_topo(10u); - EXPECT_EQ(degree(f),10); + EXPECT_EQ(degree(f), 10u); } #undef NB_MAX From b7c6222b842e20b580ce8e61591ffd770c02b0fb Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Tue, 8 Mar 2016 17:13:44 +0100 Subject: [PATCH 279/402] genus --- cgogn/core/tests/cmap/cmap2_topo_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cgogn/core/tests/cmap/cmap2_topo_test.cpp b/cgogn/core/tests/cmap/cmap2_topo_test.cpp index dc6df2b9..250e324b 100644 --- a/cgogn/core/tests/cmap/cmap2_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_topo_test.cpp @@ -150,7 +150,7 @@ class CMap2TopoTest : public CMap2, public ::testing::Test } /*! - * \brief Generate a set of closed surfaces with arbitrary genius. + * \brief Generate a set of closed surfaces with arbitrary genus. */ void add_closed_surfaces() { From 8df715d763e77977eecfeeaea872fc44cbbbf7e0 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Tue, 8 Mar 2016 17:32:44 +0100 Subject: [PATCH 280/402] lambda indent --- cgogn/core/tests/cmap/cmap2_test.cpp | 36 +++++++++++------------ cgogn/core/tests/cmap/cmap2_topo_test.cpp | 6 ++-- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/cgogn/core/tests/cmap/cmap2_test.cpp b/cgogn/core/tests/cmap/cmap2_test.cpp index b32c0459..f5526062 100644 --- a/cgogn/core/tests/cmap/cmap2_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_test.cpp @@ -134,30 +134,30 @@ class CMap2Test : public ::testing::Test } // Close the map (remove remaining boundary) cmap_.foreach_dart([&](Dart d) - { - if (cmap_.phi2(d) == d) mbuild.close_hole_topo(d); - }); + { + if (cmap_.phi2(d) == d) mbuild.close_hole_topo(d); + }); // Embed the map cmap_.foreach_dart([&](Dart d) - { - mbuild.new_orbit_embedding(CDart(d)); - }); + { + mbuild.new_orbit_embedding(CDart(d)); + }); cmap_.foreach_cell([&](Vertex v) - { - mbuild.new_orbit_embedding(v); - }); + { + mbuild.new_orbit_embedding(v); + }); cmap_.foreach_cell([&](Edge e) - { - mbuild.new_orbit_embedding(e); - }); + { + mbuild.new_orbit_embedding(e); + }); cmap_.foreach_cell([&](Face f) - { - mbuild.new_orbit_embedding(f); - }); + { + mbuild.new_orbit_embedding(f); + }); cmap_.foreach_cell([&](Volume w) - { - mbuild.new_orbit_embedding(w); - }); + { + mbuild.new_orbit_embedding(w); + }); } }; diff --git a/cgogn/core/tests/cmap/cmap2_topo_test.cpp b/cgogn/core/tests/cmap/cmap2_topo_test.cpp index 250e324b..dacba8fe 100644 --- a/cgogn/core/tests/cmap/cmap2_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_topo_test.cpp @@ -185,9 +185,9 @@ class CMap2TopoTest : public CMap2, public ::testing::Test } // Close de map foreach_dart([&](Dart d) - { - if (phi2(d) == d) close_hole_topo(d); - }); + { + if (phi2(d) == d) close_hole_topo(d); + }); } }; From fa65d24a8359abbd405c24a2998cb45153778738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 8 Mar 2016 19:24:32 +0100 Subject: [PATCH 281/402] Fixed a bug when swapping the face or volume chunk array container during the loading. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/surface_import.h | 7 ++++++- cgogn/io/volume_import.h | 8 +++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index 9aaf14ec..c7aad940 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -117,7 +117,6 @@ class SurfaceImport : public MeshImportGen mbuild.template create_embedding(); mbuild.template swap_chunk_array_container(this->vertex_attributes_); - mbuild.template swap_chunk_array_container(this->face_attributes_); typename Map::template VertexAttributeHandler> darts_per_vertex = map.template add_attribute, Vertex::ORBIT>("darts_per_vertex"); @@ -204,6 +203,12 @@ class SurfaceImport : public MeshImportGen if (need_vertex_unicity_check) map.template enforce_unique_orbit_embedding(); + if (this->face_attributes_.get_nb_attributes() > 0) + { + mbuild.template create_embedding(); + mbuild.template swap_chunk_array_container(this->face_attributes_); + } + map.remove_attribute(darts_per_vertex); this->clear(); } diff --git a/cgogn/io/volume_import.h b/cgogn/io/volume_import.h index c68def69..25c0595c 100644 --- a/cgogn/io/volume_import.h +++ b/cgogn/io/volume_import.h @@ -111,7 +111,7 @@ class VolumeImport : public MeshImportGen mbuild.template create_embedding(); mbuild.template swap_chunk_array_container(this->vertex_attributes_); - mbuild.template swap_chunk_array_container(this->volume_attributes_); + typename Map::template VertexAttributeHandler> darts_per_vertex = map.template add_attribute, Vertex::ORBIT>("darts_per_vertex"); unsigned int index = 0u; @@ -303,6 +303,12 @@ class VolumeImport : public MeshImportGen std::cout << "Map closed (" << nbBoundaryFaces << " boundary faces / " << nbH << " holes)" << std::endl; } + if (this->volume_attributes_.get_nb_attributes() > 0) + { + mbuild.template create_embedding(); + mbuild.template swap_chunk_array_container(this->volume_attributes_); + } + return true; } From bd9638ef0a2841a7342733733c44d2fdf4b95b79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 8 Mar 2016 19:25:31 +0100 Subject: [PATCH 282/402] Added class CharArrayBuffer and ImemoryStream to avoid unnecessary copies. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/io_utils.cpp | 4 ++ cgogn/io/io_utils.h | 118 ++++++++++++++++++++++++++++++++++++++++++ cgogn/io/vtk_io.h | 102 ++++++++++++++++-------------------- 3 files changed, 168 insertions(+), 56 deletions(-) diff --git a/cgogn/io/io_utils.cpp b/cgogn/io/io_utils.cpp index 08e07b91..f8036716 100644 --- a/cgogn/io/io_utils.cpp +++ b/cgogn/io/io_utils.cpp @@ -223,6 +223,10 @@ CGOGN_IO_API DataType get_data_type(const std::string& type_name) return DataType::UNKNOWN; } +CharArrayBuffer::~CharArrayBuffer() {} + +IMemoryStream::~IMemoryStream() {} + } // namespace io } // namespace cgogn diff --git a/cgogn/io/io_utils.h b/cgogn/io/io_utils.h index 8070693a..c65ccec6 100644 --- a/cgogn/io/io_utils.h +++ b/cgogn/io/io_utils.h @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -129,6 +130,123 @@ inline typename std::enable_if::value && !std::is_floatin } } // namespace internal + + +/** + * @brief The CharArrayBuffer class + * A minimalist buffer that read directly from the string given at the construction instead of copying it. + * USE WITH CAUTION : the behaviour is undefined if a CharArrayBuffer's string is modified during its lifetime. + */ +class CGOGN_IO_API CharArrayBuffer : public std::streambuf +{ +public: + using Inherit = std::streambuf; + using Self = CharArrayBuffer; + using char_type = Inherit::char_type; + using traits_type = Inherit::traits_type; // = char_traits + + inline CharArrayBuffer(const char* begin, const char*end) : + begin_(begin) + ,end_(end) + ,current_(begin) + { + cgogn_assert(begin < end); + } + + inline explicit CharArrayBuffer(const char* str) : + begin_(str) + ,end_(str + std::strlen(str)) + ,current_(str) + {} + + virtual ~CharArrayBuffer(); +private: + virtual void imbue(const std::locale& __loc) override + { + std::cerr << "CharArrayBuffer::imbue method not implemented." << std::endl; + return Inherit::imbue(__loc); + } + virtual Inherit*setbuf(char_type*, std::streamsize) override + { + std::cerr << "CharArrayBuffer::setbuf does nothing." << std::endl; + return this; + } + + virtual pos_type seekpos(pos_type, std::ios_base::openmode) override + { + std::cerr << "CharArrayBuffer::setbuf does nothing." << std::endl; + return pos_type(-1); + } + virtual int sync() override + { + std::cerr << "CharArrayBuffer::sync does nothing." << std::endl; + return Inherit::sync(); + } + virtual std::streamsize showmanyc() override + { + return end_ - current_; + } + virtual std::streamsize xsgetn(char_type* __s, std::streamsize __n) override + { + return Inherit::xsgetn(__s, __n); + } + virtual int_type underflow() override + { + if (current_ == end_) + return traits_type::eof(); + return traits_type::to_int_type(*current_); + } + virtual int_type uflow() override + { + if (current_ == end_) + return traits_type::eof(); + return traits_type::to_int_type(*current_++); + } + virtual int_type pbackfail(int_type c) override + { + if (current_ == begin_ || (c != traits_type::eof() && c != current_[-1])) + return traits_type::eof(); + + return traits_type::to_int_type(*--current_); + } + virtual std::streamsize xsputn(const char_type* , std::streamsize ) override + { + std::cerr << "CharArrayBuffer::xsputn does nothing." << std::endl; + return std::streamsize(-1); + } + virtual int_type overflow(int_type c) override + { + return Inherit::overflow(c); + } + +private: + const char* begin_; + const char* end_; + const char* current_; +}; + +/** + * @brief The IMemoryStream class + * A custom istream using the CharArrayBuffer as buffer. + * USE WITH CAUTION : the behaviour is undefined if a IMemoryStream's string is modified during its lifetime. + */ +class CGOGN_IO_API IMemoryStream : public std::istream +{ +public: + using Inherit = std::istream; + using Self = IMemoryStream; + + inline IMemoryStream(const char* str) : Inherit(), + buffer_(str) + { + this->init(&buffer_); + } + + virtual ~IMemoryStream() override; +private: + CharArrayBuffer buffer_; +}; + } // namespace io } // namespace cgogn diff --git a/cgogn/io/vtk_io.h b/cgogn/io/vtk_io.h index d6f3b57b..4438454d 100644 --- a/cgogn/io/vtk_io.h +++ b/cgogn/io/vtk_io.h @@ -336,7 +336,6 @@ protected : std::string header_type("unsigned int"); if (root_node->Attribute("header_type")) header_type = vtk_data_type_to_cgogn_name_of_type(root_node->Attribute("header_type")); -// const unsigned int header_size = (get_data_type(header_type) == DataType::UINT64)? 8u : 4u; const bool compressed = (root_node->Attribute("compressor") && (std::string(root_node->Attribute("compressor")) == "vtkZLibDataCompressor")); @@ -379,14 +378,12 @@ protected : if (data_name.empty()) std::cerr << "import_VTU : Skipping a vertex DataArray without \"Name\" attribute." << std::endl; else { - std::string text(vertex_data->GetText()); + std::string ascii_data(vertex_data->GetText()); + std::vector binary_data; if (binary) - { - std::vector data= this->read_binary_xml_data(text,compressed, get_data_type(header_type)); - text = std::string(reinterpret_cast(&data[0]), data.size()); - } + binary_data = this->read_binary_xml_data(ascii_data,compressed, get_data_type(header_type)); - std::istringstream ss(text); + IMemoryStream ss(binary_data.empty()? ascii_data.c_str() : reinterpret_cast(&binary_data[0])); if (vertex_data == position_data_array_node) { cgogn_assert(nb_comp == 3); @@ -424,68 +421,61 @@ protected : } + for (XMLElement*& cell_data : cell_nodes) { - std::string cell_connectivity; - bool cell_connectivity_is_bin = false; - std::string cell_connectivity_type; - - for (XMLElement* cell_data : cell_nodes) + if (to_lower(std::string(cell_data->Attribute("Name"))) == "connectivity" && (cell_data != cell_nodes.back())) { - const std::string& data_name = to_lower(std::string(cell_data->Attribute("Name"))); - const bool binary = (to_lower(std::string(cell_data->Attribute("format", nullptr))) == "binary"); - unsigned int nb_comp = 1; - cell_data->QueryUnsignedAttribute("NumberOfComponents", &nb_comp); - std::string type = vtk_data_type_to_cgogn_name_of_type(std::string(cell_data->Attribute("type", nullptr))); - - if (data_name.empty()) - std::cerr << "import_VTU : Skipping a cell DataArray without \"Name\" attribute." << std::endl; - else { - std::string text(cell_data->GetText()); - if (binary) - { - std::vector data= this->read_binary_xml_data(text,compressed, get_data_type(header_type)); - text = std::string(reinterpret_cast(&data[0]), data.size()); - } + std::swap(cell_data, cell_nodes.back()); + } + } + + for (XMLElement* cell_data : cell_nodes) + { + const std::string& data_name = to_lower(std::string(cell_data->Attribute("Name"))); + const bool binary = (to_lower(std::string(cell_data->Attribute("format", nullptr))) == "binary"); + unsigned int nb_comp = 1; + cell_data->QueryUnsignedAttribute("NumberOfComponents", &nb_comp); + std::string type = vtk_data_type_to_cgogn_name_of_type(std::string(cell_data->Attribute("type", nullptr))); + + if (data_name.empty()) + std::cerr << "import_VTU : Skipping a cell DataArray without \"Name\" attribute." << std::endl; + else { + std::string ascii_data(cell_data->GetText()); + std::vector binary_data; + if (binary) + binary_data = this->read_binary_xml_data(ascii_data,compressed, get_data_type(header_type)); - std::istringstream ss(text); - if (data_name == "connectivity") + IMemoryStream mem_strem(binary_data.empty()? ascii_data.c_str() : reinterpret_cast(&binary_data[0])); + if (data_name == "connectivity") + { + const unsigned int last_offset = this->offsets_.get_vec()->back(); + auto cells = DataInputGen::template newDataIO(type); + cells->read_n(mem_strem, last_offset,binary,true); + this->cells_ = *dynamic_cast_unique_ptr>(cells->simplify()); + } + else { + if (data_name == "offsets") { - cell_connectivity_is_bin = binary; - cell_connectivity_type = std::move(type); - cell_connectivity = std::move(text); + auto offsets = DataInputGen::template newDataIO(type); + offsets->read_n(mem_strem, nb_cells,binary,true); + this->offsets_ = *dynamic_cast_unique_ptr>(offsets->simplify()); } else { - if (data_name == "offsets") + if (data_name == "types") { - auto offsets = DataInputGen::template newDataIO(type); - offsets->read_n(ss, nb_cells,binary,true); - this->offsets_ = *dynamic_cast_unique_ptr>(offsets->simplify()); + auto types = DataInputGen::template newDataIO(type); + types->read_n(mem_strem, nb_cells,binary,true); + this->cell_types_ = *dynamic_cast_unique_ptr>(types->simplify()); } else { - if (data_name == "types") - { - auto types = DataInputGen::template newDataIO(type); - types->read_n(ss, nb_cells,binary,true); - this->cell_types_ = *dynamic_cast_unique_ptr>(types->simplify()); - } - else { - std::cout << "Reading cell attribute \"" << data_name << "\" of type " << type << "." << std::endl; - auto cell_att = DataInputGen::template newDataIO(type, nb_comp); - cell_att->read_n(ss, nb_cells,binary,true); - this->add_cell_attribute(*cell_att, data_name); - } + std::cout << "Reading cell attribute \"" << data_name << "\" of type " << type << "." << std::endl; + auto cell_att = DataInputGen::template newDataIO(type, nb_comp); + cell_att->read_n(mem_strem, nb_cells,binary,true); + this->add_cell_attribute(*cell_att, data_name); } } } } - - { - std::istringstream ss(cell_connectivity); - const unsigned int last_offset = this->offsets_.get_vec()->back(); - auto cells = DataInputGen::template newDataIO(cell_connectivity_type); - cells->read_n(ss, last_offset,cell_connectivity_is_bin,true); - this->cells_ = *dynamic_cast_unique_ptr>(cells->simplify()); - } } return true; } From 6245c183e31612aa8d67957ad5b539427dce5fd7 Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Wed, 9 Mar 2016 11:21:28 +0100 Subject: [PATCH 283/402] minor updates --- cgogn/core/cmap/cmap0.h | 4 +-- cgogn/core/cmap/cmap1.h | 5 ++- cgogn/core/cmap/cmap2.h | 20 +++++------ cgogn/core/cmap/map_base.h | 41 ++++++++++++----------- cgogn/core/tests/cmap/cmap1_topo_test.cpp | 12 +++---- cgogn/core/tests/cmap/cmap2_test.cpp | 16 ++++----- cgogn/core/tests/cmap/cmap2_topo_test.cpp | 12 +++---- 7 files changed, 55 insertions(+), 55 deletions(-) diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index f1c5ab1f..05d7965c 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -98,11 +98,11 @@ class CMap0_T : public MapBase /*! * \brief Init an newly added dart. */ - inline void init_dart(Dart /*d*/) + inline void init_dart(Dart) { } - inline bool check_integrity(Dart /*d*/) const + inline bool check_integrity(Dart) const { return true; } diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 318a69bf..93599afb 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -125,7 +125,8 @@ class CMap1_T : public CMap0_T (*phi_1_)[d.index] = d; } - inline bool check_integrity(Dart d) const { + inline bool check_integrity(Dart d) const + { return (phi1(phi_1(d)) == d && phi_1(phi1(d)) == d); } @@ -363,8 +364,6 @@ class CMap1_T : public CMap0_T return (it == f.dart); } -protected: - /******************************************************************************* * Orbits traversal *******************************************************************************/ diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index c2206fe3..7aca2cb1 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -315,9 +315,9 @@ class CMap2_T : public CMap1_T { CGOGN_CHECK_CONCRETE_TYPE; - const Vertex v = cut_edge_topo(e); - const Dart nf = phi2(e); - const Dart f = phi2(v); + const Dart v = cut_edge_topo(e.dart); + const Dart nf = phi2(e); + const Dart f = phi2(v); if (this->template is_embedded()) { @@ -326,27 +326,27 @@ class CMap2_T : public CMap1_T } if (this->template is_embedded()) - this->new_orbit_embedding(v); + this->new_orbit_embedding(Vertex(v)); if (this->template is_embedded()) { - this->template copy_embedding(nf, e); + this->template copy_embedding(nf, e.dart); this->new_orbit_embedding(Edge(v)); } if (this->template is_embedded()) { - this->template copy_embedding(v, e); + this->template copy_embedding(v, e.dart); this->template copy_embedding(nf, f); } if (this->template is_embedded()) { - this->template copy_embedding(v, e); - this->template copy_embedding(nf, e); + this->template copy_embedding(v, e.dart); + this->template copy_embedding(nf, e.dart); } - return v; + return Vertex(v); } protected: @@ -479,7 +479,7 @@ class CMap2_T : public CMap1_T if (phi2(d) == d) { close_hole_topo(d); - const Face new_face = phi2(d); + const Face new_face = Face(phi2(d)); if (this->template is_embedded()) { diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 461fc387..113aa702 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -401,40 +401,39 @@ class MapBase : public MapBaseData cgogn_message_assert(this->template is_embedded(), "Invalid parameter: orbit not embedded"); const ConcreteMap* cmap = to_concrete(); - AttributeHandler marker = add_attribute("__tmp_marker"); + AttributeHandler counter = add_attribute("__tmp_marker"); bool result = true; - const Self* const_map = static_cast(this); - const typename Inherit::template ChunkArrayContainer& container = - const_map->template get_attribute_container(); + const typename Inherit::template ChunkArrayContainer& container = this->attributes_[ORBIT]; // a marker is initialized to false for each "used" index of the container for (unsigned int i = container.begin(), end = container.end(); i != end; container.next(i)) - marker[i] = 0; + counter[i] = 0; // Check that the indexation of cells is correct foreach_cell_until_dart_marking([&] (CellType c) { - // insure that two cells do not share the same index - if (marker[this->template get_embedding(c.dart)] > 0) - { - result = false; - std::cerr << "Two cells with same index in orbit " << orbit_name(ORBIT) << std::endl; - return false; - } - marker[this->template get_embedding(c.dart)] = 1; - // check used indices are valid unsigned int idx = this->get_embedding(c); + // check used indices are valid if (idx == EMBNULL) { result = false; std::cerr << "EMBNULL found in orbit " << orbit_name(ORBIT) << std::endl; - return false; + return result; } + // ensure that two cells do not share the same index + if (counter[idx] > 0) + { + result = false; + std::cerr << "Two cells with same index in orbit " << orbit_name(ORBIT) << std::endl; + return result; + } + counter[idx] = 1; // check all darts of the cell use the same index (distinct to EMBNULL) cmap->foreach_dart_of_orbit_until(c, [&] (Dart d) { - if (this->template get_embedding(d) != idx) result = false; + if (this->get_embedding(CellType(d)) != idx) + result = false; if (!result) std::cerr << "Different indices in orbit " << orbit_name(ORBIT) << std::endl; return result; @@ -447,7 +446,7 @@ class MapBase : public MapBaseData { for (unsigned int i = container.begin(), end = container.end(); i != end; container.next(i)) { - if (marker[i] == 0) + if (counter[i] == 0) { result = false; std::cerr << "Some cells are not used in orbit " << orbit_name(ORBIT) << std::endl; @@ -455,7 +454,7 @@ class MapBase : public MapBaseData } } } - remove_attribute(marker); + remove_attribute(counter); return result; } @@ -465,8 +464,10 @@ class MapBase : public MapBaseData bool result = true; // check the integrity of topological relations or the correct sewing of darts - foreach_dart_until( [&cmap,&result] (Dart d) { - if (!cmap->check_integrity(d)) result = false; + foreach_dart_until([&cmap, &result] (Dart d) + { + if (!cmap->check_integrity(d)) + result = false; return result; }); if (!result) diff --git a/cgogn/core/tests/cmap/cmap1_topo_test.cpp b/cgogn/core/tests/cmap/cmap1_topo_test.cpp index 7de090c8..4c10dee0 100644 --- a/cgogn/core/tests/cmap/cmap1_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_topo_test.cpp @@ -171,7 +171,7 @@ TEST_F(CMap1TopoTest, remove_face) unsigned int count_vertices = add_faces(NB_MAX); unsigned int count_faces = NB_MAX; - for (Dart d: darts_) + for (Dart d : darts_) { if (std::rand() % 3 == 1) { @@ -195,7 +195,7 @@ TEST_F(CMap1TopoTest, split_vertex_topo) { unsigned int count_vertices = add_faces(NB_MAX); - for (Dart d: darts_) + for (Dart d : darts_) { unsigned int k = degree(Face(d)); split_vertex_topo(d); @@ -217,7 +217,7 @@ TEST_F(CMap1TopoTest, remove_vertex) unsigned int count_vertices = add_faces(NB_MAX); unsigned int count_faces = NB_MAX; - for (Dart d: darts_) + for (Dart d : darts_) { unsigned int k = degree(Face(d)); if (k > 1) @@ -248,13 +248,13 @@ TEST_F(CMap1TopoTest, reverse_face_topo) { unsigned int count_vertices = add_faces(NB_MAX); - for (Dart d: darts_) + for (Dart d : darts_) { unsigned int k = degree(Face(d)); std::vector face_darts; face_darts.reserve(k); - foreach_dart_of_orbit(Face(d), [&](Dart e) + foreach_dart_of_orbit(Face(d), [&] (Dart e) { face_darts.push_back(e); }); @@ -263,7 +263,7 @@ TEST_F(CMap1TopoTest, reverse_face_topo) EXPECT_EQ(degree(Face(d)), k); d = phi1(d); - foreach_dart_of_orbit(Face(d), [&](Dart e) + foreach_dart_of_orbit(Face(d), [&] (Dart e) { EXPECT_TRUE(face_darts.back() == e); face_darts.pop_back(); diff --git a/cgogn/core/tests/cmap/cmap2_test.cpp b/cgogn/core/tests/cmap/cmap2_test.cpp index f5526062..80d42bb1 100644 --- a/cgogn/core/tests/cmap/cmap2_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_test.cpp @@ -133,28 +133,28 @@ class CMap2Test : public ::testing::Test } } // Close the map (remove remaining boundary) - cmap_.foreach_dart([&](Dart d) + cmap_.foreach_dart([&] (Dart d) { if (cmap_.phi2(d) == d) mbuild.close_hole_topo(d); }); // Embed the map - cmap_.foreach_dart([&](Dart d) + cmap_.foreach_dart([&] (Dart d) { mbuild.new_orbit_embedding(CDart(d)); }); - cmap_.foreach_cell([&](Vertex v) + cmap_.foreach_cell([&] (Vertex v) { mbuild.new_orbit_embedding(v); }); - cmap_.foreach_cell([&](Edge e) + cmap_.foreach_cell([&] (Edge e) { mbuild.new_orbit_embedding(e); }); - cmap_.foreach_cell([&](Face f) + cmap_.foreach_cell([&] (Face f) { mbuild.new_orbit_embedding(f); }); - cmap_.foreach_cell([&](Volume w) + cmap_.foreach_cell([&] (Volume w) { mbuild.new_orbit_embedding(w); }); @@ -194,7 +194,7 @@ TEST_F(CMap2Test, cut_edge) { add_closed_surfaces(); - for (Dart d: darts_) cmap_.cut_edge(d); + for (Dart d : darts_) cmap_.cut_edge(d); EXPECT_TRUE(cmap_.check_map_integrity()); } @@ -206,7 +206,7 @@ TEST_F(CMap2Test, cut_face) { add_closed_surfaces(); - for (Dart d: darts_) + for (Dart d : darts_) { if (cmap_.degree(Face(d)) > 1u) { diff --git a/cgogn/core/tests/cmap/cmap2_topo_test.cpp b/cgogn/core/tests/cmap/cmap2_topo_test.cpp index dacba8fe..18b11596 100644 --- a/cgogn/core/tests/cmap/cmap2_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_topo_test.cpp @@ -94,7 +94,7 @@ class CMap2TopoTest : public CMap2, public ::testing::Test { bool result = false; - foreach_dart_of_orbit_until(Volume(d), [&](Dart vit) + foreach_dart_of_orbit_until(Volume(d), [&] (Dart vit) { if (vit == e) result = true; return !result; @@ -184,7 +184,7 @@ class CMap2TopoTest : public CMap2, public ::testing::Test } } // Close de map - foreach_dart([&](Dart d) + foreach_dart([&] (Dart d) { if (phi2(d) == d) close_hole_topo(d); }); @@ -275,7 +275,7 @@ TEST_F(CMap2TopoTest, cut_edge_topo) unsigned int count_faces = nb_cells(); unsigned int count_volumes = nb_cells(); - for (Dart d: darts_) + for (Dart d : darts_) { unsigned int k1 = degree(Face(d)); unsigned int k2 = degree(Face(phi2(d))); @@ -311,7 +311,7 @@ TEST_F(CMap2TopoTest, cut_face_topo) unsigned int count_faces = nb_cells(); unsigned int count_volumes = nb_cells(); - for (Dart d: darts_) + for (Dart d : darts_) { unsigned int k = degree(Face(d)); if (k > 1u) @@ -351,14 +351,14 @@ TEST_F(CMap2TopoTest, close_map) EXPECT_TRUE(check_map_integrity()); // create some random holes (full removal or partial unsewing of faces) - for (Dart d: darts_) + for (Dart d : darts_) { if (std::rand() % 2 == 1) { unsigned int n = std::rand() % 10u; unsigned int k = degree(Face(d)); - foreach_dart_of_orbit_until(Face(d), [&](Dart e) + foreach_dart_of_orbit_until(Face(d), [&] (Dart e) { Dart e2 = phi2(e); phi2_unsew(e); From 7988a7a07ce128cc81cefc7e34749ea355d94097 Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Wed, 9 Mar 2016 11:25:10 +0100 Subject: [PATCH 284/402] remove useless cmap/sanity_check file --- cgogn/core/CMakeLists.txt | 1 - cgogn/core/cmap/sanity_check.h | 109 ----------------------------- cgogn/io/examples/cmap2_import.cpp | 6 +- 3 files changed, 3 insertions(+), 113 deletions(-) delete mode 100644 cgogn/core/cmap/sanity_check.h diff --git a/cgogn/core/CMakeLists.txt b/cgogn/core/CMakeLists.txt index 8a21eb6e..0036602e 100644 --- a/cgogn/core/CMakeLists.txt +++ b/cgogn/core/CMakeLists.txt @@ -20,7 +20,6 @@ set(HEADER_FILES cmap/cmap3.h cmap/cmap3_builder.h cmap/attribute_handler.h - cmap/sanity_check.h container/chunk_array_container.h container/chunk_array_factory.h diff --git a/cgogn/core/cmap/sanity_check.h b/cgogn/core/cmap/sanity_check.h deleted file mode 100644 index 1a846ab2..00000000 --- a/cgogn/core/cmap/sanity_check.h +++ /dev/null @@ -1,109 +0,0 @@ -/******************************************************************************* -* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * -* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * -* * -* This library is free software; you can redistribute it and/or modify it * -* under the terms of the GNU Lesser General Public License as published by the * -* Free Software Foundation; either version 2.1 of the License, or (at your * -* option) any later version. * -* * -* This library is distributed in the hope that it will be useful, but WITHOUT * -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * -* for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with this library; if not, write to the Free Software Foundation, * -* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * -* * -* Web site: http://cgogn.unistra.fr/ * -* Contact information: cgogn@unistra.fr * -* * -*******************************************************************************/ - -#ifndef CORE_CMAP_SANITY_CHECK_H_ -#define CORE_CMAP_SANITY_CHECK_H_ - -namespace cgogn -{ - -/** - * \brief Tests if each \p ORBIT orbit of the map has a unique index in the \p ORBIT attribute container - * \details This is a injectivity test from the darts embedding to the attribute indices - * - * \tparam ORBIT [description] - * \return [description] - */ -template -bool is_orbit_embedding_unique(MAP& map) -{ - static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - cgogn_message_assert(map.template is_embedded(), "Invalid parameter: orbit not embedded"); - - typename MAP::template AttributeHandler counter = map.template add_attribute("__tmp_counter"); - for (unsigned int& i : counter) i = 0; - - bool result = true; - map.template foreach_cell([&] (Cell c) - { - if (counter[c] > 0) - { - result = false; - std::cout << "Index #" << map.get_embedding(c) << " of attribute container of orbit " << orbit_name(ORBIT) << " is referenced by more than one orbit" << std::endl; - } - counter[c]++; - }); - - map.remove_attribute(counter); - return result; -} - -/** - * \brief Tests if each index in the \p ORBIT attribute container is referenced the good number of times, - * \details The number of references to an index in the \p ORBIT attribute container should be equal to the - * number of darts that are embedded on this index - * - * \tparam ORBIT [description] - * \return [description] - */ -template -bool is_container_well_referenced(MAP& map) -{ - static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - cgogn_message_assert(map.template is_embedded(), "Invalid parameter: orbit not embedded"); - - typename MAP::template AttributeHandler counter = map.template add_attribute("__tmp_counter"); - - const MAP& const_map = static_cast(map); - const typename MAP::template ChunkArrayContainer& container = const_map.template get_attribute_container(); - - // a counter is initialized to 0 for each "used" index of the container - for (unsigned int i = container.begin(), end = container.end(); i != end; container.next(i)) - counter[i] = 0; - - // for each dart of the map, the counter corresponding to its embedding index is incremented - map.foreach_dart([&] (Dart d) { counter[map.template get_embedding(d)]++; }); - - bool result = true; - for (unsigned int i = container.begin(), end = container.end(); i != end; container.next(i)) - { - unsigned int nb_refs = container.get_nb_refs(i); - if (nb_refs == 1) - { - result = false; - std::cout << "Index #" << i << " has 1 ref (considered used) but is not referenced by any dart" << std::endl; - } - if (nb_refs != counter[i] + 1) - { - result = false; - std::cout << "Index #" << i << " has " << nb_refs << " refs but is referenced by " << counter[i] << " darts (nb_refs should be equal to " << counter[i] + 1 << ")" << std::endl; - } - } - - map.remove_attribute(counter); - return result; -} - -} // namespace cgogn - -#endif // CORE_CMAP_SANITY_CHECK_H_ diff --git a/cgogn/io/examples/cmap2_import.cpp b/cgogn/io/examples/cmap2_import.cpp index d3385c83..c6ea8081 100644 --- a/cgogn/io/examples/cmap2_import.cpp +++ b/cgogn/io/examples/cmap2_import.cpp @@ -69,6 +69,7 @@ int main(int argc, char** argv) map.enable_topo_cache(); map.enable_topo_cache(); + std::cout << "Map integrity : " << std::boolalpha << map.check_map_integrity() << std::endl; // std::cout << "Vertex orbits are well embedded ? -> " << std::boolalpha << cgogn::is_well_embedded(map) << std::endl; // std::cout << "Face orbits are well embedded ? -> " << std::boolalpha << cgogn::is_well_embedded(map) << std::endl; @@ -76,9 +77,8 @@ int main(int argc, char** argv) // std::cout << "Vertex orbit is uniquely embedded ? -> " << std::boolalpha << cgogn::is_orbit_embedding_unique(map) << std::endl; // std::cout << "Face orbit is uniquely embedded ? -> " << std::boolalpha << cgogn::is_orbit_embedding_unique(map) << std::endl; - std::cout << "Vertex container is well referenced ? -> " << std::boolalpha << cgogn::is_container_well_referenced(map) << std::endl; - std::cout << "Face container is well referenced ? -> " << std::boolalpha << cgogn::is_container_well_referenced(map) << std::endl; - +// std::cout << "Vertex container is well referenced ? -> " << std::boolalpha << cgogn::is_container_well_referenced(map) << std::endl; +// std::cout << "Face container is well referenced ? -> " << std::boolalpha << cgogn::is_container_well_referenced(map) << std::endl; unsigned int nb_faces = 0; map.foreach_cell([&nb_faces] (Map2::Face) { nb_faces++; }); From 4795afe296c58c9f00c1d5f140303813b0b655cb Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Wed, 9 Mar 2016 11:26:42 +0100 Subject: [PATCH 285/402] remove some includes --- benchmarks/multithreading/bench_multithreading.cpp | 1 - cgogn/io/examples/cmap2_import.cpp | 2 -- 2 files changed, 3 deletions(-) diff --git a/benchmarks/multithreading/bench_multithreading.cpp b/benchmarks/multithreading/bench_multithreading.cpp index d9be7350..18fcf557 100644 --- a/benchmarks/multithreading/bench_multithreading.cpp +++ b/benchmarks/multithreading/bench_multithreading.cpp @@ -25,7 +25,6 @@ #include #include -#include #include #include diff --git a/cgogn/io/examples/cmap2_import.cpp b/cgogn/io/examples/cmap2_import.cpp index c6ea8081..fe0768d2 100644 --- a/cgogn/io/examples/cmap2_import.cpp +++ b/cgogn/io/examples/cmap2_import.cpp @@ -4,11 +4,9 @@ #include #include -#include #include #include - #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) struct MyMapTraits : public cgogn::DefaultMapTraits From ebfc96330173c8f14751c4da7aa4cace960e0191 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 9 Mar 2016 12:00:28 +0100 Subject: [PATCH 286/402] added operator<< for Vec_T MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/geometry/types/vec.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cgogn/geometry/types/vec.h b/cgogn/geometry/types/vec.h index ccfa851c..b203ee1b 100644 --- a/cgogn/geometry/types/vec.h +++ b/cgogn/geometry/types/vec.h @@ -245,6 +245,15 @@ class Vec_T return data_; } + inline friend std::ostream& operator<<(std::ostream& o, const Self& v) + { + o << "("; + for (auto& c : v.data_) + o << c << ","; + o << ")"; + return o; + } + private: Container data_; From 232b981bb2bb952783be152339b685e65822fd8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 9 Mar 2016 12:01:16 +0100 Subject: [PATCH 287/402] fixed a bug when detecting endianness in DataInput. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/data_io.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/cgogn/io/data_io.h b/cgogn/io/data_io.h index 6449173d..d9f2c212 100644 --- a/cgogn/io/data_io.h +++ b/cgogn/io/data_io.h @@ -127,17 +127,18 @@ class DataInput : public DataInputGen if (std::is_same::value) { // if BUFFER_T = T we can directly store the data fp.read(reinterpret_cast(&data_[old_size]), n * sizeof(T)); - if (big_endian != ::cgogn::internal::cgogn_is_little_endian) + if ((big_endian && cgogn::internal::cgogn_is_little_endian) || (!big_endian && cgogn::internal::cgogn_is_big_endian)) { for (auto it = data_.begin() + old_size, end = data_.end() ; it != end; ++it) *it = cgogn::io::internal::swap_endianness(*it); } + if (fp.eof() || fp.bad()) this->reset(); } else { // 2nd case : BUFFER_T and T are different. std::vector buffer(old_size+n); - fp.read(reinterpret_cast(std::addressof(buffer[old_size])), n * sizeof(BUFFER_T)); - if (big_endian != ::cgogn::internal::cgogn_is_little_endian) + fp.read(reinterpret_cast(&buffer[old_size]), n * sizeof(BUFFER_T)); + if ((big_endian && cgogn::internal::cgogn_is_little_endian) || (!big_endian && cgogn::internal::cgogn_is_big_endian)) { for (auto it = buffer.begin() + old_size, end = buffer.end() ; it != end; ++it) *it = cgogn::io::internal::swap_endianness(*it); @@ -147,9 +148,7 @@ class DataInput : public DataInputGen // copy auto dest_it = data_.begin(); for (auto & x : buffer) - { *dest_it++ = internal::convert(x); - } } } else { std::string line; From 5c41e11a160655e196617de8f5599ba9185753a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 9 Mar 2016 12:07:06 +0100 Subject: [PATCH 288/402] base64_decode and zlib_decompress now take a const char* instead of a std::string. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also added move constructor / assignment for CharArrayBuffer and IMemoryStream Signed-off-by: Étienne Schmitt --- cgogn/io/io_utils.cpp | 47 ++++++++++++++++++------ cgogn/io/io_utils.h | 83 +++++++++++++++++++++++++++++++++++++------ cgogn/io/vtk_io.h | 33 ++++++++++------- 3 files changed, 129 insertions(+), 34 deletions(-) diff --git a/cgogn/io/io_utils.cpp b/cgogn/io/io_utils.cpp index f8036716..ed04bab7 100644 --- a/cgogn/io/io_utils.cpp +++ b/cgogn/io/io_utils.cpp @@ -40,7 +40,7 @@ namespace io { #ifdef CGOGN_WITH_ZLIB -CGOGN_IO_API std::vector zlib_decompress(const std::string& input, DataType header_type) +CGOGN_IO_API std::vector zlib_decompress(const char* input, DataType header_type) { std::uint64_t nb_blocks = UINT64_MAX; @@ -49,7 +49,6 @@ CGOGN_IO_API std::vector zlib_decompress(const std::string& input std::vector compressed_size; unsigned int word_size = 4u; - std::string header; std::vector header_data; if (header_type == DataType::UINT64) { @@ -62,7 +61,7 @@ CGOGN_IO_API std::vector zlib_decompress(const std::string& input compressed_size.resize(nb_blocks); } else { - header_data = base64_decode(header, 0, 12); + header_data = base64_decode(input, 0, 12); nb_blocks = *reinterpret_cast(&header_data[0]); uncompressed_block_size = *reinterpret_cast(&header_data[4]); last_block_size = *reinterpret_cast(&header_data[8]); @@ -85,7 +84,7 @@ CGOGN_IO_API std::vector zlib_decompress(const std::string& input compressed_size[i] = *reinterpret_cast(&header_data[4u*i]); } - std::vector data = base64_decode(input, header_end +length, input.size() - header_end - length); + std::vector data = base64_decode(input, header_end +length); std::vector res(uncompressed_block_size*(nb_blocks-1u) + last_block_size); // zlib init @@ -112,10 +111,33 @@ CGOGN_IO_API std::vector zlib_decompress(const std::string& input } #endif -CGOGN_IO_API std::vector base64_decode(const std::string& input, std::size_t begin, std::size_t length) +CGOGN_IO_API std::vector base64_decode(const char* input, std::size_t begin, std::size_t length) { const static char padCharacter('='); - if (length % 4ul) //Sanity check + + // needed if begin = 0 + while (std::isspace(*input)) + ++input; + + for (std::size_t i = 0ul ; i < begin ;) + { + if (!std::isspace(*input)) + ++i; + ++input; + } + + const char* end = input; + std::size_t i = 0ul; + for ( ; i < length && (*end != '\0') ;) + { + if (!std::isspace(*end)) + ++i; + ++end; + } + while (std::isspace(*(end-1))) + --end; + + if (i % 4ul) //Sanity check { std::cerr << "base64_decode : Error : the given length (" << length << ") is not a multiple of 4. This is not valid." << std::endl; std::exit(EXIT_FAILURE); @@ -124,19 +146,22 @@ CGOGN_IO_API std::vector base64_decode(const std::string& input, size_t padding = 0; if (length) { - if (input[begin + length-1] == padCharacter) + if (*(end-1) == padCharacter) padding++; - if (input[begin + length-2] == padCharacter) + if (*(end-2) == padCharacter) padding++; } //Setup a vector to hold the result std::vector decoded_chars; - decoded_chars.reserve(((length/4ul)*3ul) - padding); + decoded_chars.reserve(((i/4ul)*3ul) - padding); long int temp=0; //Holds decoded quanta - std::string::const_iterator cursor = input.begin() + begin; - const std::string::const_iterator end = input.begin() + begin +length; + const char* cursor = input; while (cursor != end) { + cgogn_assert(!std::isspace(*cursor)); + cgogn_assert(!std::isspace(*(cursor+1))); + cgogn_assert(!std::isspace(*(cursor+2))); + cgogn_assert(!std::isspace(*(cursor+3))); for (size_t quantumPosition = 0; quantumPosition < 4; quantumPosition++) { temp <<= 6; diff --git a/cgogn/io/io_utils.h b/cgogn/io/io_utils.h index c65ccec6..b8cdc345 100644 --- a/cgogn/io/io_utils.h +++ b/cgogn/io/io_utils.h @@ -65,10 +65,10 @@ enum DataType }; CGOGN_IO_API FileType get_file_type(const std::string& filename); CGOGN_IO_API DataType get_data_type(const std::string& type_name); -CGOGN_IO_API std::vector base64_decode(const std::string& input, std::size_t begin, std::size_t length); +CGOGN_IO_API std::vector base64_decode(const char* input, std::size_t begin, std::size_t length = std::numeric_limits::max()); #ifdef CGOGN_WITH_ZLIB -CGOGN_IO_API std::vector zlib_decompress(const std::string& input, DataType header_type); +CGOGN_IO_API std::vector zlib_decompress(const char* input, DataType header_type); #endif namespace internal @@ -145,20 +145,52 @@ class CGOGN_IO_API CharArrayBuffer : public std::streambuf using char_type = Inherit::char_type; using traits_type = Inherit::traits_type; // = char_traits - inline CharArrayBuffer(const char* begin, const char*end) : - begin_(begin) - ,end_(end) - ,current_(begin) - { - cgogn_assert(begin < end); - } + inline CharArrayBuffer() : Inherit(), + begin_(nullptr) + ,end_(nullptr) + ,current_(nullptr) + {} - inline explicit CharArrayBuffer(const char* str) : + inline explicit CharArrayBuffer(const char* str) : Inherit(), begin_(str) ,end_(str + std::strlen(str)) ,current_(str) {} + inline CharArrayBuffer(const char* begin, std::size_t size) :Inherit(), + begin_(begin) + ,end_(begin+size) + ,current_(begin) + {} + + CharArrayBuffer(const Self&) = delete; + Self& operator=(const Self&) = delete; + + inline CharArrayBuffer(Self&& other) : Inherit(std::forward(other)) + { + begin_ = other.begin_; + end_ = other.end_; + current_ = other.current_; + other.begin_ = nullptr; + other.end_ = nullptr; + other.current_ = nullptr; + } + + inline Self& operator=(Self&& other) + { + Inherit::operator =(std::forward(other)); + if (&other != this) + { + begin_ = other.begin_; + end_ = other.end_; + current_ = other.current_; + other.begin_ = nullptr; + other.end_ = nullptr; + other.current_ = nullptr; + } + return *this; + } + virtual ~CharArrayBuffer(); private: virtual void imbue(const std::locale& __loc) override @@ -236,12 +268,43 @@ class CGOGN_IO_API IMemoryStream : public std::istream using Inherit = std::istream; using Self = IMemoryStream; + inline IMemoryStream() : Inherit() + { + this->init(&buffer_); + } + inline IMemoryStream(const char* str) : Inherit(), buffer_(str) { this->init(&buffer_); } + inline IMemoryStream(const char* str, std::size_t size) : Inherit(), + buffer_(str,size) + { + this->init(&buffer_); + } + + IMemoryStream(const Self&) = delete; + Self& operator=(const Self&) = delete; + + inline IMemoryStream(Self&& other) : Inherit(std::forward(other)) + { + this->buffer_ = std::move(other.buffer_); + this->init(&buffer_); + } + + inline Self& operator=(Self&& other) + { + Inherit::operator =(std::forward(other)); + if (&other != this) + { + this->buffer_ = std::move(other.buffer_); + this->init(&buffer_); + } + return *this; + } + virtual ~IMemoryStream() override; private: CharArrayBuffer buffer_; diff --git a/cgogn/io/vtk_io.h b/cgogn/io/vtk_io.h index 4438454d..5cd83549 100644 --- a/cgogn/io/vtk_io.h +++ b/cgogn/io/vtk_io.h @@ -94,12 +94,11 @@ protected : virtual void add_vertex_attribute(const DataInputGen& attribute_data, const std::string& attribute_name) = 0; virtual void add_cell_attribute(const DataInputGen& attribute_data, const std::string& attribute_name) = 0; - inline std::vector read_binary_xml_data(std::string& data_str, bool is_compressed, DataType header_type) + inline std::vector read_binary_xml_data(const char*data_str, bool is_compressed, DataType header_type) { - data_str.erase(std::remove_if(data_str.begin(), data_str.end(), [](char c) { return std::isspace(c); }), data_str.end()); if (!is_compressed) { - std::vector decode = base64_decode(data_str, 0, data_str.size()); + std::vector decode = base64_decode(data_str, 0); decode.erase(decode.begin(), decode.begin() + (header_type == DataType::UINT32 ? 4u : 8u)); return decode; } @@ -378,23 +377,27 @@ protected : if (data_name.empty()) std::cerr << "import_VTU : Skipping a vertex DataArray without \"Name\" attribute." << std::endl; else { - std::string ascii_data(vertex_data->GetText()); + const char* ascii_data = vertex_data->GetText(); std::vector binary_data; if (binary) binary_data = this->read_binary_xml_data(ascii_data,compressed, get_data_type(header_type)); - IMemoryStream ss(binary_data.empty()? ascii_data.c_str() : reinterpret_cast(&binary_data[0])); + IMemoryStream mem_stream; + if (binary) + mem_stream = IMemoryStream(reinterpret_cast(&binary_data[0]), binary_data.size()); + else + mem_stream = IMemoryStream(ascii_data); if (vertex_data == position_data_array_node) { cgogn_assert(nb_comp == 3); auto pos = DataInputGen::template newDataIO(type, nb_comp); - pos->read_n(ss, nb_vertices,binary,true); + pos->read_n(mem_stream, nb_vertices,binary,!little_endian); this->add_vertex_attribute(*pos,"position"); this->positions_ = *dynamic_cast_unique_ptr>(pos->simplify()); } else { std::unique_ptr vertex_att = DataInputGen::template newDataIO(type, nb_comp); - vertex_att->read_n(ss, nb_vertices,binary,!little_endian); + vertex_att->read_n(mem_stream, nb_vertices,binary,!little_endian); this->add_vertex_attribute(*vertex_att, data_name); } } @@ -440,37 +443,41 @@ protected : if (data_name.empty()) std::cerr << "import_VTU : Skipping a cell DataArray without \"Name\" attribute." << std::endl; else { - std::string ascii_data(cell_data->GetText()); + const char* ascii_data = cell_data->GetText(); std::vector binary_data; if (binary) binary_data = this->read_binary_xml_data(ascii_data,compressed, get_data_type(header_type)); - IMemoryStream mem_strem(binary_data.empty()? ascii_data.c_str() : reinterpret_cast(&binary_data[0])); + IMemoryStream mem_stream; + if (binary) + mem_stream = IMemoryStream(reinterpret_cast(&binary_data[0]), binary_data.size()); + else + mem_stream = IMemoryStream(ascii_data); if (data_name == "connectivity") { const unsigned int last_offset = this->offsets_.get_vec()->back(); auto cells = DataInputGen::template newDataIO(type); - cells->read_n(mem_strem, last_offset,binary,true); + cells->read_n(mem_stream, last_offset,binary,!little_endian); this->cells_ = *dynamic_cast_unique_ptr>(cells->simplify()); } else { if (data_name == "offsets") { auto offsets = DataInputGen::template newDataIO(type); - offsets->read_n(mem_strem, nb_cells,binary,true); + offsets->read_n(mem_stream, nb_cells,binary,!little_endian); this->offsets_ = *dynamic_cast_unique_ptr>(offsets->simplify()); } else { if (data_name == "types") { auto types = DataInputGen::template newDataIO(type); - types->read_n(mem_strem, nb_cells,binary,true); + types->read_n(mem_stream, nb_cells,binary,!little_endian); this->cell_types_ = *dynamic_cast_unique_ptr>(types->simplify()); } else { std::cout << "Reading cell attribute \"" << data_name << "\" of type " << type << "." << std::endl; auto cell_att = DataInputGen::template newDataIO(type, nb_comp); - cell_att->read_n(mem_strem, nb_cells,binary,true); + cell_att->read_n(mem_stream, nb_cells,binary,!little_endian); this->add_cell_attribute(*cell_att, data_name); } } From 39ddb4b5a22f7ac0b8b2f9d108e4c1d29f1ef0b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 9 Mar 2016 12:07:24 +0100 Subject: [PATCH 289/402] added mesh heart_zlib.vtu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- data/meshes/heart_zlib.vtu | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 data/meshes/heart_zlib.vtu diff --git a/data/meshes/heart_zlib.vtu b/data/meshes/heart_zlib.vtu new file mode 100644 index 00000000..07fd7361 --- /dev/null +++ b/data/meshes/heart_zlib.vtu @@ -0,0 +1,32 @@ + + + + + + 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a6yzwSZbbLPDLnvs84cDDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9+/eNfAgwyxDAjjDLGOL+ZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfb5wwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND/8s8gUYZIhhRhhljHF+M8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvs84cDDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnim58/C5z/5JcAgwwxzAijjDHObyaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPff5wwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDr3/6S4BBhhhmhFHGGOc3E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+fzjgkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eHXP/slwCBDDDPCKGOM85sJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58/HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88M8Cf4BBhhhmhFHGGOc3E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+fzjgkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eHXP/8lwCBDDDPCKGOM85sJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58/HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88Otf/BJgkCGGGWGUMcb5zQSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzx8OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3749S9/CTDIEMOMMMoY4/xmgkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjnDwcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/wT3BNgkCGGGWGUMcb5zQSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzx8OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3749a9+CTDIEMOMMMoY4/xmgkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjnDwcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/z6178EGGSIYUYYZYxxfjPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577POHAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffv2bXwIMMsQwI4wyxji/mWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32+cMBhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ//BPYFGGSIYUYYZYxxfjPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577POHAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffv3bXwIMMsQwI4wyxji/mWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32+cMBhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//t0vAQYZYpgRRhljnN9MMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvv84YBDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1///pcAgwwxzAijjDHObyaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPff5wwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDP0G9AQYZYpgRRhljnN9MMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvv84YBDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1//4ZcAgwwxzAijjDHObyaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPff5wwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDr//4S4BBhhhmhFHGGOc3E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+fzjgkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eHXf/olwCBDDDPCKGOM85sJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58/HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88E9Af4BBhhhmhFHGGOc3E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+fzjgkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eHX//9LgEGGGGaEUcYY5zcTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz5/OOCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754dd//iXAIEMMM8IoY4zzmwkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnz8ccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zw67/8EmCQIYYZYZQxxvnNBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPHw445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745ItvfvjnME+AQYYYZoRRxhjnNxNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPn844JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnh13/9JcAgQwwzwihjjPObCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfPxxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDrv/0SYJAhhhlhlDHG+c0Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8fDjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++PXffwkwyBDDjDDKGOP8ZoJJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY5w8HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/8c5AvwCBDDDPCKGOM85sJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58/HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88Ot//BJgkCGGGWGUMcb5zQSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzx8OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3749T9/CTDIEMOMMMoY4/xmgkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjnDwcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/z6X78EGGSIYUYYZYxxfjPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577POHAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psf/jnEG2CQIYYZYZQxxvnNBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPHw445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvj1v38JMMgQw4wwyhjj/GaCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OcPBxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//Po/vwQYZIhhRhhljHF+M8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvs84cDDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9+/d9fAgwyxDAjjDLGOL+ZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfb5wwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND79yv/w/dLzYyHicLcUhuAEAACBmQRAEQRAEQRAEQRAEd7OdbbbZZnd2ZzvbbLPNNtvczW7uThCEFwRBEARBEARBEARBEF4QBEEQBEEQhBf2ffP/5Q8WAv+/kMOOOOqY40446ZTTzjjrnPMuuOiSy6646prrbrjpltvuuOue+x546JF/PPbEU88898JLr7z2xlvvvPfBR5/867Mvvvrmux9++uW3P/5z4B98CzrksCOOOua4E0465bQzzjrnvAsuuuSyK6665robbrrltjvuuue+Bx565B+PPfHUM8+98NIrr73x1jvvffDRJ//67Iuvvvnuh59++e2P/xz4h9+CDjnsiKOOOe6Ek0457YyzzjnvgosuueyKq6657oabbrntjrvuue+Bhx75x2NPPPXMcy+89Mprb7z1znsffPTJvz774qtvvvvhp19+++M/B/6db0GHHHbEUcccd8JJp5x2xlnnnHfBRZdcdsVV11x3w0233HbHXffc98BDj/zjsSeeeua5F1565bU33nrnvQ8++uRfn33x1Tff/fDTL7/98Z8DxW9Bhxx2xFHHHHfCSaecdsZZ55x3wUWXXHbFVddcd8NNt9x2x1333PfAQ4/847EnnnrmuRdeeuW1N956570PPvrkX5998dU33/3w0y+//fGfA//ut6BDDjviqGOOO+GkU04746xzzrvgoksuu+Kqa6674aZbbrvjrnvue+ChR/7x2BNPPfPcCy+98tobb73z3gcfffKvz7746pvvfvjpl9/++M+Bf+9b0CGHHXHUMcedcNIpp51x1jnnXXDRJZddcdU1191w0y233XHXPfc98NAj/3jsiaeeee6Fl1557Y233nnvg48++ddnX3z1zXc//PTLb3/858A/+hZ0yGFHHHXMcSecdMppZ5x1znkXXHTJZVdcdc11N9x0y2133HXPfQ889Mg/HnviqWeee+GlV15746133vvgo0/+9dkXX33z3Q8//fLbH/85UPoWdMhhRxx1zHEnnHTKaWecdc55F1x0yWVXXHXNdTfcdMttd9x1z30PPPTIPx574qlnnnvhpVdee+Otd9774KNP/vXZF199890PP/3y2x//OfDvfws65LAjjjrmuBNOOuW0M84657wLLrrksiuuuua6G2665bY77rrnvgceeuQfjz3x1DPPvfDSK6+98dY7733w0Sf/+uyLr7757oeffvntj/8c+A++BR1y2BFHHXPcCSedctoZZ51z3gUXXXLZFVddc90NN91y2x133XPfAw898o/HnnjqmedeeOmV19546533Pvjok3999sVX33z3w0+//PbHfw78h9+CDjnsiKOOOe6Ek0457YyzzjnvgosuueyKq6657oabbrntjrvuue+Bhx75x2NPPPXMcy+89Mprb7z1znsffPTJvz774qtvvvvhp19+++M/B8rfgg457IijjjnuhJNOOe2Ms84574KLLrnsiquuue6Gm2657Y677rnvgYce+cdjTzz1zHMvvPTKa2+89c57H3z0yb8+++Krb7774adffvvjPwf+o29Bhxx2xFHHHHfCSaecdsZZ55x3wUWXXHbFVddcd8NNt9x2x1333PfAQ4/847EnnnrmuRdeeuW1N956570PPvrkX5998dU33/3w0y+//fGfA//xt6BDDjviqGOOO+GkU04746xzzrvgoksuu+Kqa6674aZbbrvjrnvue+ChR/7x2BNPPfPcCy+98tobb73z3gcfffKvz7746pvvfvjpl9/++M+B/+Rb0CGHHXHUMcedcNIpp51x1jnnXXDRJZddcdU1191w0y233XHXPfc98NAj/3jsiaeeee6Fl1557Y233nnvg48++ddnX3z1zXc//PTLb3/850DlW9Ahhx1x1DHHnXDSKaedcdY5511w0SWXXXHVNdfdcNMtt91x1z33PfDQI/947ImnnnnuhZdeee2Nt95574OPPvnXZ1989c13P/z0y29//OfAf/ot6JDDjjjqmONOOOmU084465zzLrjoksuuuOqa62646Zbb7rjrnvseeOiRfzz2xFPPPPfCS6+89sZb77z3wUef/OuzL7765rsffvrltz/+c+A/+xZ0yGFHHHXMcSecdMppZ5x1znkXXHTJZVdcdc11N9x0y2133HXPfQ889Mg/HnviqWeee+GlV15746133vvgo0/+9dkXX33z3Q8//fLbH/858J9/CzrksCOOOua4E0465bQzzjrnvAsuuuSyK6665robbrrltjvuuue+Bx565B+PPfHUM8+98NIrr73x1jvvffDRJ//67Iuvvvnuh59++e2P/xyofgs65LAjjjrmuBNOOuW0M84657wLLrrksiuuuua6G2665bY77rrnvgceeuQfjz3x1DPPvfDSK6+98dY7733w0Sf/+uyLr7757oeffvntj/8c+C++BR1y2BFHHXPcCSedctoZZ51z3gUXXXLZFVddc90NN91y2x133XPfAw898o/HnnjqmedeeOmV19546533Pvjok3999sVX33z3w0+//PbHfw78429Bhxx2xFHHHHfCSaecdsZZ55x3wUWXXHbFVddcd8NNt9x2x1333PfAQ4/847EnnnrmuRdeeuW1N956570PPvrkX5998dU33/3w0y+//fGfA//kW9Ahhx1x1DHHnXDSKaedcdY5511w0SWXXXHVNdfdcNMtt91x1z33PfDQI/947ImnnnnuhZdeee2Nt95574OPPvnXZ1989c13P/z0y29//OdA7VvQIYcdcdQxx51w0imnnXHWOeddcNEll11x1TXX3XDTLbfdcdc99z3w0CP/eOyJp5557oWXXnntjbfeee+Djz7512dffPXNdz/89Mtvf/znwH/5LeiQw4446pjjTjjplNPOOOuc8y646JLLrrjqmutuuOmW2+646577HnjokX889sRTzzz3wkuvvPbGW++898FHn/zrsy+++ua7H3765bc//nPgn34LOuSwI4465rgTTjrltDPOOue8Cy665LIrrrrmuhtuuuW2O+66574HHnrkH4898dQzz73w0iuvvfHWO+998NEn//rsi6+++e6Hn3757Y//HPhn34IOOeyIo4457oSTTjntjLPOOe+Ciy657Iqrrrnuhptuue2Ou+6574GHHvnHY0889cxzL7z0ymtvvPXOex989Mm/Pvviq2++++GnX3774z8H6t+CDjnsiKOOOe6Ek0457YyzzjnvgosuueyKq6657oabbrntjrvuue+Bhx75x2NPPPXMcy+89Mprb7z1znsffPTJvz774qtvvvvhp19+++M/B/6rb0GHHHbEUcccd8JJp5x2xlnnnHfBRZdcdsVV11x3w0233HbHXffc98BDj/zjsSeeeua5F1565bU33nrnvQ8++uRfn33x1Tff/fDTL7/98Z8D//W3oEMOO+KoY4474aRTTjvjrHPOu+CiSy674qprrrvhpltuu+Oue+574KFH/vHYE08989wLL73y2htvvfPeBx998q/Pvvjqm+9++OmX3/74z4F//i3okMOOOOqY40446ZTTzjjrnPMuuOiSy6646prrbrjpltvuuOue+x546JF/PPbEU88898JLr7z2xlvvvPfBR5/867Mvvvrmux9++uW3P/5zoPEt6JDDjjjqmONOOOmU084465zzLrjoksuuuOqa62646Zbb7rjrnvseeOiRfzz2xFPPPPfCS6+89sZb77z3wUef/OuzL7765rsffvrltz/+c+C/+RZ0yGFHHHXMcSecdMppZ5x1znkXXHTJZVdcdc11N9x0y2133HXPfQ889Mg/HnviqWeee+GlV15746133vvgo0/+9dkXX33z3Q8//fLbH/858N9+CzrksCOOOua4E0465bQzzjrnvAsuuuSyK6665robbrrltjvuuue+Bx565B+PPfHUM8+98NIrr73x1jvvffDRJ//67Iuvvvnuh59++e2P/xz4774FHXLYEUcdc9wJJ51y2hlnnXPeBRddctkVV11z3Q033XLbHXfdc98DDz3yj8eeeOqZ51546ZXX3njrnfc++OiTf332xVfffPfDT7/89sd/DjS/BR1y2BFHHXPcCSedctoZZ51z3gUXXXLZFVddc90NN91y2x133XPfAw898o/HnnjqmedeeOmV19546533Pvjok3999sVX33z3w0+//PbHfw7899+CDjnsiKOOOe6Ek0457YyzzjnvgosuueyKq6657oabbrntjrvuue+Bhx75x2NPPPXMcy+89Mprb7z1znsffPTJvz774qtvvvvhp19+++M/B/6Hb0GHHHbEUcccd8JJp5x2xlnnnHfBRZdcdsVV11x3w0233HbHXffc98BDj/zjsSeeeua5F1565bU33nrnvQ8++uRfn33x1Tff/fDTL7/98Z8D/+O3oEMOO+KoY4474aRTTjvjrHPOu+CiSy674qprrrvhpltuu+Oue+574KFH/vHYE08989wLL73y2htvvfPeBx998q/Pvvjqm+9++OmX3/74z4HWt6BDDjviqGOOO+GkU04746xzzrvgoksuu+Kqa6674aZbbrvjrnvue+ChR/7x2BNPPfPcCy+98tobb73z3gcfffKvz7746pvvfvjpl9/++M+B/+lb0CGHHXHUMcedcNIpp51x1jnnXXDRJZddcdU1191w0y233XHXPfc98NAj/3jsiaeeee6Fl1557Y233nnvg48++ddnX3z1zXc//PTLb3/858D//C3okMOOOOqY40446ZTTzjjrnPMuuOiSy6646prrbrjpltvuuOue+x546JF/PPbEU88898JLr7z2xlvvvPfBR5/867Mvvvrmux9++uW3P/5z4H/5FnTIYUccdcxxJ5x0ymlnnHXOeRdcdMllV1x1zXU33HTLbXfcdc99Dzz0yD8ee+KpZ5574aVXXnvjrXfe++CjT/712RdfffPdDz/98tsf/znQ/hZ0yGFHHHXMcSecdMppZ5x1znkXXHTJZVdcdc11N9x0y2133HXPfQ889Mg/HnviqWeee+GlV15746133vvgo0/+9dkXX33z3Q8//fLbH/858L9+CzrksCOOOua4E0465bQzzjrnvAsuuuSyK6665robbrrltjvuuue+Bx565B+PPfHUM8+98NIrr73x1jvvffDRJ//67Iuvvvnuh59++e2P/xz4374FHXLYEUcdc9wJJ51y2hlnnXPeBRddctkVV11z3Q033XLbHXfdc98DDz3yj8eeeOqZ51546ZXX3njrnfc++OiTf332xVfffPfDT7/89sd/Dvzv34IOOeyIo4457oSTTjntjLPOOe+Ciy657Iqrrrnuhptuue2Ou+6574GHHvnHY0889cxzL7z0ymtvvPXOex989Mm/Pvviq2++++GnX3774z8HOt+CDjnsiKOOOe6Ek0457YyzzjnvgosuueyKq6657oabbrntjrvuue+Bhx75x2NPPPXMcy+89Mprb7z1znsffPTJvz774qtvvvvhp19+++M/B/6Pb0GHHHbEUcccd8JJp5x2xlnnnHfBRZdcdsVV11x3w0233HbHXffc98BDj/zjsSeeeua5F1565bU33nrnvQ8++uRfn33x1Tff/fDTL7/98Z8D/+e3oEMOO+KoY4474aRTTjvjrHPOu+CiSy674qprrrvhpltuu+Oue+574KFH/vHYE08989wLL73y2htvvfPeBx998q/Pvvjqm+9++OmX3/74z4H/61vQIYcdcdQxx51w0imnnXHWOeddcNEll11x1TXX3XDTLbfdcdc99z3w0CP/eOyJp5557oWXXnntjbfeee+Djz7512dffPXNdz/89Mtvf/znQPdb0CGHHXHUMcedcNIpp51x1jnnXXDRJZddcdU1191w0y233XHXPfc98NAj/3jsiaeeee6Fl1557Y233nnvg48++ddnX3z1zXc//PTLb3/858C/+BZ0yGFHHHXMcSecdMppZ5x1znkXXHTJZVdcdc11N9x0y2133HXPfQ889Mg/HnviqWeee+GlV15746133vvgo0/+9dkXX33z3Q8//fLbH/858C+/BR1y2BFHHXPcCSedctoZZ51z3gUXXXLZFVddc90NN91y2x133XPfAw898o/HnnjqmedeeOmV19546533Pvjok3999sVX33z3w0+//PbHfw7839+CDjnsiKOOOe6Ek0457YyzzjnvgosuueyKq6657oabbrntjrvuue+Bhx75x2NPPPXMcy+89Mprb7z1znsffPTJvz774qtvvvvhp19+++M/B3rfgg457IijjjnuhJNOOe2Ms84574KLLrnsiquuue6Gm2657Y677rnvgYce+cdjTzz1zHMvvPTKa2+89c57H3z0yb8+++Krb7774adffvvjPwf+n29Bhxx2xFHHHHfCSaecdsZZ55x3wUWXXHbFVddcd8NNt9x2x1333PfAQ4/847EnnnrmuRdeeuW1N956570PPvrkX5998dU33/3w0y+//fGfA//qW9Ahhx1x1DHHnXDSKaedcdY5511w0SWXXXHVNdfdcNMtt91x1z33PfDQI/947ImnnnnuhZdeee2Nt95574OPPvnXZ1989c13P/z0y29//OfA//st6JDDjjjqmONOOOmU084465zzLrjoksuuuOqa62646Zbb7rjrnvseeOiRfzz2xFPPPPfCS6+89sZb77z3wUef/OuzL7765rsffvrltz/+c6D/LeiQw4446pjjTjjplNPOOOuc8y646JLLrrjqmutuuOmW2+646577HnjokX889sRTzzz3wkuvvPbGW++898FHn/zrsy+++ua7H3765bc//nPgX38LOuSwI4465rgTTjrltDPOOue8Cy665LIrrrrmuhtuuuW2O+66574HHnrkH4898dQzz73w0iuvvfHWO+998NEn//rsi6+++e6Hn3757Y//HPg334IOOeyIo4457oSTTjntjLPOOe+Ciy657Iqrrrnuhptuue2Ou+6574GHHvnHY0889cxzL7z0ymtvvPXOex989Mm/Pvviq2++++GnX3774z8H/u23oEMOO+KoY4474aRTTjvjrHPOu+CiSy674qprrrvhpltuu+Oue+574KFH/vHYE08989wLL73y2htvvfPeBx998q/Pvvjqm+9++OmX3/74z4HBt/8PdlHZBHicLcUhuAEAACBmQRAEQXhBEARBEARBEARBEARBEARBEARBsJu7s80222yzzTa7s5vtbOfubLPN3QRBEF4QBEEQhBcEQRD2ffP/5Q/2A/+/kMOOOOofxxx3wkmnnHbGWeecd8FFl1x2xVXXXHfDTbfcdsdd99z3wEOPPPbEU88898JLr7z2xlvvvPfBR5/867Mvvvrmux/+89Mvv/1x4N/5FnTIYUcc9Y9jjjvhpFNOO+Osc8674KJLLrviqmuuu+GmW26746577nvgoUcee+KpZ5574aVXXnvjrXfe++CjT/712RdfffPdD//56Zff/jjwD74FHXLYEUf945jjTjjplNPOOOuc8y646JLLrrjqmutuuOmW2+646577HnjokceeeOqZ51546ZXX3njrnfc++OiTf332xVfffPfDf3765bc/Dvy734IOOeyIo/5xzHEnnHTKaWecdc55F1x0yWVXXHXNdTfcdMttd9x1z30PPPTIY0889cxzL7z0ymtvvPXOex989Mm/Pvviq2++++E/P/3y2x8HBt+CDjnsiKP+ccxxJ5x0ymlnnHXOeRdcdMllV1x1zXU33HTLbXfcdc99Dzz0yGNPPPXMcy+89Mprb7z1znsffPTJvz774qtvvvvhPz/98tsfB/7ht6BDDjviqH8cc9wJJ51y2hlnnXPeBRddctkVV11z3Q033XLbHXfdc98DDz3y2BNPPfPcCy+98tobb73z3gcfffKvz7746pvvfvjPT7/89seBf/Qt6JDDjjjqH8ccd8JJp5x2xlnnnHfBRZdcdsVV11x3w0233HbHXffc98BDjzz2xFPPPPfCS6+89sZb77z3wUef/OuzL7765rsf/vPTL7/9ceAffws65LAjjvrHMcedcNIpp51x1jnnXXDRJZddcdU1191w0y233XHXPfc98NAjjz3x1DPPvfDSK6+98dY7733w0Sf/+uyLr7757of//PTLb38cGH4LOuSwI476xzHHnXDSKaedcdY5511w0SWXXXHVNdfdcNMtt91x1z33PfDQI4898dQzz73w0iuvvfHWO+998NEn//rsi6+++e6H//z0y29/HPj3vgUdctgRR/3jmONOOOmU084465zzLrjoksuuuOqa62646Zbb7rjrnvseeOiRx5546pnnXnjpldfeeOud9z746JN/ffbFV99898N/fvrltz8O/Pvfgg457Iij/nHMcSecdMppZ5x1znkXXHTJZVdcdc11N9x0y2133HXPfQ889MhjTzz1zHMvvPTKa2+89c57H3z0yb8+++Krb7774T8//fLbHwf+g29Bhxx2xFH/OOa4E0465bQzzjrnvAsuuuSyK6665robbrrltjvuuue+Bx565LEnnnrmuRdeeuW1N956570PPvrkX5998dU33/3wn59++e2PA6NvQYccdsRR/zjmuBNOOuW0M84657wLLrrksiuuuua6G2665bY77rrnvgceeuSxJ5565rkXXnrltTfeeue9Dz765F+fffHVN9/98J+ffvntjwP/4begQw474qh/HHPcCSedctoZZ51z3gUXXXLZFVddc90NN91y2x133XPfAw898tgTTz3z3AsvvfLaG2+9894HH33yr8+++Oqb7374z0+//PbHgf/oW9Ahhx1x1D+OOe6Ek0457YyzzjnvgosuueyKq6657oabbrntjrvuue+Bhx557ImnnnnuhZdeee2Nt95574OPPvnXZ1989c13P/znp19+++PAf/wt6JDDjjjqH8ccd8JJp5x2xlnnnHfBRZdcdsVV11x3w0233HbHXffc98BDjzz2xFPPPPfCS6+89sZb77z3wUef/OuzL7765rsf/vPTL7/9cWD8LeiQw4446h/HHHfCSaecdsZZ55x3wUWXXHbFVddcd8NNt9x2x1333PfAQ4889sRTzzz3wkuvvPbGW++898FHn/zrsy+++ua7H/7z0y+//XHgP/kWdMhhRxz1j2OOO+GkU04746xzzrvgoksuu+Kqa6674aZbbrvjrnvue+ChRx574qlnnnvhpVdee+Otd9774KNP/vXZF199890P//npl9/+OPCffgs65LAjjvrHMcedcNIpp51x1jnnXXDRJZddcdU1191w0y233XHXPfc98NAjjz3x1DPPvfDSK6+98dY7733w0Sf/+uyLr7757of//PTLb38c+M++BR1y2BFH/eOY40446ZTTzjjrnPMuuOiSy6646prrbrjpltvuuOue+x546JHHnnjqmedeeOmV19546533Pvjok3999sVX33z3w39++uW3Pw5MvgUdctgRR/3jmONOOOmU084465zzLrjoksuuuOqa62646Zbb7rjrnvseeOiRx5546pnnXnjpldfeeOud9z746JN/ffbFV99898N/fvrltz8O/Offgg457Iij/nHMcSecdMppZ5x1znkXXHTJZVdcdc11N9x0y2133HXPfQ889MhjTzz1zHMvvPTKa2+89c57H3z0yb8+++Krb7774T8//fLbHwf+i29Bhxx2xFH/OOa4E0465bQzzjrnvAsuuuSyK6665robbrrltjvuuue+Bx565LEnnnrmuRdeeuW1N956570PPvrkX5998dU33/3wn59++e2PA//lt6BDDjviqH8cc9wJJ51y2hlnnXPeBRddctkVV11z3Q033XLbHXfdc98DDz3y2BNPPfPcCy+98tobb73z3gcfffKvz7746pvvfvjPT7/89seB6begQw474qh/HHPcCSedctoZZ51z3gUXXXLZFVddc90NN91y2x133XPfAw898tgTTz3z3AsvvfLaG2+9894HH33yr8+++Oqb7374z0+//PbHgf/qW9Ahhx1x1D+OOe6Ek0457YyzzjnvgosuueyKq6657oabbrntjrvuue+Bhx557ImnnnnuhZdeee2Nt95574OPPvnXZ1989c13P/znp19+++PAf/0t6JDDjjjqH8ccd8JJp5x2xlnnnHfBRZdcdsVV11x3w0233HbHXffc98BDjzz2xFPPPPfCS6+89sZb77z3wUef/OuzL7765rsf/vPTL7/9ceC/+RZ0yGFHHPWPY4474aRTTjvjrHPOu+CiSy674qprrrvhpltuu+Oue+574KFHHnviqWeee+GlV15746133vvgo0/+9dkXX33z3Q//+emX3/44MPsWdMhhRxz1j2OOO+GkU04746xzzrvgoksuu+Kqa6674aZbbrvjrnvue+ChRx574qlnnnvhpVdee+Otd9774KNP/vXZF199890P//npl9/+OPDffgs65LAjjvrHMcedcNIpp51x1jnnXXDRJZddcdU1191w0y233XHXPfc98NAjjz3x1DPPvfDSK6+98dY7733w0Sf/+uyLr7757of//PTLb38c+O++BR1y2BFH/eOY40446ZTTzjjrnPMuuOiSy6646prrbrjpltvuuOue+x546JHHnnjqmedeeOmV19546533Pvjok3999sVX33z3w39++uW3Pw7899+CDjnsiKP+ccxxJ5x0ymlnnHXOeRdcdMllV1x1zXU33HTLbXfcdc99Dzz0yGNPPPXMcy+89Mprb7z1znsffPTJvz774qtvvvvhPz/98tsfB+bfgg457Iij/nHMcSecdMppZ5x1znkXXHTJZVdcdc11N9x0y2133HXPfQ889MhjTzz1zHMvvPTKa2+89c57H3z0yb8+++Krb7774T8//fLbHwf+h29Bhxx2xFH/OOa4E0465bQzzjrnvAsuuuSyK6665robbrrltjvuuue+Bx565LEnnnrmuRdeeuW1N956570PPvrkX5998dU33/3wn59++e2PA//kW9Ahhx1x1D+OOe6Ek0457YyzzjnvgosuueyKq6657oabbrntjrvuue+Bhx557ImnnnnuhZdeee2Nt95574OPPvnXZ1989c13P/znp19+++PAP/0WdMhhRxz1j2OOO+GkU04746xzzrvgoksuu+Kqa6674aZbbrvjrnvue+ChRx574qlnnnvhpVdee+Otd9774KNP/vXZF199890P//npl9/+OLD4FnTIYUcc9Y9jjjvhpFNOO+Osc8674KJLLrviqmuuu+GmW26746577nvgoUcee+KpZ5574aVXXnvjrXfe++CjT/712RdfffPdD//56Zff/jjwP34LOuSwI476xzHHnXDSKaedcdY5511w0SWXXXHVNdfdcNMtt91x1z33PfDQI4898dQzz73w0iuvvfHWO+998NEn//rsi6+++e6H//z0y29/HPhn34IOOeyIo/5xzHEnnHTKaWecdc55F1x0yWVXXHXNdTfcdMttd9x1z30PPPTIY0889cxzL7z0ymtvvPXOex989Mm/Pvviq2++++E/P/3y2x8H/qdvQYccdsRR/zjmuBNOOuW0M84657wLLrrksiuuuua6G2665bY77rrnvgceeuSxJ5565rkXXnrltTfeeue9Dz765F+fffHVN9/98J+ffvntjwPLb0GHHHbEUf845rgTTjrltDPOOue8Cy665LIrrrrmuhtuuuW2O+66574HHnrksSeeeua5F1565bU33nrnvQ8++uRfn33x1Tff/fCfn3757Y8D//O3oEMOO+Kofxxz3AknnXLaGWedc94FF11y2RVXXXPdDTfdctsdd91z3wMPPfLYE08989wLL73y2htvvfPeBx998q/Pvvjqm+9++M9Pv/z2x4H/5VvQIYcdcdQ/jjnuhJNOOe2Ms84574KLLrnsiquuue6Gm2657Y677rnvgYceeeyJp5557oWXXnntjbfeee+Djz7512dffPXNdz/856dffvvjwD//FnTIYUcc9Y9jjjvhpFNOO+Osc8674KJLLrviqmuuu+GmW26746577nvgoUcee+KpZ5574aVXXnvjrXfe++CjT/712RdfffPdD//56Zff/jiw+hZ0yGFHHPWPY4474aRTTjvjrHPOu+CiSy674qprrrvhpltuu+Oue+574KFHHnviqWeee+GlV15746133vvgo0/+9dkXX33z3Q//+emX3/448L9+CzrksCOO+scxx51w0imnnXHWOeddcNEll11x1TXX3XDTLbfdcdc99z3w0COPPfHUM8+98NIrr73x1jvvffDRJ//67Iuvvvnuh//89Mtvfxz4374FHXLYEUf945jjTjjplNPOOOuc8y646JLLrrjqmutuuOmW2+646577HnjokceeeOqZ51546ZXX3njrnfc++OiTf332xVfffPfDf3765bc/DvyLb0GHHHbEUf845rgTTjrltDPOOue8Cy665LIrrrrmuhtuuuW2O+66574HHnrksSeeeua5F1565bU33nrnvQ8++uRfn33x1Tff/fCfn3757Y8D629Bhxx2xFH/OOa4E0465bQzzjrnvAsuuuSyK6665robbrrltjvuuue+Bx565LEnnnrmuRdeeuW1N956570PPvrkX5998dU33/3wn59++e2PA//yW9Ahhx1x1D+OOe6Ek0457YyzzjnvgosuueyKq6657oabbrntjrvuue+Bhx557ImnnnnuhZdeee2Nt95574OPPvnXZ1989c13P/znp19+++PAv/oWdMhhRxz1j2OOO+GkU04746xzzrvgoksuu+Kqa6674aZbbrvjrnvue+ChRx574qlnnnvhpVdee+Otd9774KNP/vXZF199890P//npl9/+OPCvvwUdctgRR/3jmONOOOmU084465zzLrjoksuuuOqa62646Zbb7rjrnvseeOiRx5546pnnXnjpldfeeOud9z746JN/ffbFV99898N/fvrltz8ObL4FHXLYEUf945jjTjjplNPOOOuc8y646JLLrrjqmutuuOmW2+646577HnjokceeeOqZ51546ZXX3njrnfc++OiTf332xVfffPfDf3765bc/Dvzv34IOOeyIo/5xzHEnnHTKaWecdc55F1x0yWVXXHXNdTfcdMttd9x1z30PPPTIY0889cxzL7z0ymtvvPXOex989Mm/Pvviq2++++E/P/3y2x8H/o9vQYccdsRR/zjmuBNOOuW0M84657wLLrrksiuuuua6G2665bY77rrnvgceeuSxJ5565rkXXnrltTfeeue9Dz765F+fffHVN9/98J+ffvntjwP/57egQw474qh/HHPcCSedctoZZ51z3gUXXXLZFVddc90NN91y2x133XPfAw898tgTTz3z3AsvvfLaG2+9894HH33yr8+++Oqb7374z0+//PbHge23oEMOO+Kofxxz3AknnXLaGWedc94FF11y2RVXXXPdDTfdctsdd91z3wMPPfLYE08989wLL73y2htvvfPeBx998q/Pvvjqm+9++M9Pv/z2x4H/61vQIYcdcdQ/jjnuhJNOOe2Ms84574KLLrnsiquuue6Gm2657Y677rnvgYceeeyJp5557oWXXnntjbfeee+Djz7512dffPXNdz/856dffvvjwP/9LeiQw4446h/HHHfCSaecdsZZ55x3wUWXXHbFVddcd8NNt9x2x1333PfAQ4889sRTzzz3wkuvvPbGW++898FHn/zrsy+++ua7H/7z0y+//XHg//kWdMhhRxz1j2OOO+GkU04746xzzrvgoksuu+Kqa6674aZbbrvjrnvue+ChRx574qlnnnvhpVdee+Otd9774KNP/vXZF199890P//npl9/+OLD7FnTIYUcc9Y9jjjvhpFNOO+Osc8674KJLLrviqmuuu+GmW26746577nvgoUcee+KpZ5574aVXXnvjrXfe++CjT/712RdfffPdD//56Zff/jjwb74FHXLYEUf945jjTjjplNPOOOuc8y646JLLrrjqmutuuOmW2+646577HnjokceeeOqZ51546ZXX3njrnfc++OiTf332xVfffPfDf3765bc/Dvzbb0GHHHbEUf845rgTTjrltDPOOue8Cy665LIrrrrmuhtuuuW2O+66574HHnrksSeeeua5F1565bU33nrnvQ8++uRfn33x1Tff/fCfn3757Y8D/++3oEMOO+Kofxxz3AknnXLaGWedc94FF11y2RVXXXPdDTfdctsdd91z3wMPPfLYE08989wLL73y2htvvfPeBx998q/Pvvjqm+9++M9Pv/z2x4H9t/8Pd+bZQHicLcUv2AEAAOBnex5BEARBEARBEARBEARBEAThC8IXBEEQBEEQBEEQBEEQBEEQBEFwN9tss83dbLOd29zNNtu5zTa3uc3+PM997y/83uAu8G8KMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqr/GGNv6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy8D/+CPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwip/WOMv62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwy8A//CPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyh/W+Ms6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/wy8G//EWSIYUYYZYxxJphkimlmmGWOeRZYZIllVljlD2v8ZZ0NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffhnY/xFkiGFGGGWMcSaYZIppZphljnkWWGSJZVZY5Q9r/GWdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH34Z+Hf+CDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6zyhzX+ss4Gm2yxzQ67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mBFGGWOcCSaZYpoZZpljngUWWWKZFVb5wxp/WWeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHXwb+tz+CDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq/xhjb+ss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888MvA//7H0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV/rDGX9bZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754ZeB9x9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVf6wxl/W2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXgX/1R5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVP6zxl3U22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++GXg//gjyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMof1vjLOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/8MvB//hFkiGFGGGWMcSaYZIppZphljnkWWGSJZVZY5Q9r/GWdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH34Z+PwRZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWOUPa/xlnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9+GfjXfwQZYpgRRhljnAkmmWKaGWaZY54FFllimRVW+cMaf1lng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh18G/q8/ggwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqv8YY2/rLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDLwP/9x9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVf6wxl/W2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky++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88AjTzzzwitvvPPBJ19888Mvfwz8qf4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfA39afQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Dv6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfAxH9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgb+rP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfD39GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+vv4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sdAVH8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgH+jPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/EP9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgX+kP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MRDTn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPjH+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/RH8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgn+rPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38MxPVnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/pn+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwD/Xn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPgz/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4GE/gwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8C/0J9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4l/ozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDK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L38M/C/9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgf+tP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfB/9GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwbyf/T/AtC86Mh4nC3RoRcBAIDYYXvvgiAIgiAIgiAIgiDYZpttdrOb3dlmm2222WZ3ttmd22wTBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEHY27vvV74/4PcH+b8W+P8FGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgr/+Vf8AgQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8Df8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bv+k/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wxUPCfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Fv+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA3/bfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Dv+M8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888MvfwwU/WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+rv8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfA3/OfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Pv+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfAyX/GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgX/gP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfCH/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/0H8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WOg7D+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwj/xnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/sh/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4B/7zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DFT8Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv6J/wwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8Af+88gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8if8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sdA1X8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgn/rPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/DP/GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgX/uP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MVDzn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPgX/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/0n8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgX/nPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M1P1nkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/rX/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwL/xn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPi3/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwMN/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4F/5z+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHw7/1nkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/oP/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHQNN/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TDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfAv/WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwbm/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/yn8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgX/vPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/Bv/GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgYX/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwL/1n0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPh3/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/3n8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WNg6T+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwH/xnkCGGGWGUMcaZYJIppplh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FVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvljYP9X/j/T5ulAeJwt0a8fAQCA3mG3zwVBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBsM0229zNNttss80227nNbbZzm23247PtecP7/AHfP9z/QeD/LsgQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA3/5//uHDDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwF/Rn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPir+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwMH/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4G/pj+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHw1/VnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/ob+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwFF/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4G/qzyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPwt/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4G/rT+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DFw0p9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4I/0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+BP9afQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Dv6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA2f9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgb+rP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfD39GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+vv4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfARX8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgH+jPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/EP9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgX+kP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MXDVn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPjH+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/RH8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgn+rPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M3PRnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/pn+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwD/Xn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPgX+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6yw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dtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+C/6M8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8V/0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Br/4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAf9OfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+O/6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA/9DfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+CnP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfA/9WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+l/4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfA/9afQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4YCPyl//f/B86B6H14nC3WIRcCgJaVURyfiorKKCoqKjqoqKioqKioBAKB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sc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfDP9GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+uf4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAn+nPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38MJPRnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/oX+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwL/Un0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPhX+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwNJ/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4F/rT+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwb/RnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/q3+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvs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2WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4K//lX/AIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/A3/GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgb/pP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MVDwn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPhb/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/238GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPg7/jPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38MFP1nkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/q7/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwN/zn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPj7/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwMl/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4F/4D+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwh/4zyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/9B/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvljoOw/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8I/8Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv7IfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Af+88gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888MvfwxU/GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+if8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAH/vPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/In/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHQNV/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4J/6zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPwz/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4F/7j+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DFQ859BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4F/4zyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/9J/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4F/5zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DNT9Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv61/wwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8C/8Z9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4t/4zyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8DDf8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bf+c/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8O/9Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv6D/wwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx0DTfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+A/+s8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8J/8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+B/+w/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx0PKfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+C/+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA3/qP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfBn/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwNt/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4H/6j+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHw3/xnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/rv/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHQMd/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4H/4zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPy5/wwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8Bf+M8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwx0/WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+0n8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgf/rPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/C//GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgZ7/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwP/2n0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPg//jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/138GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WOg/1f+Py5g+QR4nC3RoRcBAIDYYe/eBUEQBEEQBEEQBEEQBEEQBEEQBEEQBEGwzXa2c5ttttlmN9tss802t9lmd24TBEEQBEEQBEEQBEHY27vvV74/4PeH/T8I/P+CDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHw1/7KP2SQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+uv8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfA3/CfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4YGPjPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/E3/GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgb/lP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfBH/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwND/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4G/7T+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwd/xnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/th/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvljYOQ/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8Cf+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA3/XfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Dv+c8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888MvfwyM/WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+vv8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAP/CfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+If+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfAxP/GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgX/kP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfCP/WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+if8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfA1H8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgn/rPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/DP/GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgX/uP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MTDzn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPgX/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/6j+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwL/1nkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G5v4zyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/8p/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4F/7zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPwb/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4GF/wwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8C/9Z9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4d/4zyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/95/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvljYOk/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8B/8Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv6j/wwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8B/8p9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hhY+c8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8Z/8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+B/+I/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8F/9Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Btb+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA3/mP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfDf/GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+u/8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAxn8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgf/jPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/E//GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgf/lP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MbD1n0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NP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x8BDfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Df6M8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8W/0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+BP9GfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4YeOrPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/Kn+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwL/Tn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPj3+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwMv/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4E/059BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4D/ozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/1F/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4K0/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8J/0Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv6z/gwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8Cf688gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwx89GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+Qn8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgv+jPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/Ff9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPga/+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwH/Tn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPjv+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/Q38GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgpz+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwP/VnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/pf+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwP/Wn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GAj8pf/3/wcqkPh9eJwt1iEDAQCjnlHb/bbZZpu72WabbbZrm2222WabbbYJgiAIgiAIgiAIgiAIgiAIgiAIgiAIgiAIgiAIgiAIgiAIgiDsbt95y/kBT3n/EPiTwP9bkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/sIf/QODDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwF/VnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/kR/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvnjn4f/IwwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8Bf0p9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4y/ozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8Df0V/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvnjnx++/88fGGSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgb+qP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfDX9GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+uv4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sdASH8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgb+jPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/E39GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWP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o4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfAv9WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+lf4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sdAUn8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgX+vPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/Bv9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgX+rP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MZDSn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPh3+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/Xn8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgP+jPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38MpPVnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/qP+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwH/Sn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPjP+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwMZ/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4H/oj+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwX/VnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/pv+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHQFZ/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4L/rzyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPwP/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4H/qT+DDDHMCKOMMc4Ek0wx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TDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfCP/GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+yH8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgH/vPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38MVPxnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/on/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwB/7zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPyJ/wwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx0DVfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Cf+s8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8M/8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bf+4/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wxUPOfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Bf+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA//SfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Bf+c8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888MvfwzU/WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+tf8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAv/GfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Lf+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfAw3/GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgX/nP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfDv/WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+g/8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sdA038GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgP/rPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/Cf/GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgf/sP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MdDyn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPgv/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/6j+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwZ/4zyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8Dbf8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+B/+o/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8N/8Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv67/wwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx0DHfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+B/+M8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8uf8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAX/jPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38MdP1nkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/tJ/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4H/6zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPwv/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4Ge/wwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8D/9p9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4P/4zyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/9d/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvljoP9X/j+KYAkTeJwt0aEXAQCA2GHv3QVBEARBEARBEARBEARBEARBEARBEARBsM12tnObbbbZZjfbbLPNNrfZZnduEwRBEARBEARBEARB2Nu771e+P+D3h/0/CPz/ggwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8Nf+yj9kkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/rr/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwN/wn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GBj4zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPxN/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4G/5T+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwR/4zyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8DQ/8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bv+0/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8Hf8Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv7YfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y2DkP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfAn/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/138GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPg7/nPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38MjP1nkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/r7/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yy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dtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y2DpP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfAf/GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+o/8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAf/KfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4YWPnPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/Gf/GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgf/iP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfBf/WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwbW/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/5j+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHw3/xnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/rv/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwMZ/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4H/4zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPxP/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4H/5T+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DGw9Z9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj43/4zyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8Df+4/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8Bf+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfAzv/GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgb/0n0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPg//jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/138GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WNg/1f+P4v1CU94nC3Rrx8BAIDeYZ/PXRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEd7PNNttss80222yzzd3sZpvb3Ga/97zhff6A7x/u/yDwfxdkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4E/+v/+IYMMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfDH+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/SX8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgoD+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwl/VnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/or+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwF/Vn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY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LXfc88AjTzzzwitvvPPBJ19888Mvfwx89GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+XH8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgv+jPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/Ff9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPga/+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwF/ozyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPw3/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4H/rj+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHw059BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4H/ozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/1N/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454H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PQ888sQzL7zyxjsffPLFNz/88sfAv9WfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Hf6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfAyn9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgX+vP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfAf9GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+o/4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sdAWn8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgP+nPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/Gf9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgf+iP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MZDRn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPiv+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/TX8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgv+vPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38MZPVnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/of+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwP/Un0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPhf+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwM5/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4H/rT+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwf/RnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/q/+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHQP7P/H/kyxjXeJwt0aEbAYCDmGHhFwRBEARBEARBEATBdra5zTa7s81tttnONttss812brNNEARBEARBEARBEARBEARBEARBEARBEARhz557v/L+Ad8f8n8I/P+CDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHw1/7KPzDIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/3X8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgj/xnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8GCv4zyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8Df8N/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4G/6zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPwt/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4Gi/wwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8Af+88gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8bf8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bv+M/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wxUPKfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Lv+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA3/PfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Dv+88gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888MvfwyU/WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+gf8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAn/jPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/Kn/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHQMV/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4B/6zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPwj/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4F/7D+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DFQ9Z9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4M/8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bf+I/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8E/9Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bmr+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA//MfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Cf+88gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8C/8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Buv8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAv/SfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Ff+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA3/uP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MdDwn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPjX/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/xn8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPg3/rPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38MNP1nkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/p3/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwL/3n0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPgP/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwMt/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4H/6D+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwn/xnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/rP/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHQNt/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4L/4zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPxX/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4H/5j+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHQ8Z9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj47/4zyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/8N/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4C/8Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Brr+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA3/pP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfA//WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+l/8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sdAz38GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgf/vPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/B//GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgf/rP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MdD/K/8f5mAZE3icLdGhGwGAg5hh4RcEQRAEQRAEQRAEQRAEQRAEQRAEQRAEwXa22eY222yzzTbbbOduttlmm+3cTRAEQRAEQRAEQRAEYc+ee7/y/gHfH/p/CPz/ggwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8Nf+yj8wyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8Df91/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4I/8Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bgb+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA3/DfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Bv+s8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8Lf8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bof8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfA3/afQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Dv+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA3/XfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y2DkP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfDH/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/z38GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPg7/vPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38MjP1nkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/oH/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwD/0n0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPhH/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwMT/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4F/7D+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwT/xnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/qn/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwNR/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4J/5zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPxz/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4F/4T+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DEw859BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4l/4zyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/8p/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4F/7zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DMz9Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv6N/wwyxDAj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ZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hjY+s8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8b/8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+B/+M/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8Of+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfAzv/GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgb/wn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPhL/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4H/6z+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DGw/yv/H+f1GU94nC3RrxcBgKPeYeG7cwRBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEATBNttsszvb3Du71zbb3DvbbLPNNtvsx9n2vOF9/oDPH/Z/CPzfBRlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4C//f//AIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/BX9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgb+qP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MXDQn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPhr+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/XX8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgb+jPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38MHPVnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/qb+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwN/Sn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPjb+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwMn/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4G/oz+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwR/ozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8Df1d/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4Kw/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8Pf0Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv6+/gwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8A/0J9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hi46M8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8sf4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAn+jPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/EP9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgav+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwD/Sn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPhT/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4E/059BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hi46c8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8Y/0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bf6I/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8E/1Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bu76M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA/9MfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Cf688gQwwzwihjjDPBJFNMM8Msc8yz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eRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgX+kP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfCP9WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+if4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sdATH8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgn+rPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/DP9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgX+uP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MRDXn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPgX+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/Un8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgT/RnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8GEvozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/0p/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4F/rzyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPwb/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4Gk/gwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8C/1Z9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4d/ozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/15/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvljIKU/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8B/0Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv6j/gwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8B/0p9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hhI688gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8Z/0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+B/6I/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8F/1Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/BjL6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA/9NfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+C/688gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8D/0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+BrP4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfA/9SfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+F/6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA/9bfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375YyCnP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfB/9GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+r/4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAn+rPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M5P/C/wdA2ijXeJwt0aEXAQCA2GHh9p4gCIIgCIIgCIIg2GabbXazm2222WZ3ttlmd7bZndtsEwRBEARBEARBEARBEARBEARBEARBEARB2Nu771e+P+D3B/m/Fvj/BRlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4K//lX/AIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/A3/GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgb/pP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MVDwn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPhb/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/238GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPg7/jPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38MFP1nkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/q7/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwN/zn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPj7/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwMl/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4F/4D+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwh/4zyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/9B/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvljoOw/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8I/8Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv7IfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Af+88gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888MvfwxU/GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+if8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAP/WfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Gf+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA1X/GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgX/uP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBpts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yBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwNt/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4H/6j+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHw3/xnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/rv/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHQMd/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4H/4zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPy5/wwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8Bf+M8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwx0/WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+0n8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgf/rPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/C//GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgZ7/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwP/2n0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPg//jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/138GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WOg/1f+P0JvKRN4nC3RoRcBAIDYYeH2niAIgiAIgiAIgiAIgiAIgiAIgiAIgiDYZjvbuc0222yzm2222Wab22yzO3cTBEEQBEEQBEEQBEHY27vvV74/4PcH/b8W+P8FGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgr/+Vf8AgQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8Df8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bv+k/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wxMPCfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Fv+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA3/bfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+AP/WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwaG/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/x38GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPg7/rPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/JH/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwMh/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4I/9Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv6e/wwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8Df959BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hgY+88gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8A/8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bf+g/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8I/8Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bib+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA//YfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Cf+M8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8U/8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bqf8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAP/OfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Of+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA//CfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y2DmP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfAv/WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+xH8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgX/nPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38MzP1nkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/rX/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwL/xn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPi3/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwML/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4F/5z+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHw7/1nkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/oP/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwNJ/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4D/6zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPwn/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4H/7D+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DGw8p9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4L/4zyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/9V/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4L/5zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DKz9Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv7UfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+C/+88gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8D/8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bjf8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfA//SfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+F/+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA//bfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y2DrP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfB//GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+zH8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgz/1nkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8Gdv4zyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8Df+E/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8Jf+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA//XfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y2D/V/4/RAQpT3icLdGvHwEAgN5h4baPIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCINhmm23uZpttttlmm23uzm22c5tt9uOz7XnD+/wB3z/Y/6XA/12QIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+yv/3DxhkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4G/qj+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHw1/RnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8GDvozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8Df11/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4G/ozyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPxN/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4Gj/gwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8Df0p9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj42/ozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8Df0d/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4KQ/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8If6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA3+kP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfB39WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwbO+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/T38GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPg7+vPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/AP9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgYv+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwD/Un0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPhH+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/WH8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgqj+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwT/RnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/qn+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwD/Tn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GLjpzyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPxz/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4F/oT+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwL/VnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G7vozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/0p/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4F/rzyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPwb/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4GH/gwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8C/1Z9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4d/ozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/15/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4Kk/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8Mf6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA3+iP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfCn+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwMv/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4E/059BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4D/ozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/1F/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4K0/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8J/0Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv6z/gwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8Cf688gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwx89GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+Qn8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgv+jPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/Ff9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPga/+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwH/Tn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPjv+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/Q38GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgpz+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwP/VnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/pf+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwP/Wn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GAj85f/3/wc+nyiMeJwt1iETAgCXllHUz11UVFRUVFR0UVFRUVFR0SUQCAQCgUAgEAgEAoFAIBAIBAKBQCAQCAQCgUAgEAgEAoFAIBAIBAKBQHDdPbecH/DMO3P/EPijwP+/IEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/KW/8A8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAX9afQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Cv6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA3/Qn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPir+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/pD+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwx/ozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx//bPB/zh8YZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bv6Y/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8Nf1Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv6G/gwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyxz979P+cPzDIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/U38GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgb+nPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/G39GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgbD+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwN/Rn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPi7+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/T38GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WMgoj+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHw9/VnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/oH+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwD/Un0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GIjqzyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPwj/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4F/rD+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwT/RnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8GYvozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/1R/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4J/pzyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPxz/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4G4/gwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8C/0J9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4l/ozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8Df6I/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wxkNCfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Ff6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA/9afwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Df6M8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwwk9WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+rf4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAv9OfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Pf6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfAyn9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgf+gP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfAf9WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+k/4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sdAWn8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgP+vPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/Bf9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgf+qP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MZDRn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPhv+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/XX8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgf+jPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38MZPVnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/qf+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwP/Sn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPjf+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwM5/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4H/oz+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwf/VnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/lR/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvljIP8X/j+c2jjXeJwt0aEXAQCA2GHh3p4gCIIgCIIgCIIg2GabbXazm2222WZ3ttlmd7bZndtsEwRBEARBEARBEARBEARBEARBEARBEARB2Nu771e+P+D3B/m/Fvj/BRlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4K//lX/AIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/A3/GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgb/pP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MVDwn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPhb/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/238GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPg7/jPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38MFP1nkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/q7/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwN/zn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPj7/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwMl/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4F/4D+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwh/4zyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/9B/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvljoOw/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8I/8Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv7IfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Af+88gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888MvfwxU/GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+if8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAP/WfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Gf+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA1X/GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgX/uP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfAv/GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+pf8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sdAzX8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgX/nPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/Gv/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CSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4H/4zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPy5/wwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8Bf+M8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwx0/WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+0n8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgf/rPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/C//GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgZ7/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwP/2n0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPg//jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/138GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WOg/1f+P55vORN4nC3RoRcBAIDYYeHeniAIgiAIgiAIgiAIgiAIgiAIgiAIgiDYZjvbuc0222yzm2222Wab22yzO3cTBEEQBEEQBEEQBEHY27vvV74/4PcH/b8W+P8FGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgr/+Vf8AgQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8Df8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bv+k/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wxMPCfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Fv+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA3/bfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+AP/WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwaG/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/x38GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPg7/rPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/JH/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwMh/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4I/9Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv6e/wwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8Df959BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hgY+88gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8A/8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bf+g/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8I/8Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bib+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA//YfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Cf+M8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8U/8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bqf8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAP/OfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Of+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA//CfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y2DmP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfAv/WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+xH8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgX/nPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38MzP1nkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/rX/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwL/xn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPi3/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwML/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4F/5z+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHw7/1nkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/oP/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwNJ/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4D/6zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPwn/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4H/7D+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DGw8p9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4L/4zyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/9V/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4L/5zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DKz9Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv7UfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+C/+88gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8D/8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bjf8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfA//SfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+F/+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA//bfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y2DrP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfB//GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+zH8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgz/1nkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8Gdv4zyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8Df+E/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8Jf+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA//XfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y2D/V/4/oAQ5T3icLdGvHwEAgN5h4T6bIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCINhmm23uZpttttlmm23uzm22c5tt9uOz7XnD+/wB3z/Y/6XA/12QIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+yv/3DxhkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4G/qj+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHw1/RnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8GDvozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8Df11/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4G/ozyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPxN/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4Gj/gwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8Df0p9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj42/ozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8Df0d/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4KQ/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8If6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA3+kP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfB39WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwbO+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/T38GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPg7+vPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/AP9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgYv+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwD/Un0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPhH+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/WH8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgqj+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwT/RnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/qn+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwD/Tn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GLjpzyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPxz/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4F/oT+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwL/VnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G7vozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/0p/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4F/rzyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPwb/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4GH/gwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8C/1Z9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4d/ozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/15/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4Kk/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8Mf6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA3+iP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfCn+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwMv/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4E/059BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4D/ozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/1F/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4K0/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8J/0Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv6z/gwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8Cf688gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwx89GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+Qn8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgv+jPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/Ff9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPga/+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwH/Tn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPjv+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/Q38GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgpz+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwP/VnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/pf+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwP/Wn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GAj85f/3/weanziMeJwt1iEDAYCD3mHb/tvZZpvbbLPNNtvZZpttttlmm+0EQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRB2u3ve8nyAX3n/EPijwP9fkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/tJf+AcGGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgL+vPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/BX9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgT/ozyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPxV/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4G/pj+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwR/ozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx//LPif8wcGGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgr+vPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/A39GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgb+pP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/88c+O3p/zBwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Bv6c8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8bf0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bv6M/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wxENafQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+GP9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgb+rP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfD39GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwYi+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/X38GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgH+jPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/EP9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgaj+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwD/Sn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPjH+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/RH8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WMgpj+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwT/VnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/pn+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwD/Xn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GIjrzyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPwL/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4F/qT+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwJ/ozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8DCf0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bf6U/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8K/1Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv6N/gwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx0BSfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Df6s8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8O/0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bf68/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wxkNKfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+A/6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA/9RfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+A/6c8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwyk9WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+s/4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAf9GfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+K/6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfAxn9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgf+mP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfDf9WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+h/4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sdAVn8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgf+rPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/C/9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgf+tP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MZDTn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPg/+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/V38GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgT/VnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G8n/h/wP42kjXeJwt0aEXAQCA2GHh3psgCIIgCIIgCIIg2GabbXazm2222WZ3ttlmd7bZndtsEwRBEARBEARBEARBEARBEARBEARBEARB2Nu771e+P+D3B/m/Fvj/BRlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4K//lX/AIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/A3/GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgb/pP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MVDwn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPhb/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/238GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPg7/jPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38MFP1nkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/q7/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwN/zn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPj7/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwMl/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4F/4D+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwh/4zyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/9B/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvljoOw/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8I/8Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv7IfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Af+88gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888MvfwxU/GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+if8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAP/WfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Gf+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA1X/GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgX/uP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfAv/GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+pf8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sdAzX8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgX/nPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/Gv/GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgX/jP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MVD3n0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPi3/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/7D+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdc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J5554ZU33vngky+++eGXPwb+0n8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgf/rPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/C//GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgZ7/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwP/2n0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPg//jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/138GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WOg/1f+P/pvSRN4nC3RoRcBAIDYYeHemyAIgiAIgiAIgiAIgiAIgiAIgiAIgiDYZjvbuc0222yzm2222Wab22yzO3cTBEEQBEEQBEEQBEHY27vvV74/4PcH/b8W+P8FGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgr/+Vf8AgQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8Df8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bv+k/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wxMPCfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Fv+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA3/bfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+AP/WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwaG/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/x38GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPg7/rPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/JH/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwMh/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4I/9Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv6e/wwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8Df959BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hgY+88gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8A/8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bf+g/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8I/8Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bib+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA//YfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Cf+M8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8U/8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bqf8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAP/OfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Of+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA//CfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y2DmP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfAv/WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+xH8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgX/nPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38MzP1nkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/rX/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwL/xn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPi3/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwML/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4F/5z+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHw7/1nkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/oP/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwNJ/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4D/6zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPwn/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4H/7D+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DGw8p9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4L/4zyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/9V/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4L/5zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DKz9Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv7UfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+C/+88gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8D/8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bjf8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfA//SfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+F/+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA//bfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y2DrP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfB//GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+zH8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgz/1nkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8Gdv4zyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8Df+E/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8Jf+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA//XfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y2D/V/4//ARJT3icLdGvHwEAgN5h4T6fCYIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCILbbLPN7myzzTbbbLPN3ezONrvZZr/3vOF9/oDvH+z/UuD/LsgQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA3/4//0DBhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4C/rzyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPwV/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4GD/gwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8Bf1Z9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4a/ozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8Df11/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4Kg/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8Df0Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv6m/gwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8Df0p9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hg46c8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8bf0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+BP9KfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+GP9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgbP+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwN/Rn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPi7+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/T38GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgoj+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHw9/VnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/oH+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwD/Un0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GLjqzyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPwj/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4F/rD+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwT/RnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8GbvozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/1R/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4J/pzyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPxz/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4G7/gwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8C/0J9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4l/ozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/0p/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4KE/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8K/1Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv6N/gwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8C/1Z9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hh46s8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8if4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAn+rPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/Dv9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgZf+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwL/Xn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPgz/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4E/159BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hh4688gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8B/0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+B/6g/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8J/0Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bj76M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA/9ZfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Av9GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+i/4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAV38GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgv+rPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/Df9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgf+uP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfDTn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPgf+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/U38GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgf+nPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL3/8P8X/3/9v9p9IjHicLdcxHwEMuNZh1VupVCqVSqVSqVQqlUplMBgMBoPBYDAYDAaDwWAwGAwGg8FgMBgMBoPBYDAYDAaDwWAwGAwGg8HQ6ZzrWa4P8B/u3/NHIBj4/xdkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4E/92f+wSBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPx5/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4G/oD+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwh/4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAX9SfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Ev6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA39ZfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375YyCoP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfBX9GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+qv4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAX9OfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/74J0P/p/zBIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/HX9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgb+hP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfA39WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXP/7Jg/+n/MEgQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8Lf0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bv60/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8Hf0Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/BiL6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA39XfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Dv6c8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8ff0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+BqP4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAP9CfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+If6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA/9IfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375YyCmP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfCP9WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+if4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAP9WfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4YiOvPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/DP9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgX+uP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfAv9GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwYS+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/Un8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgX+nPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/Gv9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgaT+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwL/Rn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPi3+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/Tn8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WMgpT+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHw7/VnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/oP+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwH/Un0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GEjrzyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPwn/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4H/rD+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwX/RnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8GMvozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/1V/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4L/pzyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPx3/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4Gs/gwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8D/0J9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4n/ozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/0t/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvljIKc/gwwxzAijjDHOBJNMMc0Ms8wx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WWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y6DpP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfDv/WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+g/8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAf/SfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4YaPnPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/Cf/GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgf/sP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfBf/GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwba/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/1X8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgv/nPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPB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TbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4YGPrPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/F3/GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgb/nP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfD3/WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwZG/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/5D+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwx/4zyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/8B/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvljYOw/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8A/9Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv6R/wwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8A/9p9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hiY+M8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8E/8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bf+o/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8M/8Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bqb+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA//cfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Bf+M8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8S/8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bmf8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAv/KfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Nf+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA//GfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y2DuP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfBv/WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+nf8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAv/efQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4YWPjPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/Af/GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgT/xn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPiP/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwNL/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4H/5D+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwn/1nkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/ov/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwMp/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4L/6zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPw3/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4H/7j+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DGw9p9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4H/4zyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8Df+o/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8Gf+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfAxv/GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgf/pP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfC//GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+t/8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfA1n8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPg//jPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/F//GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgT/3n0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GNj5zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPyF/wwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8Bf+s8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVX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S6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GLjozyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPwD/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4F/qD+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwj/RnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8GrvozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/1h/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4J/ozyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPxT/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4Gb/gwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8A/059BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj45/ozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/0J/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4K4/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8C/1Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv6V/gwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8C/1p9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hh46M8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8G/0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bf6s/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8O/0Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bp76M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA3+qP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfBn+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/Xn8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgpT+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwH/RnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/lx/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4C/0Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bt76M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA/9RfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+A/6c8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8Z/0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bj/4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAf9GfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Ev9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgf+qP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfDVn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPhv+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/XX8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgf+jPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/PRnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/qf+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwP/Sn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPjf+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwOBv/L//v8AUq5YjHicLdchEwIAl5ZR1E+XVVRUVFRUdFFRUVFRUdElEAgEAoFAIBAIBAKBQCAQCAQCgUAgEAgEAoFAIBAIBAKBQCAQCAQCgUBw3T23nB/wzLwz9w+BPw78/wsyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8Bf+gv/wCBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPxl/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4G/oj+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwB/0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bv6o/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8Nf0Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv5IfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375YyCoP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfDH+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/XX8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgb+jPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL3/8s6H/c/7AIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/E39GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgb+lP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfC39WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXP/7Zg/fn/IFBhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4O/ozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8Df1d/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4O/pzyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DET0Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv6+/gwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8A/0J9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4h/ozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8DUf0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bf6Q/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8I/1Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv6J/gwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx0BMfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Cf6s8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8M/0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bf64/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wxENefQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Bf6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA/9SfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+BP9GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwYS+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/Sn8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgX+vPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/Bv9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgaT+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwL/Vn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPh3+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/Xn8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WMgpT+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwH/RnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/qP+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwH/Sn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GEjrzyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPxn/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4H/oj+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwX/VnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8GMvozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/01/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRde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kf8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAH/nPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/H3/GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgX/gP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MTD2n0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPiH/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/yH8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgH/vPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38MTPxnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/on/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwD/1n0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPhn/jPI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kimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+m/8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAf/efQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4YWPvPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/A//GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgf/pP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfC//GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwY2/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/238GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPg//jPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/F//GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPga3/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwJ/4zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPyp/wwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8Cf+c8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwzs/GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+3H8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgL/xnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/tJ/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvljYP9X/j+0E2lPeJwt0a8fAQCA3mHhgt1HEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBsM0229zNNttss80229ydu9lmm23247PtecP7/AHfP9j/pcD/XZAhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv7y//cPGGSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgb+iP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfBX9WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwYO+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/TX8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgr+vPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/A39GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgaP+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwN/Un0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPhb+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/W38GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgpD+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwR/ozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8Df6w/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8Hf0Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bs76M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA39XfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Dv6c8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8ff0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bi/4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAP9CfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+If6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA/9IfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+CqP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfCP9WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+if4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAP9WfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4YuOnPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/DP9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgX+uP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfAv9GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwbu+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/Un8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgX+nPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/Gv9GWSIYUYYZYxxJphkimlmmGWOeRZY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LLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8Df9CfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Kv6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA39NfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+CP9GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwaC+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/XX8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgj/VnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/ob+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHPxv6n/MHBhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4G/qzyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPwt/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4G/rT+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//PHPHvw/5w8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfA39GfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Lv6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA39PfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375YyCiP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfD39WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+gf4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAP9SfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4YiOrPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/CP9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgX+sP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfBP9GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwZi+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/VH8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgn+nPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/HP9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgbj+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwL/Qn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPiX+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/oj+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DGQ0J9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4V/ozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/1p/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4N/ozyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DCT1Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv6t/gwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8C/059BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj49/ozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8DKf0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+B/6A/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8B/1Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv6T/gwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx0BafwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+A/688gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8F/0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+B/6o/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wxkNGfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+G/6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA/9dfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+B/6M8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwxk9WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+p/4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfA/9KfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+N/6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfAzn9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgf+jP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfB/9WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+VH8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WMg/xf+Pwz4eNd4nC3RoRcBAIDYYeGCtycIgiAIgiAIgiDYZpttdrObbbbZnW222WZ3ttmd22wTBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEHY27vvV74/4PcH+b8W+P8FGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgr/+Vf8AgQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8Df8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bv+k/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wxUPCfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXW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OOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPiH/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/yH8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgH/vPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38MTPxnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/on/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwD/1n0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPhn/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwNT/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4F/7j+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwL/xnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/qX/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwMx/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4F/5zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPyx/wwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8C/9p9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hiY+88gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8G/8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bf+s/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8O/8Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bhb+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA//efwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+A/+M8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8R/8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bpf8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAf/KfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+M/+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA//FfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y2DlP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfBf/WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+m/8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAf/efQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4YWPvPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/A//GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgf/pP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfC//GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwY2/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/238GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPg//jPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/F//GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPga3/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwJ/4zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPyp/wwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8Cf+c8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwzs/GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+3H8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgL/xnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/tJ/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvljYP9X/j8QInlPeJwt0a8fAQCA3mHhgs9OEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBsM0229zNNttss80229ydu9lmm23247PtecP7/AHfP9j/pcD/XZAhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv7y//cPGGSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgb+iP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfBX9WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwYO+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/TX8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgr+vPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/A39GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgaP+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwN/Un0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPhb+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/W38GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgpD+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwR/ozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8Df6w/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8Hf0Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bs76M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA39XfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Dv6c8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8ff0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bi/4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAP9CfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+If6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA/9IfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+CqP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfCP9WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+if4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAP9WfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4YuOnPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/DP9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgX+uP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfAv9GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwbu+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/Un8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgX+nPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/Gv9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgYf+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwL/Rn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPi3+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/Tn8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450P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L/0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+B/60/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wxEPjD//f/Bwq9eIx4nC3WIQMBgIPeYdv+29nONttss80229lmm2222Wab7QRBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEHa7e97yfIBfef8Q+OPA/1+QIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+0l/4BwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Av688gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8Ff0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+BP+jPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/FX9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgb+mP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfBH+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwNB/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4G/rj+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwN/RnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/lh/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvnjn4X+c/7AIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/E39GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgb+lP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfC39WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXP/7Zwftz/sAgQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8Hf0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bv6s/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8Pf0Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/BiL6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA39ffwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Af6M8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8Q/0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+BqP4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAP9KfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Mf6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA/9EfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375YyCmP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfBP9WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+mf4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAP9efQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4YiOvPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/Av9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgX+pP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfAn+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwMJ/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4F/pT+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwr/VnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/o3+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHQFJ/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj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YZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwbyf+H/A2j4iNd4nC3RoRcBAIDYYeGC9yYIgiAIgiAIgiDYZpttdrObbbbZnW222WZ3ttmd22wTBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEHY27vvV74/4PcH+b8W+P8FGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgr/+Vf8AgQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8Df8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bv+k/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wxUPCfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Fv+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA3/bfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Dv+M8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888MvfwwU/WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+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Y4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M1P1nkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/rX/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwL/xn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPi3/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwMN/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4F/5z+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHw7/1nkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/oP/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHQNN/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4D/6zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPwn/xlkiGFGGGWMcSaY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ZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4Q/8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bkf8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAH/nPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/H3/GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgX/gP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MTD2n0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPiH/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/yH8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgH/vPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38MTPxnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/on/DDLEMCOMMsY4E0wyxTQzzDLH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WWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y2DlP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfBf/WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+m/8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAf/efQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4YWPvPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/A//GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgf/pP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfC//GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwY2/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/238GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPg//jPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/F//GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPga3/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwJ/4zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPyp/wwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8Cf+c8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwzs/GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+3H8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgL/xnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/tJ/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvljYP9X/j9sIolPeJwt0a8fAQCA3mHhgs9ngiAIgiAIgiAIgiAIgiAIgiAIgiAIgiAIgiAIgiAIgiAIgttss83ubLPNNttss83u3M02t9lmv/e84X3+gO8f7P9S4P8uyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8Df/j//QMGGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgL+vPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/BX9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgYP+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwF/Vn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPhr+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/XX8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgqD+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwN/RnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/qb+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwN/Sn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GDjpzyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPxt/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4E/0p9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4Y/0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bs/4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfA39GfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Lv6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA39PfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+CiP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfD39WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+gf4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAP9SfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4YuOrPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/CP9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgX+sP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfBP9GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwZu+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/VH8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgn+nPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/HP9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgbv+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwL/Qn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY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c8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8df0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bv6E/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8Df1Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc//snA/yl/MMgQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA39LfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Bv688gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8Hf0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y9/8tj/KX8wyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8Df1d/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4O/pzyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPx9/RlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4Go/gwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8A/0J9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4h/ozyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/0h/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvljIKY/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8I/1Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv6J/gwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8A/1Z9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hiI688gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8M/0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bf64/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8C/0Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/BhL6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA/9SfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+Bf6c8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8a/0ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+BpP4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAv9GfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4Y+Lf6M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA/9OfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375YyClP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfDv9WeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwb+g/4MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAf9SfQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4YSOvPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/Cf9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgf+sP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MfBf9GeQIYYZYZQxxplgkimmmWGWOeZZYJEllllhlTXW2WCTLbbZYZc99jngkCOOOeGUM8654JIrrrnhljvueeCRJ5554ZU33vngky+++eGXPwYy+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/VX8GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WPgv+nPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/Hf9GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgaz+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwP/Qn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPif+jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwP/S38GGWKYEUYZY5wJJplimhlmmWOeBRZZYpkVVlljnQ022WKbHXbZY58DDjnimBNOOeOcCy654pobbrnjngceeeKZF155450PPvnimx9++WMgpz+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwv/VnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/o/+DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwP/Vn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GMj/mf8PxPiY13icLdEhGwEAgJhh4YIgCIIgCIIgCIIguDu72WabbXZzm91ss80222xzN7vZJgiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCsGfPvV95f8D3B/lQ4P8XZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+BP/xr/4BBhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4I/8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+BP/afQYYYZoRRxhhngkmmmGaGWeaYZ4FFllhmhVXWWGeDTbbYZodd9tjngEOOOOaEU84454JLrrjmhlvuuOeBR5545oVX3njng0+++OaHX/4YKPjPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/A3/GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgT/xn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPib/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwNF/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4G/5T+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwt/1nkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G/o7/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHQMl/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4O/6zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPw9/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4G/7z+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DFQ9p9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4B/4zyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/9B/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4B/5zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DFT8Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv6x/wwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8Cf+s8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8E/8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bqv8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAn/nPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/FP/GWSIYUYYZYxxJphkimlmmGWOeRZYZIllVlhljXU22GSLbXbYZY99DjjkiGNOOOWMcy645IprbrjljnseeOSJZ1545Y13Pvjki29++OWPgX/mP4MMMcwIo4wxzgSTTDHNDLPMMc8CiyyxzAqrrLHOBptssc0Ou+yxzwGHHHHMCaeccc4Fl1xxzQ233HHPA4888cwLr7zxzgeffPHND7/8MVDzn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GPjn/jPIEMOMMMoY40wwyRTTzDDLHPMssMgSy6ywyhrrbLDJFtvssMse+xxwyBHHnHDKGedccMkV19xwyx33PPDIE8+88Mob73zwyRff/PDLHwN/7j+DDDHMCKOMMc4Ek0wxzQyzzDHPAossscwKq6yxzgabbLHNDrvssc8BhxxxzAmnnHHOBZdccc0Nt9xxzwOPPPHMC6+88c4Hn3zxzQ+//DHwL/xnkCGGGWGUMcaZYJIppplhljnmWWCRJZZZYZU11tlgky222WGXPfY54JAjjjnhlDPOueCSK6654ZY77nngkSeeeeGVN9754JMvvvnhlz8G6v4zyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/9J/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvlj4F/5zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPxr/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4GG/wwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8C/8Z9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4t/4zyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8D/85/BhlimBFGGWOcCSaZYpoZZpljngUWWWKZFVZZY50NNtlimx122WOfAw454pgTTjnjnAsuueKaG265454HHnnimRdeeeOdDz754psffvljoOk/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8O/9Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv6D/wwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx8B/9J9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hho+c8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8J/8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+B/+w/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8F/8Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Btr+M8gQw4wwyhjjTDDJFNPMMMsc8yywyBLLrLDKGutssMkW2+ywyx77HHDIEceccMoZ51xwyRXX3HDLHfc88MgTz7zwyhvvfPDJF9/88MsfA//VfwYZYpgRRhljnAkmmWKaGWaZY54FFllimRVWWWOdDTbZYpsddtljnwMOOeKYE04545wLLrnimhtuueOeBx554pkXXnnjnQ8++eKbH375Y+C/+c8gQwwzwihjjDPBJFNMM8Msc8yzwCJLLLPCKmuss8EmW2yzwy577HPAIUccc8IpZ5xzwSVXXHPDLXfc88AjTzzzwitvvPPBJ19888Mvfwz8d/8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+Bjv8MMsQwI4wyxjgTTDLFNDPMMsc8CyyyxDIrrLLGOhtsssU2O+yyxz4HHHLEMSeccsY5F1xyxTU33HLHPQ888sQzL7zyxjsffPLFNz/88sfAX/jPIEMMM8IoY4wzwSRTTDPDLHPMs8AiSyyzwiprrLPBJltss8Mue+xzwCFHHHPCKWecc8ElV1xzwy133PPAI08888Irb7zzwSdffPPDL38M/KX/DDLEMCOMMsY4E0wyxTQzzDLHPAssssQyK6yyxjobbLLFNjvsssc+BxxyxDEnnHLGORdccsU1N9xyxz0PPPLEMy+88sY7H3zyxTc//PLHwP/wn0GGGGaEUcYYZ4JJpphmhlnmmGeBRZZYZoVV1lhng0222GaHXfbY54BDjjjmhFPOOOeCS6645oZb7rjngUeeeOaFV95454NPvvjmh1/+GOj6zyBDDDPCKGOMM8EkU0wzwyxzzLPAIksss8Iqa6yzwSZbbLPDLnvsc8AhRxxzwilnnHPBJVdcc8Mtd9zzwCNPPPPCK2+888EnX3zzwy9/DPxP/xlkiGFGGGWMcSaYZIppZphljnkWWGSJZVZYZY11Nthki2122GWPfQ445IhjTjjljHMuuOSKa2645Y57HnjkiWdeeOWNdz745Itvfvjlj4G/8p9BhhhmhFHGGGeCSaaYZoZZ5phngUWWWGaFVdZYZ4NNtthmh1322OeAQ4445oRTzjjngkuuuOaGW+6454FHnnjmhVfeeOeDT7745odf/hj4X/4zyBDDjDDKGONMMMkU08wwyxzzLLDIEsussMoa62ywyRbb7LDLHvsccMgRx5xwyhnnXHDJFdfccMsd9zzwyBPPvPDKG+988MkX3/zwyx8DPf8ZZIhhRhhljHEmmGSKaWaYZY55FlhkiWVWWGWNdTbYZIttdthlj30OOOSIY0445YxzLrjkimtuuOWOex545IlnXnjljXc++OSLb3745Y+B/+0/gwwxzAijjDHOBJNMMc0Ms8wxzwKLLLHMCqussc4Gm2yxzQ677LHPAYccccwJp5xxzgWXXHHNDbfccc8DjzzxzAuvvPHOB5988c0Pv/wx8H/8Z5AhhhlhlDHGmWCSKaaZYZY55llgkSWWWWGVNdbZYJMtttlhlz32OeCQI4454ZQzzrngkiuuueGWO+554JEnnnnhlTfe+eCTL7754Zc/Bv6v/wwyxDAjjDLGOBNMMsU0M8wyxzwLLLLEMiusssY6G2yyxTY77LLHPgcccsQxJ5xyxjkXXHLFNTfccsc9DzzyxDMvvPLGOx988sU3P/zyx0D/r/1/xo2ZE3icLcWRFsIAAADAYBAMBsEgCIJBEAyCIAiCIBgMBoNgMBgMgsEgCAZBEAwGfWhv793JBX24mC0dOvLKsdfeeOvEO++d+uCjTz774qtvzpy7cOm7K9du3Prhzr2ffnnw2x9/PXryz3+nnCPh + + + BwAAAAAAAAAAgAAAAAAAACkgAAAAAAAANQAAAAAAAAA1AAAAAAAAADUAAAAAAAAANQAAAAAAAAA1AAAAAAAAADUAAAAAAAAAHwAAAAAAAAA=eJztwSEBAAAAgKDu/8EeAQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGME7AEx4nO3BIQEAAACAoO7/wR4BCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYwTsATHic7cEhAQAAAICg7v/BHgEKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABjBOwBMeJztwSEBAAAAgKDu/8EeAQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGME7AEx4nO3BIQEAAACAoO7/wR4BCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYwTsATHic7cEhAQAAAICg7v/BHgEKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABjBOwBMeJztwTEBAAAAwqB//QMbRKAAAAAAAAAAgBsDUOZBqg== + + + + + From 11d1eaaf3e94dc8677a68d709a7b87bef2e2a4bf Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Wed, 9 Mar 2016 12:58:47 +0100 Subject: [PATCH 290/402] close_hole + moving close_map in CMap2Builder --- cgogn/core/cmap/cmap2.h | 82 ---------------- cgogn/core/cmap/cmap2_builder.h | 108 +++++++++++++++++++++- cgogn/core/tests/cmap/cmap2_topo_test.cpp | 8 +- 3 files changed, 111 insertions(+), 87 deletions(-) diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index c2206fe3..6dc2c000 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -438,88 +438,6 @@ class CMap2_T : public CMap1_T } } -protected: - - inline void close_hole_topo(Dart d) - { - cgogn_message_assert(phi2(d) == d, "CMap2: close hole called on a dart that is not a phi2 fix point"); - - Dart first = this->add_dart(); // First edge of the face that will fill the hole - phi2_sew(d, first); // phi2-link the new edge to the hole - - Dart d_next = d; // Turn around the hole - Dart d_phi1; // to complete the face - do - { - do - { - d_phi1 = this->phi1(d_next); // Search and put in d_next - d_next = phi2(d_phi1); // the next dart of the hole - } while (d_next != d_phi1 && d_phi1 != d); - - if (d_phi1 != d) - { - Dart next = this->split_vertex_topo(first); // Add a new vertex into the built face - phi2_sew(d_next, next); // and link the face to the hole - } - } while (d_phi1 != d); - } - -protected: - - /** - * @brief close_map closes the map so that there are no phi2 fix points - */ - void close_map() - { - CGOGN_CHECK_CONCRETE_TYPE; - - for (Dart d : *this) - { - if (phi2(d) == d) - { - close_hole_topo(d); - const Face new_face = phi2(d); - - if (this->template is_embedded()) - { - foreach_dart_of_orbit(new_face, [this] (Dart it) - { - this->new_orbit_embedding(CDart(it)); - }); - } - - if (this->template is_embedded()) - { - foreach_dart_of_orbit(new_face, [this] (Dart it) - { - this->template copy_embedding(it, this->phi1(phi2(it))); - }); - } - - if (this->template is_embedded()) - { - foreach_dart_of_orbit(new_face, [this] (Dart it) - { - this->template copy_embedding(it, phi2(it)); - }); - } - - if (this->template is_embedded()) - this->new_orbit_embedding(new_face); - - if (this->template is_embedded()) - { - const unsigned int idx = this->get_embedding(Volume(d)); - foreach_dart_of_orbit(new_face, [this, idx] (Dart it) - { - this->template set_embedding(it, idx); - }); - } - } - } - } - public: inline unsigned int degree(Face f) const diff --git a/cgogn/core/cmap/cmap2_builder.h b/cgogn/core/cmap/cmap2_builder.h index 22d8d5be..d0622e06 100644 --- a/cgogn/core/cmap/cmap2_builder.h +++ b/cgogn/core/cmap/cmap2_builder.h @@ -36,6 +36,11 @@ class CMap2Builder_T using Self = CMap2Builder_T; using CMap2 = cgogn::CMap2; + using CDart = typename CMap2::CDart; + using Vertex = typename CMap2::Vertex; + using Edge = typename CMap2::Edge; + using Face = typename CMap2::Face; + using Volume = typename CMap2::Volume; template using ChunkArrayContainer = typename CMap2::template ChunkArrayContainer; @@ -89,14 +94,111 @@ class CMap2Builder_T return map_.CMap2::Inherit::add_face_topo(nb_edges); } - inline void close_hole_topo(Dart d) + /*! + * \brief Close the topological hole that contains Dart d (a fixed point for PHI2). + * \param d : a vertex of the hole + * \return a vertex of the face that close the hole + * This method is used to close a CMap2 that has been build through the 2-sewing of 1-faces. + * A face is inserted on the boundary that begin at dart d. + */ + inline Dart close_hole_topo(Dart d) { - map_.close_hole_topo(d); + cgogn_message_assert(map_.phi2(d) == d, "CMap2: close hole called on a dart that is not a phi2 fix point"); + + Dart first = map_.add_dart(); // First edge of the face that will fill the hole + map_.phi2_sew(d, first); // 2-sew the new edge to the hole + + Dart d_next = d; // Turn around the hole + Dart d_phi1; // to complete the face + do + { + do + { + d_phi1 = map_.phi1(d_next); // Search and put in d_next + d_next = map_.phi2(d_phi1); // the next dart of the hole + } while (d_next != d_phi1 && d_phi1 != d); + + if (d_phi1 != d) + { + Dart next = map_.split_vertex_topo(first); // Add a vertex into the built face + phi2_sew(d_next, next); // and 2-sew the face to the hole + } + } while (d_phi1 != d); + + return first; } + /*! + * \brief Close a hole with a new face and update the embedding of incident cells. + * \param d : a vertex of the hole + * This method is used to close a CMap2 that has been build through the 2-sewing of 1-faces. + * A face is inserted on the boundary that begin at dart d. + * If the map has Dart, Vertex, Edge, Face or Volume attributes, + * the embedding of the inserted face and incident cells are automatically updated. + * More precisely : + * - a Face attribute is created, if needed, for the face that fill the hole. + * - the Vertex, Edge and Volume attributes are copied, if needed, from incident cells. + */ + inline void close_hole(Dart d) + { + const Face f = close_hole_topo(d); + + if (map_.template is_embedded()) + { + map_.foreach_dart_of_orbit(f, [this] (Dart it) + { + map_.new_orbit_embedding(CDart(it)); + }); + } + + if (map_.template is_embedded()) + { + map_.foreach_dart_of_orbit(f, [this] (Dart it) + { + map_.template copy_embedding(it, map_.phi1(map_.phi2(it))); + }); + } + + if (map_.template is_embedded()) + { + map_.foreach_dart_of_orbit(f, [this] (Dart it) + { + map_.template copy_embedding(it, map_.phi2(it)); + }); + } + + if (map_.template is_embedded()) + map_.new_orbit_embedding(f); + + if (map_.template is_embedded()) + { + const unsigned int idx = map_.get_embedding(Volume(d)); + map_.foreach_dart_of_orbit(f, [this, idx] (Dart it) + { + map_.template set_embedding(it, idx); + }); + } + } + + /*! + * \brief Close the map by inserting faces in its holes and update the embedding of incident cells. + * This method is used to close a CMap2 that has been build through the 2-sewing of 1-faces. + * If the map has Dart, Vertex, Edge, Face or Volume attributes, + * the embedding of the inserted faces and incident cells are automatically updated. + * More precisely : + * - Face attributes are created, if needed, for the faces that fill the holes. + * - Vertex, Edge and Volume attributes are copied, if needed, from incident cells. + * If the indexation of embedding was unique, the closed map is well embedded. + */ inline void close_map() { - map_.close_map(); + for (Dart d : map_) + { + if (map_.phi2(d) == d) + { + close_hole(d); + } + } } private: diff --git a/cgogn/core/tests/cmap/cmap2_topo_test.cpp b/cgogn/core/tests/cmap/cmap2_topo_test.cpp index dacba8fe..0e4b5e95 100644 --- a/cgogn/core/tests/cmap/cmap2_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_topo_test.cpp @@ -24,6 +24,7 @@ #include #include +#include namespace cgogn { @@ -44,6 +45,7 @@ class CMap2TopoTest : public CMap2, public ::testing::Test public: using Inherit = CMap2; + using MapBuilder = CMap2Builder_T; using Vertex = CMap2TopoTest::Vertex; using Edge = CMap2TopoTest::Edge; using Face = CMap2TopoTest::Face; @@ -184,9 +186,10 @@ class CMap2TopoTest : public CMap2, public ::testing::Test } } // Close de map + MapBuilder mbuild(*this); foreach_dart([&](Dart d) { - if (phi2(d) == d) close_hole_topo(d); + if (phi2(d) == d) mbuild.close_hole_topo(d); }); } }; @@ -391,7 +394,8 @@ TEST_F(CMap2TopoTest, close_map) } } - close_map(); + MapBuilder mbuild(*this); + mbuild.close_map(); EXPECT_TRUE(check_map_integrity()); } From 972e93aa45fda5be7313cb69c2e52b0ecdf34b85 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Wed, 9 Mar 2016 13:41:53 +0100 Subject: [PATCH 291/402] using close_map in cmap2 test --- cgogn/core/tests/cmap/cmap2_topo_test.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/cgogn/core/tests/cmap/cmap2_topo_test.cpp b/cgogn/core/tests/cmap/cmap2_topo_test.cpp index 0e4b5e95..055a4443 100644 --- a/cgogn/core/tests/cmap/cmap2_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_topo_test.cpp @@ -187,10 +187,7 @@ class CMap2TopoTest : public CMap2, public ::testing::Test } // Close de map MapBuilder mbuild(*this); - foreach_dart([&](Dart d) - { - if (phi2(d) == d) mbuild.close_hole_topo(d); - }); + mbuild.close_map(); } }; From 7c95120b7ae55450e8effbfdca41b87bcff456f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 9 Mar 2016 14:40:06 +0100 Subject: [PATCH 292/402] fixed compilation with clang. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/data_io.h | 2 +- cgogn/io/io_utils.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cgogn/io/data_io.h b/cgogn/io/data_io.h index d9f2c212..c1691a2c 100644 --- a/cgogn/io/data_io.h +++ b/cgogn/io/data_io.h @@ -256,7 +256,7 @@ class DataInput : public DataInputGen std::vector& res_vec = *(static_cast*>(res->get_data())); res_vec = std::move(this->data_); this->data_ = std::vector(); - return res; + return std::unique_ptr(res.release()); } private: diff --git a/cgogn/io/io_utils.h b/cgogn/io/io_utils.h index b8cdc345..46061cb1 100644 --- a/cgogn/io/io_utils.h +++ b/cgogn/io/io_utils.h @@ -268,18 +268,18 @@ class CGOGN_IO_API IMemoryStream : public std::istream using Inherit = std::istream; using Self = IMemoryStream; - inline IMemoryStream() : Inherit() + inline IMemoryStream() : Inherit(nullptr) { this->init(&buffer_); } - inline IMemoryStream(const char* str) : Inherit(), + inline IMemoryStream(const char* str) : Inherit(nullptr), buffer_(str) { this->init(&buffer_); } - inline IMemoryStream(const char* str, std::size_t size) : Inherit(), + inline IMemoryStream(const char* str, std::size_t size) : Inherit(nullptr), buffer_(str,size) { this->init(&buffer_); From b235877875d609e74bece022170e8a4053ac6ce8 Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Wed, 9 Mar 2016 15:14:48 +0100 Subject: [PATCH 293/402] explicit Cell constructor --- cgogn/core/basic/cell.h | 8 +-- cgogn/core/cmap/cmap0.h | 2 +- cgogn/core/cmap/cmap1.h | 6 +- cgogn/core/cmap/cmap2.h | 2 +- cgogn/core/cmap/cmap3.h | 80 +++++++++++------------ cgogn/core/cmap/map_base.h | 59 +++++++++-------- cgogn/core/examples/map/map.cpp | 3 +- cgogn/core/tests/basic/cell_test.cpp | 10 +-- cgogn/core/tests/cmap/cmap0_topo_test.cpp | 6 +- cgogn/core/tests/cmap/cmap1_test.cpp | 11 ++-- cgogn/core/tests/cmap/cmap1_topo_test.cpp | 9 +-- cgogn/core/tests/cmap/cmap2_test.cpp | 5 +- cgogn/core/tests/cmap/cmap2_topo_test.cpp | 2 +- cgogn/geometry/algos/area.h | 10 +-- cgogn/geometry/algos/ear_triangulation.h | 17 ++--- cgogn/geometry/algos/normal.h | 28 ++++---- cgogn/geometry/tests/algos/algos_test.cpp | 22 +++---- cgogn/io/data_io.h | 2 +- cgogn/io/examples/cmap3_import.cpp | 5 +- cgogn/io/io_utils.h | 6 +- cgogn/io/surface_import.h | 2 +- cgogn/io/volume_import.h | 11 ++-- cgogn/multiresolution/cph/ihcmap2.h | 6 +- 23 files changed, 162 insertions(+), 150 deletions(-) diff --git a/cgogn/core/basic/cell.h b/cgogn/core/basic/cell.h index 3a22b81f..f8e37164 100644 --- a/cgogn/core/basic/cell.h +++ b/cgogn/core/basic/cell.h @@ -105,7 +105,7 @@ class Cell * \brief Creates a new Cell with a dart. * \param[in] d dart to convert to a cell of a given orbit */ - inline Cell(Dart d) : dart(d) + inline explicit Cell(Dart d) : dart(d) {} /** @@ -138,21 +138,21 @@ class Cell * \param[in] rhs the cell to assign * \return The cell with the assigned value */ - Self operator=(Self rhs) { dart = rhs.dart; return *this; } + inline Self& operator=(Self rhs) { dart = rhs.dart; return *this; } /** * \brief Prints a cell to a stream. * \param[out] out the stream to print on * \param[in] rhs the cell to print */ - friend std::ostream& operator<<(std::ostream &out, const Self& rhs) { return out << rhs.dart; } + inline friend std::ostream& operator<<(std::ostream &out, const Self& rhs) { return out << rhs.dart; } /** * \brief Reads a cell from a stream. * \param[in] in the stream to read from * \param[out] rhs the cell read */ - friend std::istream& operator>>(std::istream &in, Self& rhs) { in >> rhs.dart; return in; } + inline friend std::istream& operator>>(std::istream &in, Self& rhs) { in >> rhs.dart; return in; } /** * \brief Name of this CGoGN type diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index 05d7965c..45f7b427 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -121,7 +121,7 @@ class CMap0_T : public MapBase { CGOGN_CHECK_CONCRETE_TYPE; - Vertex v = this->add_dart(); + Vertex v = Vertex(this->add_dart()); if (this->template is_embedded()) this->new_orbit_embedding(v); diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 93599afb..770bcbdc 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -233,7 +233,7 @@ class CMap1_T : public CMap0_T { CGOGN_CHECK_CONCRETE_TYPE; - Face f = add_face_topo(size); + const Face f(add_face_topo(size)); if (this->template is_embedded()) { @@ -298,7 +298,7 @@ class CMap1_T : public CMap0_T { CGOGN_CHECK_CONCRETE_TYPE; - Vertex nv = split_vertex_topo(v); + const Vertex nv(split_vertex_topo(v)); if (this->template is_embedded()) this->new_orbit_embedding(nv); @@ -351,7 +351,7 @@ class CMap1_T : public CMap0_T return this->nb_darts_of_orbit(f); } - inline bool has_degree(Face f, unsigned int degree) + inline bool has_degree(Face f, unsigned int degree) const { Dart it = f.dart ; for (unsigned int i=1;i { CGOGN_CHECK_CONCRETE_TYPE; - const Face f = add_face_topo(size); + const Face f(add_face_topo(size)); if (this->template is_embedded()) { diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 648a406d..dae4e181 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -366,13 +366,13 @@ class CMap3_T : public CMap2_T CGOGN_CHECK_CONCRETE_TYPE; // Search the map for topological holes (fix points of phi3) unsigned int nb = 0u; - for (Dart d: (*this)) + for (Dart d : (*this)) { if (phi3(d) == d) { ++nb; close_hole_topo(d); - const Volume new_volume = phi3(d); + const Volume new_volume(phi3(d)); if (this->template is_embedded()) { @@ -621,7 +621,7 @@ class CMap3_T : public CMap2_T *******************************************************************************/ template - inline void foreach_incident_edge(Vertex v, const FUNC& f) const + inline void foreach_incident_edge(Vertex v, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); DartMarkerStore marker(*this); @@ -630,13 +630,13 @@ class CMap3_T : public CMap2_T if (!marker.is_marked(d)) { foreach_dart_of_PHI23(d, [&marker] (Dart dd) { marker.mark(dd); }); - f(d); + func(Edge(d)); } }); } template - inline void foreach_incident_face(Vertex v, const FUNC& f) const + inline void foreach_incident_face(Vertex v, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); DartMarkerStore marker(*this); @@ -646,13 +646,13 @@ class CMap3_T : public CMap2_T { marker.mark(d); marker.mark(this->phi1(phi3(d))); - f(d); + func(Face(d)); } }); } template - inline void foreach_incident_volume(Vertex v, const FUNC& f) const + inline void foreach_incident_volume(Vertex v, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Volume), "Wrong function cell parameter type"); DartMarkerStore marker(*this); @@ -661,7 +661,7 @@ class CMap3_T : public CMap2_T if (!marker.is_marked(d)) { marker.mark_orbit(Vertex2(d)); - f(d); + func(Volume(d)); } }); } @@ -670,22 +670,22 @@ class CMap3_T : public CMap2_T inline void foreach_incident_vertex(Edge e, const FUNC& f) const { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); - f(e.dart); - f(this->phi2(e.dart)); + f(Vertex(e.dart)); + f(Vertex(this->phi2(e.dart))); } template - inline void foreach_incident_face(Edge e, const FUNC& f) const + inline void foreach_incident_face(Edge e, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); - foreach_dart_of_PHI23(e, f); + foreach_dart_of_PHI23(e, [&func] (Dart d) { func(Face(d)); }); } template - inline void foreach_incident_volume(Edge e, const FUNC& f) const + inline void foreach_incident_volume(Edge e, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Volume), "Wrong function cell parameter type"); - foreach_dart_of_PHI23(e, f); + foreach_dart_of_PHI23(e, [&func] (Dart d) { func(Volume(d)); }); } template @@ -706,29 +706,29 @@ class CMap3_T : public CMap2_T inline void foreach_incident_volume(Face f, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Volume), "Wrong function cell parameter type"); - func(f); - func(phi3(f.dart)); + func(Volume(f)); + func(Volume(phi3(f.dart))); } template - inline void foreach_incident_vertex(Volume v, const FUNC& f) const + inline void foreach_incident_vertex(Volume v, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); - Inherit::foreach_incident_vertex(v, f); + Inherit::foreach_incident_vertex(v, func); } template - inline void foreach_incident_edge(Volume v, const FUNC& f) const + inline void foreach_incident_edge(Volume v, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); - Inherit::foreach_incident_edge(v, f); + Inherit::foreach_incident_edge(v, func); } template - inline void foreach_incident_face(Volume v, const FUNC& f) const + inline void foreach_incident_face(Volume v, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); - Inherit::foreach_incident_face(v, f); + Inherit::foreach_incident_face(v, func); } /******************************************************************************* @@ -736,17 +736,17 @@ class CMap3_T : public CMap2_T *******************************************************************************/ template - inline void foreach_adjacent_vertex_through_edge(Vertex v, const FUNC& f) const + inline void foreach_adjacent_vertex_through_edge(Vertex v, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); foreach_incident_edge(v, [&] (Edge e) { - f(Vertex(this->phi2(e.dart))); + func(Vertex(this->phi2(e.dart))); }); } template - inline void foreach_adjacent_vertex_through_face(Vertex v, const FUNC& f) const + inline void foreach_adjacent_vertex_through_face(Vertex v, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); DartMarker marker_vertex(*this); @@ -758,14 +758,14 @@ class CMap3_T : public CMap2_T if (!marker_vertex.is_marked(vertex_of_face)) { marker_vertex.mark_orbit(vertex_of_face); - f(vertex_of_face); + func(vertex_of_face); } }); }); } template - inline void foreach_adjacent_vertex_through_volume(Vertex v, const FUNC& f) const + inline void foreach_adjacent_vertex_through_volume(Vertex v, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); DartMarker marker_vertex(*this); @@ -777,14 +777,14 @@ class CMap3_T : public CMap2_T if (!marker_vertex.is_marked(inc_vert)) { marker_vertex.mark_orbit(inc_vert); - f(inc_vert); + func(inc_vert); } }); }); } template - inline void foreach_adjacent_edge_through_vertex(Edge e, const FUNC& f) const + inline void foreach_adjacent_edge_through_vertex(Edge e, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); foreach_incident_vertex(e, [&] (Vertex iv) @@ -792,13 +792,13 @@ class CMap3_T : public CMap2_T foreach_incident_edge(iv, [&] (Edge ie) { if (ie.dart != iv.dart) - f(ie); + func(ie); }); }); } template - inline void foreach_adjacent_edge_through_face(Edge e, const FUNC& f) const + inline void foreach_adjacent_edge_through_face(Edge e, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); DartMarker marker_edge(*this); @@ -810,14 +810,14 @@ class CMap3_T : public CMap2_T if (!marker_edge.is_marked(inc_edge)) { marker_edge.mark_orbit(inc_edge); - f(inc_edge); + func(inc_edge); } }); }); } template - inline void foreach_adjacent_edge_through_volume(Edge e, const FUNC& f) const + inline void foreach_adjacent_edge_through_volume(Edge e, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); DartMarker marker_edge(*this); @@ -829,7 +829,7 @@ class CMap3_T : public CMap2_T if (!marker_edge.is_marked(inc_edge)) { marker_edge.mark_orbit(inc_edge); - f(inc_edge); + func(inc_edge); } }); }); @@ -894,7 +894,7 @@ class CMap3_T : public CMap2_T } template - inline void foreach_adjacent_volume_through_vertex(Volume v, const FUNC& f) const + inline void foreach_adjacent_volume_through_vertex(Volume v, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Volume), "Wrong function cell parameter type"); DartMarker marker_volume(*this); @@ -906,14 +906,14 @@ class CMap3_T : public CMap2_T if (!marker_volume.is_marked(inc_vol)) { marker_volume.mark_orbit(inc_vol); - f(inc_vol); + func(inc_vol); } }); }); } template - inline void foreach_adjacent_volume_through_edge(Volume v, const FUNC& f) const + inline void foreach_adjacent_volume_through_edge(Volume v, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Volume), "Wrong function cell parameter type"); DartMarker marker_volume(*this); @@ -925,14 +925,14 @@ class CMap3_T : public CMap2_T if (!marker_volume.is_marked(inc_vol)) { marker_volume.mark_orbit(inc_vol); - f(inc_vol); + func(inc_vol); } }); }); } template - inline void foreach_adjacent_volume_through_face(Volume v, const FUNC& f) const + inline void foreach_adjacent_volume_through_face(Volume v, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Volume), "Wrong function cell parameter type"); DartMarker marker_volume(*this); @@ -944,7 +944,7 @@ class CMap3_T : public CMap2_T if (!marker_volume.is_marked(inc_vol)) { marker_volume.mark_orbit(inc_vol); - f(inc_vol); + func(inc_vol); } }); }); diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 8cc449c7..e0daedfa 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -864,8 +864,9 @@ class MapBase : public MapBaseData { if (!dm.is_marked(d)) { - dm.mark_orbit(CellType(d)); - f(d); + CellType c(d); + dm.mark_orbit(c); + f(c); } } } @@ -906,8 +907,9 @@ class MapBase : public MapBaseData { if (!dm.is_marked(it)) { - dm.template mark_orbit(it); - cells.push_back(Cell(it)); + CellType c(it); + dm.mark_orbit(c); + cells.push_back(c); ++k; } this->topology_.next(it.index); @@ -916,16 +918,16 @@ class MapBase : public MapBaseData futures[i].push_back(thread_pool->enqueue([&cells, &f] (unsigned int th_id) { for (auto c : cells) - f(c,th_id); + f(c, th_id); })); // next thread if (++j == nb_threads_pool) { // again from 0 & change buffer j = 0; - const unsigned int id = (i+1u)%2u; + const unsigned int id = (i+1u) % 2u; for (auto& fu : futures[id]) fu.wait(); - for (auto &b : cells_buffers[id]) + for (auto& b : cells_buffers[id]) dbuffs->release_cell_buffer(b); futures[id].clear(); cells_buffers[id].clear(); @@ -954,10 +956,11 @@ class MapBase : public MapBaseData d != end; this->topology_.next(d.index)) { - if (!cm.is_marked(d)) + CellType c(d); + if (!cm.is_marked(c)) { - cm.mark(d); - f(d); + cm.mark(c); + f(c); } } } @@ -996,10 +999,11 @@ class MapBase : public MapBaseData cells.reserve(PARALLEL_BUFFER_SIZE); for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != end; ) { - if (!cm.is_marked(it)) + CellType c(it); + if (!cm.is_marked(c)) { - cm.mark(it); - cells.push_back(it); + cm.mark(c); + cells.push_back(c); ++k; } this->topology_.next(it.index); @@ -1014,10 +1018,10 @@ class MapBase : public MapBaseData if (++j == nb_threads_pool) { // again from 0 & change buffer j = 0; - const unsigned int id = (i+1u)%2u; + const unsigned int id = (i+1u) % 2u; for (auto& fu : futures[id]) fu.wait(); - for (auto &b : cells_buffers[id]) + for (auto& b : cells_buffers[id]) dbuffs->release_cell_buffer(b); futures[id].clear(); cells_buffers[id].clear(); @@ -1027,13 +1031,12 @@ class MapBase : public MapBaseData // clean all at end for (auto& fu : futures[0u]) fu.wait(); - for (auto &b : cells_buffers[0u]) + for (auto& b : cells_buffers[0u]) dbuffs->release_cell_buffer(b); for (auto& fu : futures[1u]) fu.wait(); - for (auto &b : cells_buffers[1u]) + for (auto& b : cells_buffers[1u]) dbuffs->release_cell_buffer(b); - } template @@ -1046,7 +1049,7 @@ class MapBase : public MapBaseData i != end; this->attributes_[ORBIT].next(i)) { - f((*this->global_topo_cache_[ORBIT])[i]); + f(CellType((*this->global_topo_cache_[ORBIT])[i])); } } @@ -1076,7 +1079,7 @@ class MapBase : public MapBaseData && (static_cast(end - it) > nb_threads_pool)) nbc = static_cast((end - it) / nb_threads_pool); - unsigned int local_end = std::min(it+nbc,end); + unsigned int local_end = std::min(it+nbc, end); const auto& cache = *(this->global_topo_cache_[ORBIT]); @@ -1089,7 +1092,7 @@ class MapBase : public MapBaseData unsigned int loc_it = it; while (loc_it < local_end) { - f(cache[loc_it],th_id); + f(CellType(cache[loc_it]), th_id); attr.next(loc_it); } })); @@ -1126,8 +1129,9 @@ class MapBase : public MapBaseData { if (!dm.is_marked(d)) { - dm.mark_orbit(CellType(d)); - if(!f(d)) + CellType c(d); + dm.mark_orbit(c); + if(!f(c)) break; } } @@ -1144,10 +1148,11 @@ class MapBase : public MapBaseData d != end; this->topology_.next(d.index)) { - if (!cm.is_marked(d)) + CellType c(d); + if (!cm.is_marked(c)) { - cm.mark(d); - if(!f(d)) + cm.mark(c); + if(!f(c)) break; } } @@ -1163,7 +1168,7 @@ class MapBase : public MapBaseData i != end; this->attributes_[ORBIT].next(i)) { - if(!f((*this->global_topo_cache_[ORBIT])[i])) + if(!f(CellType((*this->global_topo_cache_[ORBIT])[i]))) break; } } diff --git a/cgogn/core/examples/map/map.cpp b/cgogn/core/examples/map/map.cpp index 985858ee..a792e54a 100644 --- a/cgogn/core/examples/map/map.cpp +++ b/cgogn/core/examples/map/map.cpp @@ -83,8 +83,7 @@ int test1(MAP& map) std::vector* vertdb = cgogn::get_dart_buffers()->get_buffer(); std::vector* vert_b = reinterpret_cast< std::vector* >(vertdb); - - vert_b->push_back(d1); + vert_b->push_back(typename MAP::Vertex(d1)); vert_b->push_back(typename MAP::Vertex(d1)); cgogn::get_dart_buffers()->release_cell_buffer(vertdb); diff --git a/cgogn/core/tests/basic/cell_test.cpp b/cgogn/core/tests/basic/cell_test.cpp index da88d8f5..3cddaac7 100644 --- a/cgogn/core/tests/basic/cell_test.cpp +++ b/cgogn/core/tests/basic/cell_test.cpp @@ -49,7 +49,7 @@ TEST(CellTest, Constructor) TEST(CellTest, OutOfLimitConstructor) { - Cell c1 = dmax; + Cell c1(dmax); Dart d1 = c1; Cell c2; Dart d2 = c2; @@ -58,7 +58,7 @@ TEST(CellTest, OutOfLimitConstructor) TEST(CellTest, CopyConstructor) { - Cell c = dglobal; + Cell c(dglobal); Dart d = c; Cell ccopy(c); Dart dcopy = ccopy; @@ -67,13 +67,13 @@ TEST(CellTest, CopyConstructor) TEST(CellTest, IsValid) { - Cell c = dglobal; + Cell c(dglobal); EXPECT_TRUE(c.is_valid()); } TEST(CellTest, Assignation) { - Cell c1 = dglobal; + Cell c1(dglobal); Cell c2; c2 = c1; @@ -84,7 +84,7 @@ TEST(CellTest, Assignation) TEST(CellTest, PrintingOut) { - Cell c = dglobal; + Cell c(dglobal); std::ostringstream s; s << "c=" << c; EXPECT_EQ(0, strcmp(s.str().c_str(), "c=10")); diff --git a/cgogn/core/tests/cmap/cmap0_topo_test.cpp b/cgogn/core/tests/cmap/cmap0_topo_test.cpp index 354b1734..270eb39b 100644 --- a/cgogn/core/tests/cmap/cmap0_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap0_topo_test.cpp @@ -110,17 +110,17 @@ TEST_F(CMap0TopoTest, remove_vertex) add_vertices(NB_MAX); int count_vertices = NB_MAX; - cmap_.remove_vertex(darts_.back()); + cmap_.remove_vertex(Vertex(darts_.back())); --count_vertices; EXPECT_EQ(cmap_.nb_darts(), count_vertices); EXPECT_EQ(cmap_.nb_cells(), count_vertices); darts_.pop_back(); - for (Dart d: darts_) + for (Dart d : darts_) { if (std::rand() % 3 == 1) { - cmap_.remove_vertex(d); + cmap_.remove_vertex(Vertex(d)); --count_vertices; } } diff --git a/cgogn/core/tests/cmap/cmap1_test.cpp b/cgogn/core/tests/cmap/cmap1_test.cpp index 84b6d117..8d17f0b0 100644 --- a/cgogn/core/tests/cmap/cmap1_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_test.cpp @@ -120,12 +120,13 @@ TEST_F(CMap1Test, remove_face) unsigned int count_vertices = add_faces(NB_MAX); int count_faces = NB_MAX; - for (Dart d: darts_) + for (Dart d : darts_) { if (std::rand() % 3 == 1) { - unsigned int k = cmap_.degree(d); - cmap_.remove_face(d); + Face f(d); + unsigned int k = cmap_.degree(f); + cmap_.remove_face(f); count_vertices -= k; --count_faces; } @@ -143,9 +144,9 @@ TEST_F(CMap1Test, split_vertex) { unsigned int count_vertices = add_faces(NB_MAX); - for (Dart d: darts_) + for (Dart d : darts_) { - cmap_.split_vertex(d); + cmap_.split_vertex(Vertex(d)); ++count_vertices; } diff --git a/cgogn/core/tests/cmap/cmap1_topo_test.cpp b/cgogn/core/tests/cmap/cmap1_topo_test.cpp index 4c10dee0..af0c926a 100644 --- a/cgogn/core/tests/cmap/cmap1_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_topo_test.cpp @@ -175,8 +175,9 @@ TEST_F(CMap1TopoTest, remove_face) { if (std::rand() % 3 == 1) { - unsigned int k = degree(Face(d)); - remove_face(d); + Face f(d); + unsigned int k = degree(f); + remove_face(f); count_vertices -= k; --count_faces; } @@ -280,7 +281,7 @@ TEST_F(CMap1TopoTest, reverse_face_topo) */ TEST_F(CMap1TopoTest, degree) { - Face f = this->add_face_topo(10u); + Face f(this->add_face_topo(10u)); EXPECT_EQ(degree(f), 10u); } @@ -289,7 +290,7 @@ TEST_F(CMap1TopoTest, degree) */ TEST_F(CMap1TopoTest, has_degree) { - Face f = this->add_face_topo(10u); + Face f(this->add_face_topo(10u)); EXPECT_TRUE(has_degree(f, 10u)); EXPECT_FALSE(has_degree(f, 0u)); diff --git a/cgogn/core/tests/cmap/cmap2_test.cpp b/cgogn/core/tests/cmap/cmap2_test.cpp index 80d42bb1..c147016c 100644 --- a/cgogn/core/tests/cmap/cmap2_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_test.cpp @@ -194,7 +194,8 @@ TEST_F(CMap2Test, cut_edge) { add_closed_surfaces(); - for (Dart d : darts_) cmap_.cut_edge(d); + for (Dart d : darts_) + cmap_.cut_edge(Edge(d)); EXPECT_TRUE(cmap_.check_map_integrity()); } @@ -215,7 +216,7 @@ TEST_F(CMap2Test, cut_face) while (i-- > 0u) e = cmap_.phi1(e); if (e == d) e = cmap_.phi1(e); - cmap_.cut_face(d, e); + cmap_.cut_face(Vertex(d), Vertex(e)); } } EXPECT_TRUE(cmap_.check_map_integrity()); diff --git a/cgogn/core/tests/cmap/cmap2_topo_test.cpp b/cgogn/core/tests/cmap/cmap2_topo_test.cpp index 18b11596..fff86461 100644 --- a/cgogn/core/tests/cmap/cmap2_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_topo_test.cpp @@ -397,7 +397,7 @@ TEST_F(CMap2TopoTest, close_map) TEST_F(CMap2TopoTest, degree) { - Face f = this->add_face_topo(10u); + Face f(this->add_face_topo(10u)); EXPECT_EQ(degree(f), 10u); } diff --git a/cgogn/geometry/algos/area.h b/cgogn/geometry/algos/area.h index 5ba8bd0b..c6483a57 100644 --- a/cgogn/geometry/algos/area.h +++ b/cgogn/geometry/algos/area.h @@ -36,16 +36,18 @@ namespace geometry template inline typename VEC3_T::Scalar triangle_area(const MAP& map, typename MAP::Face f, const typename MAP::template VertexAttributeHandler& position) { + using Vertex = typename MAP::Vertex; return triangle_area( - position[f.dart], - position[map.phi1(f.dart)], - position[map.phi_1(f.dart)] + position[Vertex(f.dart)], + position[Vertex(map.phi1(f.dart))], + position[Vertex(map.phi_1(f.dart))] ); } template inline typename VEC3_T::Scalar convex_face_area(const MAP& map, typename MAP::Face f, const typename MAP::template VertexAttributeHandler& position) { + using Vertex = typename MAP::Vertex; if(map.degree(f) == 3) return triangle_area(map, f, position); else @@ -54,7 +56,7 @@ inline typename VEC3_T::Scalar convex_face_area(const MAP& map, typename MAP::Fa VEC3_T center = centroid(map, f, position); map.foreach_incident_edge(f, [&] (typename MAP::Edge e) { - area += triangle_area(center, position[e.dart], position[map.phi1(e.dart)]); + area += triangle_area(center, position[Vertex(e.dart)], position[Vertex(map.phi1(e.dart))]); }); return area; } diff --git a/cgogn/geometry/algos/ear_triangulation.h b/cgogn/geometry/algos/ear_triangulation.h index 75afb671..7c0672cf 100644 --- a/cgogn/geometry/algos/ear_triangulation.h +++ b/cgogn/geometry/algos/ear_triangulation.h @@ -243,17 +243,18 @@ class EarTriangulation VertexPoly* prem = nullptr; nb_verts_ = 0; convex_ = true; - Vertex a = f.dart; - Vertex b = Vertex(map_.phi1(a)); - Vertex c = Vertex(map_.phi1(b)); + + Dart a = f.dart; + Dart b = map_.phi1(a); + Dart c = map_.phi1(b); do { - const VEC3& P1 = position[a]; - const VEC3& P2 = position[b]; - const VEC3& P3 = position[c]; + const VEC3& P1 = position[Vertex(a)]; + const VEC3& P2 = position[Vertex(b)]; + const VEC3& P3 = position[Vertex(c)]; Scalar val = compute_ear_angle(P1, P2, P3); - VertexPoly* vp = new VertexPoly(b, val, Scalar((P3-P1).squaredNorm()), vpp); + VertexPoly* vp = new VertexPoly(Vertex(b), val, Scalar((P3-P1).squaredNorm()), vpp); if (vp->value_ > 5.0f) // concav angle convex_ = false; @@ -265,7 +266,7 @@ class EarTriangulation b = c; c = map_.phi1(c); nb_verts_++; - } while (a.dart != f.dart); + } while (a != f.dart); VertexPoly::close(prem, vpp); diff --git a/cgogn/geometry/algos/normal.h b/cgogn/geometry/algos/normal.h index 9625b6d4..7ecd74fa 100644 --- a/cgogn/geometry/algos/normal.h +++ b/cgogn/geometry/algos/normal.h @@ -41,10 +41,11 @@ namespace geometry template inline VEC3 triangle_normal(const MAP& map, Cell f, const typename MAP::template VertexAttributeHandler& position) { + using Vertex = typename MAP::Vertex; VEC3 n = triangle_normal( - position[f.dart], - position[map.phi1(f.dart)], - position[map.phi_1(f.dart)] + position[Vertex(f.dart)], + position[Vertex(map.phi1(f.dart))], + position[Vertex(map.phi_1(f.dart))] ); normalize_safe(n); return n; @@ -53,12 +54,13 @@ inline VEC3 triangle_normal(const MAP& map, Cell f, const typename template inline VEC3 newell_normal(const MAP& map, Cell f, const typename MAP::template VertexAttributeHandler& position) { + using Vertex = typename MAP::Vertex; using Scalar = typename cgogn::geometry::vector_traits::Scalar; VEC3 n{Scalar(0), Scalar(0), Scalar(0)}; map.foreach_incident_vertex(f, [&] (Cell v) { - const VEC3& p = position[v.dart]; - const VEC3& q = position[map.phi1(v.dart)]; + const VEC3& p = position[Vertex(v.dart)]; + const VEC3& q = position[Vertex(map.phi1(v.dart))]; n[0] += (p[1] - q[1]) * (p[2] + q[2]); n[1] += (p[2] - q[2]) * (p[0] + q[0]); n[2] += (p[0] - q[0]) * (p[1] + q[1]); @@ -70,7 +72,7 @@ inline VEC3 newell_normal(const MAP& map, Cell f, const typename MA template inline VEC3 face_normal(const MAP& map, Cell f, const typename MAP::template VertexAttributeHandler& position) { - if (map.degree(f) == 3) + if (map.has_degree(f, 3)) return triangle_normal(map, f, position); else return newell_normal(map, f, position); @@ -79,15 +81,16 @@ inline VEC3 face_normal(const MAP& map, Cell f, const typename MAP: template inline VEC3 vertex_normal(const MAP& map, Cell v, const typename MAP::template VertexAttributeHandler& position) { + using Vertex = typename MAP::Vertex; using Scalar = typename VEC3::Scalar; VEC3 n{Scalar{0}, Scalar{0}, Scalar{0}}; - const VEC3& p = position[v.dart]; + const VEC3& p = position[Vertex(v.dart)]; map.foreach_incident_face(v, [&] (Cell f) { VEC3 facen = face_normal(map, f, position); - const VEC3& p1 = position[map.phi1(f.dart)]; - const VEC3& p2 = position[map.phi_1(f.dart)]; + const VEC3& p1 = position[Vertex(map.phi1(f.dart))]; + const VEC3& p2 = position[Vertex(map.phi_1(f.dart))]; const Scalar l = (p1-p).squaredNorm() * (p2-p).squaredNorm(); if (l != Scalar(0)) facen *= convex_face_area(map, f, position) / l; @@ -100,15 +103,16 @@ inline VEC3 vertex_normal(const MAP& map, Cell v, const typename M template inline VEC3 vertex_normal(const MAP& map, Cell v, const typename MAP::template VertexAttributeHandler& position, const typename MAP::template AttributeHandler& fnormal) { + using Vertex = typename MAP::Vertex; using Scalar = typename VEC3::Scalar; VEC3 n{Scalar{0}, Scalar{0} ,Scalar{0}}; - const VEC3& p = position[v.dart]; + const VEC3& p = position[Vertex(v.dart)]; map.foreach_incident_face(v, [&] (Cell f) { VEC3 facen = fnormal[f]; - const VEC3& p1 = position[map.phi1(f.dart)]; - const VEC3& p2 = position[map.phi_1(f.dart)]; + const VEC3& p1 = position[Vertex(map.phi1(f.dart))]; + const VEC3& p2 = position[Vertex(map.phi_1(f.dart))]; const Scalar l = (p1-p).squaredNorm() * (p2-p).squaredNorm(); if (l != Scalar(0)) facen *= convex_face_area(map, f, position) / l; diff --git a/cgogn/geometry/tests/algos/algos_test.cpp b/cgogn/geometry/tests/algos/algos_test.cpp index 34c60c19..3db4d402 100644 --- a/cgogn/geometry/tests/algos/algos_test.cpp +++ b/cgogn/geometry/tests/algos/algos_test.cpp @@ -65,8 +65,8 @@ TYPED_TEST(Algos_TEST, TriangleArea) using Scalar = typename cgogn::geometry::vector_traits::Scalar; cgogn::io::import_surface(this->map2_, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); VertexAttributeHandler vertex_position = this->map2_.template get_attribute("position"); - const Scalar area = cgogn::geometry::triangle_area(this->map2_, *this->map2_.begin(), vertex_position); - const Scalar cf_area = cgogn::geometry::convex_face_area(this->map2_, *this->map2_.begin(), vertex_position); + const Scalar area = cgogn::geometry::triangle_area(this->map2_, Face(*this->map2_.begin()), vertex_position); + const Scalar cf_area = cgogn::geometry::convex_face_area(this->map2_, Face(*this->map2_.begin()), vertex_position); EXPECT_DOUBLE_EQ(area, Scalar(12.5f)); EXPECT_DOUBLE_EQ(cf_area, Scalar(12.5f)); } @@ -76,7 +76,7 @@ TYPED_TEST(Algos_TEST, QuadArea) using Scalar = typename cgogn::geometry::vector_traits::Scalar; cgogn::io::import_surface(this->map2_, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); VertexAttributeHandler vertex_position = this->map2_.template get_attribute("position"); - const Scalar area = cgogn::geometry::convex_face_area(this->map2_, *this->map2_.begin(), vertex_position); + const Scalar area = cgogn::geometry::convex_face_area(this->map2_, Face(*this->map2_.begin()), vertex_position); EXPECT_DOUBLE_EQ(area, Scalar(10)); } @@ -85,7 +85,7 @@ TYPED_TEST(Algos_TEST, TriangleCentroid) using Scalar = typename cgogn::geometry::vector_traits::Scalar; cgogn::io::import_surface(this->map2_, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); VertexAttributeHandler vertex_position = this->map2_.template get_attribute("position"); - const TypeParam centroid = cgogn::geometry::centroid(this->map2_, CMap2::Face(*this->map2_.begin()), vertex_position); + const TypeParam centroid = cgogn::geometry::centroid(this->map2_, Face(*this->map2_.begin()), vertex_position); EXPECT_DOUBLE_EQ(centroid[0], Scalar(5)/Scalar(3)); EXPECT_DOUBLE_EQ(centroid[1], Scalar(5)/Scalar(3)); EXPECT_DOUBLE_EQ(centroid[2], Scalar(0)); @@ -96,7 +96,7 @@ TYPED_TEST(Algos_TEST, QuadCentroid) using Scalar = typename cgogn::geometry::vector_traits::Scalar; cgogn::io::import_surface(this->map2_, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); VertexAttributeHandler vertex_position = this->map2_.template get_attribute("position"); - const TypeParam centroid = cgogn::geometry::centroid(this->map2_, CMap2::Face(*this->map2_.begin()), vertex_position); + const TypeParam centroid = cgogn::geometry::centroid(this->map2_, Face(*this->map2_.begin()), vertex_position); EXPECT_DOUBLE_EQ(centroid[0], Scalar(2.5f)); EXPECT_DOUBLE_EQ(centroid[1], Scalar(1)); EXPECT_DOUBLE_EQ(centroid[2], Scalar(0)); @@ -107,8 +107,8 @@ TYPED_TEST(Algos_TEST, TriangleNormal) using Scalar = typename cgogn::geometry::vector_traits::Scalar; cgogn::io::import_surface(this->map2_, std::string(DEFAULT_MESH_PATH) + std::string("singleTriangle.obj")); VertexAttributeHandler vertex_position = this->map2_.template get_attribute("position"); - const TypeParam& n1 = cgogn::geometry::triangle_normal(this->map2_, CMap2::Face(*this->map2_.begin()), vertex_position); - const TypeParam& n2 = cgogn::geometry::face_normal(this->map2_, CMap2::Face(*this->map2_.begin()), vertex_position); + const TypeParam& n1 = cgogn::geometry::triangle_normal(this->map2_, Face(*this->map2_.begin()), vertex_position); + const TypeParam& n2 = cgogn::geometry::face_normal(this->map2_, Face(*this->map2_.begin()), vertex_position); EXPECT_TRUE(cgogn::almost_equal_relative(n1[0], n2[0])); EXPECT_TRUE(cgogn::almost_equal_relative(n1[1], n2[1])); EXPECT_TRUE(cgogn::almost_equal_relative(n1[2], n2[2])); @@ -124,7 +124,7 @@ TYPED_TEST(Algos_TEST, QuadNormal) using Scalar = typename cgogn::geometry::vector_traits::Scalar; cgogn::io::import_surface(this->map2_, std::string(DEFAULT_MESH_PATH) + std::string("singleQuad.obj")); VertexAttributeHandler vertex_position = this->map2_.template get_attribute("position"); - const TypeParam& n1 = cgogn::geometry::face_normal(this->map2_, CMap2::Face(*this->map2_.begin()), vertex_position); + const TypeParam& n1 = cgogn::geometry::face_normal(this->map2_, Face(*this->map2_.begin()), vertex_position); const TypeParam& cross = n1.cross(TypeParam(Scalar(0), Scalar(0), Scalar(1))); EXPECT_TRUE(cgogn::almost_equal_relative(cross[0], Scalar(0))); EXPECT_TRUE(cgogn::almost_equal_relative(cross[1], Scalar(0))); @@ -155,16 +155,16 @@ TYPED_TEST(Algos_TEST, EarTriangulation) EXPECT_TRUE(indices.size() == 9); Scalar area = 0; - for (size_t i=0; i(this->map2_,f,vertex_position); + cgogn::geometry::apply_ear_triangulation(this->map2_, f, vertex_position); EXPECT_TRUE(this->map2_.template nb_cells()==4); EXPECT_TRUE(this->map2_.template nb_cells()==7); } diff --git a/cgogn/io/data_io.h b/cgogn/io/data_io.h index d9f2c212..c1691a2c 100644 --- a/cgogn/io/data_io.h +++ b/cgogn/io/data_io.h @@ -256,7 +256,7 @@ class DataInput : public DataInputGen std::vector& res_vec = *(static_cast*>(res->get_data())); res_vec = std::move(this->data_); this->data_ = std::vector(); - return res; + return std::unique_ptr(res.release()); } private: diff --git a/cgogn/io/examples/cmap3_import.cpp b/cgogn/io/examples/cmap3_import.cpp index 2509f1fd..f1dc1c0f 100644 --- a/cgogn/io/examples/cmap3_import.cpp +++ b/cgogn/io/examples/cmap3_import.cpp @@ -48,7 +48,6 @@ int main(int argc, char** argv) map.enable_topo_cache(); map.enable_topo_cache(); - unsigned int nbw = 0u; map.foreach_cell([&nbw] (Map3::Volume) { @@ -59,8 +58,8 @@ int main(int argc, char** argv) map.foreach_cell([&] (Map3::Face f) { ++nbf; - Vec3 v1 = vertex_position[map.phi1(f.dart)] - vertex_position[f.dart]; - Vec3 v2 = vertex_position[map.phi_1(f.dart)] - vertex_position[f.dart]; + Vec3 v1 = vertex_position[Map3::Vertex(map.phi1(f.dart))] - vertex_position[Map3::Vertex(f.dart)]; + Vec3 v2 = vertex_position[Map3::Vertex(map.phi_1(f.dart))] - vertex_position[Map3::Vertex(f.dart)]; }); unsigned int nbv = 0; diff --git a/cgogn/io/io_utils.h b/cgogn/io/io_utils.h index b8cdc345..46061cb1 100644 --- a/cgogn/io/io_utils.h +++ b/cgogn/io/io_utils.h @@ -268,18 +268,18 @@ class CGOGN_IO_API IMemoryStream : public std::istream using Inherit = std::istream; using Self = IMemoryStream; - inline IMemoryStream() : Inherit() + inline IMemoryStream() : Inherit(nullptr) { this->init(&buffer_); } - inline IMemoryStream(const char* str) : Inherit(), + inline IMemoryStream(const char* str) : Inherit(nullptr), buffer_(str) { this->init(&buffer_); } - inline IMemoryStream(const char* str, std::size_t size) : Inherit(), + inline IMemoryStream(const char* str, std::size_t size) : Inherit(nullptr), buffer_(str,size) { this->init(&buffer_); diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index c7aad940..99631567 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -167,7 +167,7 @@ class SurfaceImport : public MeshImportGen { unsigned int vertex_index = map.get_embedding(Vertex(d)); - std::vector& next_vertex_darts = darts_per_vertex[map.phi1(d)]; + std::vector& next_vertex_darts = darts_per_vertex[Vertex(map.phi1(d))]; bool phi2_found = false; bool first_OK = true; diff --git a/cgogn/io/volume_import.h b/cgogn/io/volume_import.h index 25c0595c..b472c3b6 100644 --- a/cgogn/io/volume_import.h +++ b/cgogn/io/volume_import.h @@ -54,6 +54,8 @@ class VolumeImport : public MeshImportGen using Map = CMap3; using Vertex = typename Map::Vertex; using Volume = typename Map::Volume; + using Face = typename Map::Face; + using Face2 = typename Map::Face2; static const unsigned int CHUNK_SIZE = MAP_TRAITS::CHUNK_SIZE; @@ -98,11 +100,8 @@ class VolumeImport : public MeshImportGen volume_attributes_.remove_attributes(); } - bool create_map(Map& map) { - using Face = typename Map::Face; - if (this->nb_vertices_ == 0u) return false; @@ -256,7 +255,7 @@ class VolumeImport : public MeshImportGen { if (m.is_marked(d)) { - std::vector& vec = darts_per_vertex[map.phi1(d)]; + std::vector& vec = darts_per_vertex[Vertex(map.phi1(d))]; Dart good_dart; for(auto it = vec.begin(); it != vec.end() && good_dart.is_nil(); ++it) @@ -284,14 +283,14 @@ class VolumeImport : public MeshImportGen f1_it = map.phi1(f1_it); f2_it = map.phi_1(f2_it); } while (f1_it != d); - m.template unmark_orbit(d); + m.unmark_orbit(Face(d)); } // else // std::cout << "erreur : degD != degGD" << std::endl; } else { - m.template unmark_orbit(d); + m.unmark_orbit(Face2(d)); ++nbBoundaryFaces; } } diff --git a/cgogn/multiresolution/cph/ihcmap2.h b/cgogn/multiresolution/cph/ihcmap2.h index f1d23de7..a35fa4e6 100644 --- a/cgogn/multiresolution/cph/ihcmap2.h +++ b/cgogn/multiresolution/cph/ihcmap2.h @@ -249,18 +249,18 @@ class IHCMap2_T : public CMap2_T, public CPH2 */ Face add_face(unsigned int size) { - Face f = this->add_face_topo(size); + Face f(this->add_face_topo(size)); if (this->template is_embedded()) foreach_dart_of_orbit(f, [this] (Dart d) { - this->template new_orbit_embedding(d); + this->new_orbit_embedding(CDart(d)); }); if (this->template is_embedded()) foreach_dart_of_orbit(f, [this] (Dart v) { - this->template new_orbit_embedding(v); + this->new_orbit_embedding(Vertex(v)); }); if (this->template is_embedded()) From 2a122cc3223dcbeccd77e431df2f5c8bdc1f98db Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Wed, 9 Mar 2016 15:16:12 +0100 Subject: [PATCH 294/402] minor change --- cgogn/core/cmap/cmap0.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index 45f7b427..d79b67f2 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -121,7 +121,7 @@ class CMap0_T : public MapBase { CGOGN_CHECK_CONCRETE_TYPE; - Vertex v = Vertex(this->add_dart()); + const Vertex v(this->add_dart()); if (this->template is_embedded()) this->new_orbit_embedding(v); From a9bf3e6540272ab2d11fdbeb486b2e607629cd0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 9 Mar 2016 15:28:25 +0100 Subject: [PATCH 295/402] fixed warnings (missing override and no return) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/vtk_io.h | 81 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 26 deletions(-) diff --git a/cgogn/io/vtk_io.h b/cgogn/io/vtk_io.h index 5cd83549..03289afb 100644 --- a/cgogn/io/vtk_io.h +++ b/cgogn/io/vtk_io.h @@ -112,8 +112,13 @@ protected : #endif } } - - bool parse_vtk_legacy_file(std::ifstream& fp) + /** + * @brief parse_vtk_legacy_file + * @param fp + * @return + * NOTE : by default binary data seems to be stored in big endian order. + */ + bool parse_vtk_legacy_file(std::ifstream& fp, bool big_endian = true) { VTK_MESH_TYPE vtk_type(VTK_MESH_TYPE::UNKNOWN); @@ -164,7 +169,7 @@ protected : sstream >> nb_vertices >> type_str; type_str = to_lower(type_str); auto pos = DataInputGen::template newDataIO(type_str, 3); - pos->read_n(fp, nb_vertices, !ascii_file, false); + pos->read_n(fp, nb_vertices, !ascii_file, big_endian); this->add_vertex_attribute(*pos,"position"); this->positions_ = *dynamic_cast_unique_ptr>(pos->simplify()); } else { @@ -172,7 +177,7 @@ protected : { unsigned int size; sstream >> nb_cells >> size; - cells_.read_n(fp, size, !ascii_file, false); + cells_.read_n(fp, size, !ascii_file, big_endian); std::vector* cell_types_vec = static_cast*>(cell_types_.get_data()); cgogn_assert(cell_types_vec != nullptr); @@ -197,7 +202,7 @@ protected : { unsigned int nbc; sstream >> nbc; - cell_types_.read_n(fp, nbc, !ascii_file, false); + cell_types_.read_n(fp, nbc, !ascii_file, big_endian); } else { if (word == "POINT_DATA" || word == "CELL_DATA") { @@ -242,7 +247,7 @@ protected : } std::unique_ptr att(DataInputGen::template newDataIO(att_type, num_comp)); - att->read_n(fp, nb_data, !ascii_file, false); + att->read_n(fp, nb_data, !ascii_file, big_endian); if (cell_data) this->add_cell_attribute(*att, att_name); else @@ -268,7 +273,7 @@ protected : sstream >> data_name >> nb_comp >> nb_data >> data_type; std::cout << "reading field \"" << data_name << "\" of type " << data_type << " (" << nb_comp << " components)." << std::endl; std::unique_ptr att(DataInputGen::template newDataIO(data_type, nb_comp)); - att->read_n(fp, nb_data, !ascii_file, false); + att->read_n(fp, nb_data, !ascii_file, big_endian); if (cell_data) this->add_cell_attribute(*att, data_name); else @@ -532,11 +537,53 @@ class VtkSurfaceImport : public VtkIO: virtual ~VtkSurfaceImport() override {} protected: + + inline bool read_xml_file(const std::string& filename) + { + if (!Inherit_Vtk::parse_xml_vtu(filename)) + return false; + this->fill_surface_import(); + return true; + } + inline bool read_vtk_legacy_file(std::ifstream& fp) { if (!Inherit_Vtk::parse_vtk_legacy_file(fp)) return false; + this->fill_surface_import(); + return true; + } + + virtual void add_vertex_attribute(const DataInputGen& attribute_data, const std::string& attribute_name) override + { + attribute_data.to_chunk_array(attribute_data.add_attribute(this->vertex_attributes_, attribute_name)); + } + virtual void add_cell_attribute(const DataInputGen& attribute_data, const std::string& attribute_name) override + { + attribute_data.to_chunk_array(attribute_data.add_attribute(this->face_attributes_, attribute_name)); + } + virtual bool import_file_impl(const std::string& filename) override + { + const FileType file_type = get_file_type(filename); + switch (file_type) + { + case FileType::FileType_VTK_LEGACY: + { + std::ifstream fp(filename.c_str(), std::ios::in); + cgogn_assert(fp.good()); + return this->read_vtk_legacy_file(fp); + } + case FileType::FileType_VTU: + return this->read_xml_file(filename); + default: + std::cerr << "VtkSurfaceImport does not handle the files of type \"" << get_extension(filename) << "\"." << std::endl; + return false; + } + } +private: + inline void fill_surface_import() + { this->nb_vertices_ = this->positions_.size(); this->nb_faces_ = this->cell_types_.size(); @@ -575,24 +622,6 @@ class VtkSurfaceImport : public VtkIO: } } } - return true; - } - - virtual void add_vertex_attribute(const DataInputGen& attribute_data, const std::string& attribute_name) override - { - attribute_data.to_chunk_array(attribute_data.add_attribute(this->vertex_attributes_, attribute_name)); - } - virtual void add_cell_attribute(const DataInputGen& attribute_data, const std::string& attribute_name) override - { - attribute_data.to_chunk_array(attribute_data.add_attribute(this->face_attributes_, attribute_name)); - } - virtual bool import_file_impl(const std::string& filename) - { - std::ifstream fp(filename.c_str(), std::ios::in | std::ios::binary); - cgogn_assert(fp.good()); - const FileType file_type = get_file_type(filename); - if (file_type == FileType::FileType_VTK_LEGACY) - return this->read_vtk_legacy_file(fp); } }; @@ -686,7 +715,7 @@ class VtkVolumeImport : public VtkIO:: attribute_data.to_chunk_array(attribute_data.add_attribute(this->volume_attributes_, attribute_name)); } - virtual bool import_file_impl(const std::string& filename) + virtual bool import_file_impl(const std::string& filename) override { const FileType file_type = get_file_type(filename); switch (file_type) { From 3c3097ce0218eae35add4477ce5c209b5010c448 Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Wed, 9 Mar 2016 15:40:49 +0100 Subject: [PATCH 296/402] merge --- cgogn/core/cmap/cmap2.h | 2 +- cgogn/core/cmap/cmap2_builder.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index fd1b4213..2a9a62ce 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -479,7 +479,7 @@ class CMap2_T : public CMap1_T if (phi2(d) == d) { close_hole_topo(d); - const Face new_face = phi2(d); + const Face new_face(phi2(d)); if (this->template is_embedded()) { diff --git a/cgogn/core/cmap/cmap2_builder.h b/cgogn/core/cmap/cmap2_builder.h index d0622e06..4d6b120b 100644 --- a/cgogn/core/cmap/cmap2_builder.h +++ b/cgogn/core/cmap/cmap2_builder.h @@ -141,7 +141,7 @@ class CMap2Builder_T */ inline void close_hole(Dart d) { - const Face f = close_hole_topo(d); + const Face f(close_hole_topo(d)); if (map_.template is_embedded()) { From 0cb339e16290926ef3490f9f446f192aec93bc8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 9 Mar 2016 15:47:00 +0100 Subject: [PATCH 297/402] Fixed Eigen warnings and removed close_map and close_hole_topo from map2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/cmap2.h | 82 ---------------------------------- cgogn/geometry/CMakeLists.txt | 4 +- cgogn/io/CMakeLists.txt | 1 - cgogn/rendering/CMakeLists.txt | 1 - 4 files changed, 3 insertions(+), 85 deletions(-) diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 05369faf..abae8625 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -438,88 +438,6 @@ class CMap2_T : public CMap1_T } } -protected: - - inline void close_hole_topo(Dart d) - { - cgogn_message_assert(phi2(d) == d, "CMap2: close hole called on a dart that is not a phi2 fix point"); - - Dart first = this->add_dart(); // First edge of the face that will fill the hole - phi2_sew(d, first); // phi2-link the new edge to the hole - - Dart d_next = d; // Turn around the hole - Dart d_phi1; // to complete the face - do - { - do - { - d_phi1 = this->phi1(d_next); // Search and put in d_next - d_next = phi2(d_phi1); // the next dart of the hole - } while (d_next != d_phi1 && d_phi1 != d); - - if (d_phi1 != d) - { - Dart next = this->split_vertex_topo(first); // Add a new vertex into the built face - phi2_sew(d_next, next); // and link the face to the hole - } - } while (d_phi1 != d); - } - -protected: - - /** - * @brief close_map closes the map so that there are no phi2 fix points - */ - void close_map() - { - CGOGN_CHECK_CONCRETE_TYPE; - - for (Dart d : *this) - { - if (phi2(d) == d) - { - close_hole_topo(d); - const Face new_face = phi2(d); - - if (this->template is_embedded()) - { - foreach_dart_of_orbit(new_face, [this] (Dart it) - { - this->new_orbit_embedding(CDart(it)); - }); - } - - if (this->template is_embedded()) - { - foreach_dart_of_orbit(new_face, [this] (Dart it) - { - this->template copy_embedding(it, this->phi1(phi2(it))); - }); - } - - if (this->template is_embedded()) - { - foreach_dart_of_orbit(new_face, [this] (Dart it) - { - this->template copy_embedding(it, phi2(it)); - }); - } - - if (this->template is_embedded()) - this->new_orbit_embedding(new_face); - - if (this->template is_embedded()) - { - const unsigned int idx = this->get_embedding(Volume(d)); - foreach_dart_of_orbit(new_face, [this, idx] (Dart it) - { - this->template set_embedding(it, idx); - }); - } - } - } - } - public: inline unsigned int degree(Face f) const diff --git a/cgogn/geometry/CMakeLists.txt b/cgogn/geometry/CMakeLists.txt index de5d3707..955eed17 100644 --- a/cgogn/geometry/CMakeLists.txt +++ b/cgogn/geometry/CMakeLists.txt @@ -30,8 +30,10 @@ add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "_d") + target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC + $ +) target_include_directories(${PROJECT_NAME} PUBLIC - $ $ $ ) diff --git a/cgogn/io/CMakeLists.txt b/cgogn/io/CMakeLists.txt index 4cb73230..79cd7772 100644 --- a/cgogn/io/CMakeLists.txt +++ b/cgogn/io/CMakeLists.txt @@ -40,7 +40,6 @@ add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "_d") target_include_directories(${PROJECT_NAME} PUBLIC - $ $ $ $ diff --git a/cgogn/rendering/CMakeLists.txt b/cgogn/rendering/CMakeLists.txt index 5ecb840b..a7f10a95 100644 --- a/cgogn/rendering/CMakeLists.txt +++ b/cgogn/rendering/CMakeLists.txt @@ -39,7 +39,6 @@ add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "_d") target_include_directories(${PROJECT_NAME} PUBLIC - $ $ $ $ From 71d75d484da94117869f17729c4dd2c3ec2d7ebf Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Wed, 9 Mar 2016 16:07:31 +0100 Subject: [PATCH 298/402] picking mt --- cgogn/geometry/algos/picking.h | 185 +++++++++++++++--- cgogn/geometry/functions/intersection.h | 16 +- .../tests/functions/intersection_test.cpp | 16 +- cgogn/rendering/examples/picking_viewer.cpp | 184 +++++++++++++---- cgogn/rendering/map_render.h | 36 ++++ 5 files changed, 361 insertions(+), 76 deletions(-) diff --git a/cgogn/geometry/algos/picking.h b/cgogn/geometry/algos/picking.h index 442e6dbf..4ca51e53 100644 --- a/cgogn/geometry/algos/picking.h +++ b/cgogn/geometry/algos/picking.h @@ -26,6 +26,8 @@ #include #include +#include + #include #include @@ -33,69 +35,206 @@ #include #include +#include + namespace cgogn { namespace geometry { -//template -//inline void picking_vertices(MAP& map, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename VEC3::Scalar dist, typename std::vector selected) -//{ -// VEC3 AB = B - A ; -// cgogn_message_assert(AB.squaredNorm()>0.0,"line must be defined by 2 different points"); -// AB.normalize(); - -// selected.clear(); -// map.foreach_cell([&] (typename MAP::Vertex v) -// { -// if(squared_distance_normalized_line_point(A,AB,position[v])< dist*dist) -// selected.push_back(v); -// }); -//} template -inline void picking_face(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector selected) +inline void picking_internal_face(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector>& selected ) { using Vertex = typename MAP::Vertex; using Face = typename MAP::Face; + using Scalar = typename VEC3::Scalar; + VEC3 AB = B - A ; cgogn_message_assert(AB.squaredNorm()>0.0,"line must be defined by 2 different points"); AB.normalize(); - selected.clear(); - std::vector ear_indices; - ear_indices.reserve(256); - m.foreach_cell([&] (Face f) + // thread data + using Triplet = typename std::vector>; + std::vector selected_th(cgogn::get_nb_threads()); + std::vector> ear_indices_th(cgogn::get_nb_threads()); + + m.parallel_foreach_cell([&] (Face f, unsigned int th) { + VEC3 inter; if (m.has_degree(f,3)) { const VEC3& p1 = position[Vertex(f.dart)]; const VEC3& p2 = position[Vertex(m.phi1(f.dart))]; const VEC3& p3 = position[Vertex(m.phi1(m.phi1(f.dart)))]; - if (intersection_ray_triangle(A,AB,p1,p2,p3)) - selected.push_back(f); + if (intersection_ray_triangle(A,AB,p1,p2,p3,&inter)) + selected_th[th].push_back(std::make_tuple(f,inter,(inter-A).squaredNorm())); } else { + std::vector& ear_indices = ear_indices_th[th]; + ear_indices.clear(); cgogn::geometry::compute_ear_triangulation(m,f,position,ear_indices); for(unsigned int i=0; i(A,AB,p1,p2,p3)) + if (intersection_ray_triangle(A,AB,p1,p2,p3,&inter)) { - selected.push_back(f); + selected_th[th].push_back(std::make_tuple(f,inter,(inter-A).squaredNorm())); i = ear_indices.size(); } } } }); + + //merging thread result + for (unsigned int i=0;i& f1, const std::tuple& f2) -> bool + { + return std::get<2>(f1) < std::get<2>(f2); + }; + + // sorting + std::sort(selected.begin(),selected.end(),dist_sort); +} + +template +bool picking_face(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector& selected) +{ + typename std::vector> sel; + picking_internal_face(m,position,A,B,sel); + + selected.clear(); + for (auto fs: sel) + selected.push_back(std::get<0>(fs)); + + return !selected.empty(); +} + + +template +bool picking_vertex(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector& selected) +{ + using Vertex = typename MAP::Vertex; + using Face = typename MAP::Face; + using Scalar = typename VEC3::Scalar; + + typename std::vector> sel; + picking_internal_face(m,position,A,B,sel); + + DartMarker dm(m); + selected.clear(); + for (auto fs: sel) + { + float min_d2 = std::numeric_limits::max(); + Vertex closest_vertex; + + Face f = std::get<0>(fs); + const VEC3& I = std::get<1>(fs); + + m.foreach_incident_vertex( f, [&] (Vertex v) + { + Scalar d2 = (position[v] - I).squaredNorm(); + if (d2 < min_d2) + { + min_d2 = d2; + closest_vertex = v; + } + }); + + if (!dm.is_marked(closest_vertex.dart)) + { + dm.mark_orbit(closest_vertex); + selected.push_back(closest_vertex); + } + } + + return !selected.empty(); } +template +bool picking_edge(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector& selected) +{ + using Vertex = typename MAP::Vertex; + using Edge = typename MAP::Edge; + using Face = typename MAP::Face; + using Scalar = typename VEC3::Scalar; + + typename std::vector> sel; + picking_internal_face(m,position,A,B,sel); + + DartMarker dm(m); + selected.clear(); + for (auto fs: sel) + { + float min_d2 = std::numeric_limits::max(); + Edge closest_edge; + + Face f = std::get<0>(fs); + const VEC3& I = std::get<1>(fs); + + m.foreach_incident_edge( f, [&] (Edge e) + { + const VEC3& p_e1 = position[Vertex(e.dart)]; + const VEC3& p_e2 = position[Vertex(m.phi1(e.dart))]; + Scalar d2 = squared_distance_line_point(p_e1,p_e2,I); + if (d2 < min_d2) + { + min_d2 = d2; + closest_edge = e; + } + }); + if (!dm.is_marked(closest_edge.dart)) + { + dm.mark_orbit(closest_edge); + selected.push_back(closest_edge); + } + } + + return !selected.empty(); +} + +template +bool picking_volume(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector& selected) +{ + using Vertex = typename MAP::Vertex; + using Edge = typename MAP::Edge; + using Face = typename MAP::Face; + using Volume = typename MAP::Volume; + using Scalar = typename VEC3::Scalar; + + typename std::vector> sel; + picking_internal_face(m,position,A,B,sel); + + selected.clear(); + DartMarker dm(m); + for (auto fs: sel) + { + Face f = std::get<0>(fs); + Volume vo = Volume(f.dart); + if (!dm.is_marked(vo.dart)) + { + dm.mark_orbit(vo); + selected.push_back(vo); + } + } + return !selected.empty(); +} + + + + } // namespace geometry } // namespace cgogn diff --git a/cgogn/geometry/functions/intersection.h b/cgogn/geometry/functions/intersection.h index e5678cf6..818815ec 100644 --- a/cgogn/geometry/functions/intersection.h +++ b/cgogn/geometry/functions/intersection.h @@ -31,16 +31,8 @@ namespace geometry { -enum Intersection -{ - NO_INTERSECTION = 0, - VERTEX_INTERSECTION = 1, - EDGE_INTERSECTION = 2, - FACE_INTERSECTION = 3 -}; - template -Intersection intersection_ray_triangle(const VEC3_T& P, const VEC3_T& Dir, const VEC3_T& Ta, const VEC3_T& Tb, const VEC3_T& Tc, VEC3_T* inter=nullptr) +bool intersection_ray_triangle(const VEC3_T& P, const VEC3_T& Dir, const VEC3_T& Ta, const VEC3_T& Tb, const VEC3_T& Tc, VEC3_T* inter=nullptr) { using Scalar = typename VEC3_T::Scalar; @@ -77,7 +69,8 @@ Intersection intersection_ray_triangle(const VEC3_T& P, const VEC3_T& Dir, const else ++nz ; - if ((np != 0) && (nn != 0)) return NO_INTERSECTION ; + if ((np != 0) && (nn != 0)) + return false ; if (inter) { @@ -88,7 +81,8 @@ Intersection intersection_ray_triangle(const VEC3_T& P, const VEC3_T& Dir, const *inter = Ta * alpha + Tb * beta + Tc * gamma ; } - return Intersection(FACE_INTERSECTION - nz) ; + return true ; + } diff --git a/cgogn/geometry/tests/functions/intersection_test.cpp b/cgogn/geometry/tests/functions/intersection_test.cpp index 9f2d3457..e8a14d15 100644 --- a/cgogn/geometry/tests/functions/intersection_test.cpp +++ b/cgogn/geometry/tests/functions/intersection_test.cpp @@ -45,9 +45,9 @@ TYPED_TEST_CASE(Intesection_TEST, VecTypes ); TYPED_TEST(Intesection_TEST, IntersectionLineTriangle) { using Scalar = typename cgogn::geometry::vector_traits::Scalar; - TypeParam p0(Scalar(1), Scalar(1), Scalar(6.1)); - TypeParam p1(Scalar(5), Scalar(1), Scalar(6.3)); - TypeParam p2(Scalar(3), Scalar(5), Scalar(6.2)); + TypeParam p0(Scalar(1), Scalar(1), Scalar(96.1)); + TypeParam p1(Scalar(5), Scalar(1), Scalar(92.3)); + TypeParam p2(Scalar(3), Scalar(5), Scalar(94.2)); TypeParam A0(Scalar(3), Scalar(3), Scalar(0)); TypeParam D0(Scalar(0.001), Scalar(0.001), Scalar(1.0)); @@ -57,11 +57,9 @@ TYPED_TEST(Intesection_TEST, IntersectionLineTriangle) TypeParam A2(Scalar(5), Scalar(1), Scalar(0)); TypeParam A3(Scalar(9), Scalar(5), Scalar(0)); - EXPECT_TRUE(cgogn::geometry::intersection_ray_triangle(A0,D0,p0,p1,p2) == cgogn::geometry::FACE_INTERSECTION); - EXPECT_TRUE(cgogn::geometry::intersection_ray_triangle(A1,D1,p0,p1,p2) == cgogn::geometry::EDGE_INTERSECTION); - EXPECT_TRUE(cgogn::geometry::intersection_ray_triangle(A2,D1,p0,p1,p2) == cgogn::geometry::VERTEX_INTERSECTION); - EXPECT_TRUE(cgogn::geometry::intersection_ray_triangle(A3,D0,p0,p1,p2) == cgogn::geometry::NO_INTERSECTION); + EXPECT_TRUE(cgogn::geometry::intersection_ray_triangle(A0,D0,p0,p1,p2)); + EXPECT_TRUE(cgogn::geometry::intersection_ray_triangle(A1,D1,p0,p1,p2)); + EXPECT_TRUE(cgogn::geometry::intersection_ray_triangle(A2,D1,p0,p1,p2)); + EXPECT_FALSE(cgogn::geometry::intersection_ray_triangle(A3,D0,p0,p1,p2)); - -// EXPECT_DOUBLE_EQ(cgogn::geometry::intersection_ray_triangle(p0,p1,p2), Scalar(2)); } diff --git a/cgogn/rendering/examples/picking_viewer.cpp b/cgogn/rendering/examples/picking_viewer.cpp index 3a61d4c0..e9bc3fa8 100644 --- a/cgogn/rendering/examples/picking_viewer.cpp +++ b/cgogn/rendering/examples/picking_viewer.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -36,15 +37,15 @@ #include #include #include - +#include #include #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) using Map2 = cgogn::CMap2; -using Vec3 = Eigen::Vector3d; -//using Vec3 = cgogn::geometry::Vec_T>; +//using Vec3 = Eigen::Vector3d; +using Vec3 = cgogn::geometry::Vec_T>; template using VertexAttributeHandler = Map2::VertexAttributeHandler; @@ -60,7 +61,7 @@ class Viewer : public QOGLViewer virtual void draw(); virtual void init(); virtual void mousePressEvent(QMouseEvent *e); - virtual void resizeGL(int w, int h); + virtual void keyPressEvent(QKeyEvent *); void import(const std::string& surfaceMesh); @@ -69,6 +70,9 @@ class Viewer : public QOGLViewer private: + void rayClick(QMouseEvent* event, QVector3D& P, QVector3D& Q); + + QRect viewport_; QMatrix4x4 proj_; QMatrix4x4 view_; @@ -84,6 +88,9 @@ class Viewer : public QOGLViewer cgogn::rendering::ShaderFlat* shader2_; + cgogn::rendering::Drawer* drawer_; + + int cell_picking; }; @@ -100,7 +107,7 @@ void Viewer::import(const std::string& surfaceMesh) cgogn::geometry::compute_bounding_box(vertex_position_, bb_); - setSceneRadius(bb_.diag_size()); + setSceneRadius(bb_.diag_size()/2.0); Vec3 center = bb_.center(); setSceneCenter(qoglviewer::Vec(center[0], center[1], center[2])); showEntireScene(); @@ -119,13 +126,13 @@ Viewer::Viewer() : bb_(), render_(nullptr), vbo_pos_(nullptr), - shader2_(nullptr) + shader2_(nullptr), + drawer_(nullptr), + cell_picking(0) {} void Viewer::draw() { -// QMatrix4x4 proj; -// QMatrix4x4 view; camera()->getProjectionMatrix(proj_); camera()->getModelViewMatrix(view_); @@ -138,13 +145,18 @@ void Viewer::draw() render_->draw(cgogn::rendering::TRIANGLES); shader2_->release_vao(0); shader2_->release(); + + glDisable(GL_POLYGON_OFFSET_FILL); + + drawer_->call_list(proj_,view_); + } void Viewer::init() { glClearColor(0.1f,0.1f,0.3f,0.0f); - vbo_pos_ = new cgogn::rendering::VBO; + vbo_pos_ = new cgogn::rendering::VBO(3); cgogn::rendering::update_vbo(vertex_position_, *vbo_pos_); render_ = new cgogn::rendering::MapRender(); @@ -159,46 +171,151 @@ void Viewer::init() shader2_->set_back_color(QColor(0,0,200)); shader2_->set_ambiant_color(QColor(5,5,5)); shader2_->release(); -} -void Viewer::mousePressEvent(QMouseEvent* event) -{ + drawer_ = new cgogn::rendering::Drawer(this); +} -// camera()->getProjectionMatrix(proj_); -// camera()->getModelViewMatrix(view_); +void Viewer::rayClick(QMouseEvent* event, QVector3D& P, QVector3D& Q) +{ + int vp[4]; + glGetIntegerv(GL_VIEWPORT, vp); + QRect viewport = QRect(vp[0],vp[1],vp[2],vp[3]); unsigned int x = event->x()*devicePixelRatio(); - unsigned int y = this->height() - event->y()*devicePixelRatio(); - QVector3D wp(x,y,0); - QVector3D wq(x,y,0.99); - QVector3D P = wp.unproject(view_,proj_,viewport_); - QVector3D Q = wq.unproject(view_,proj_,viewport_); - - Vec3 A(P[0],P[1],P[2]); - Vec3 B(Q[0],Q[1],Q[2]); + unsigned int y = (this->height()-event->y())*devicePixelRatio(); + QVector3D wp(x,y,0.01); + P = wp.unproject(view_,proj_,viewport); + QVector3D wq(x,y,0.99); + Q = wq.unproject(view_,proj_,viewport); +} -// std::cout< selected; - cgogn::geometry::picking_face(map_,vertex_position_,A,B,selected); +void Viewer::keyPressEvent(QKeyEvent *ev) +{ + switch (ev->key()) + { + case Qt::Key_0: + cell_picking = 0; + break; + case Qt::Key_1: + cell_picking = 1; + break; + case Qt::Key_2: + cell_picking = 2; + break; + case Qt::Key_3: + cell_picking = 3; + break; + } + QOGLViewer::keyPressEvent(ev); +} - std::cout << selected.size()<< std::endl; +void Viewer::mousePressEvent(QMouseEvent* event) +{ + if (event->modifiers() & Qt::ShiftModifier) + { + QVector3D P; + QVector3D Q; + rayClick(event,P,Q); + + Vec3 A(P[0],P[1],P[2]); + Vec3 B(Q[0],Q[1],Q[2]); + + drawer_->new_list(); + switch(cell_picking) + { + case 0: + { + std::vector selected; + cgogn::geometry::picking_vertex(map_,vertex_position_,A,B,selected); + std::cout<< "Selected vertices: "<< selected.size()<point_size_aa(4.0); + drawer_->begin(GL_POINTS); + // closest point in red + drawer_->color3f(1.0,0.0,0.0); + drawer_->vertex3fv(vertex_position_[selected[0]]); + // others in yellow + drawer_->color3f(1.0,1.0,0.0); + for(unsigned int i=1u;ivertex3fv(vertex_position_[selected[i]]); + drawer_->end(); + } + } + break; + case 1: + { + std::vector selected; + cgogn::geometry::picking_edge(map_,vertex_position_,A,B,selected); + std::cout<< "Selected edges: "<< selected.size()<line_width(2.0); + drawer_->begin(GL_LINES); + // closest face in red + drawer_->color3f(1.0,0.0,0.0); + cgogn::rendering::add_edge_to_drawer(map_,selected[0],vertex_position_,drawer_); + // others in yellow + drawer_->color3f(1.0,1.0,0.0); + for(unsigned int i=1u;i(map_,selected[i],vertex_position_,drawer_); + drawer_->end(); + } + } + break; + case 2: + { + std::vector selected; + cgogn::geometry::picking_face(map_,vertex_position_,A,B,selected); + std::cout<< "Selected faces: "<< selected.size()<line_width(2.0); + drawer_->begin(GL_LINES); + // closest face in red + drawer_->color3f(1.0,0.0,0.0); + cgogn::rendering::add_face_to_drawer(map_,selected[0],vertex_position_,drawer_); + // others in yellow + drawer_->color3f(1.0,1.0,0.0); + for(unsigned int i=1u;i(map_,selected[i],vertex_position_,drawer_); + drawer_->end(); + } + } + break; + case 3: + { + std::vector selected; + cgogn::geometry::picking_volume(map_,vertex_position_,A,B,selected); + std::cout<< "Selected volumes: "<< selected.size()<line_width(2.0); + drawer_->begin(GL_LINES); + // closest face in red + drawer_->color3f(1.0,0.0,0.0); + cgogn::rendering::add_volume_to_drawer(map_,selected[0],vertex_position_,drawer_); + // others in yellow + drawer_->color3f(1.0,1.0,0.0); + for(unsigned int i=1u;i(map_,selected[i],vertex_position_,drawer_); + drawer_->end(); + } + } + break; + } + drawer_->end_list(); + } QOGLViewer::mousePressEvent(event); } -void Viewer::resizeGL(int w, int h) -{ - int vp[4]; - glGetIntegerv(GL_VIEWPORT, vp); - viewport_= QRect(vp[0],vp[1],vp[2],vp[3]); - std::cout << "viewport"<< std::endl; -} int main(int argc, char** argv) { @@ -220,6 +337,7 @@ int main(int argc, char** argv) viewer.setWindowTitle("simpleViewer"); viewer.import(surfaceMesh); viewer.show(); + viewer.resize(800,600); // Run main loop. return application.exec(); diff --git a/cgogn/rendering/map_render.h b/cgogn/rendering/map_render.h index eb38c400..f7eb40b4 100644 --- a/cgogn/rendering/map_render.h +++ b/cgogn/rendering/map_render.h @@ -302,6 +302,42 @@ void create_drawer_topo2(MAP& m, const typename MAP::template VertexAttributeHan } +template +void add_edge_to_drawer(MAP& m, typename MAP::Edge e, const typename MAP::template VertexAttributeHandler& position, Drawer* dr) +{ + using Vertex = typename MAP::Vertex; + dr->vertex3fv(position[Vertex(e.dart)]); + dr->vertex3fv(position[Vertex(m.phi1(e.dart))]); +} + + +template +void add_face_to_drawer(MAP& m, typename MAP::Face f, const typename MAP::template VertexAttributeHandler& position, Drawer* dr) +{ + using Vertex = typename MAP::Vertex; + using Edge = typename MAP::Edge; + m.foreach_incident_edge(f, [&] (Edge e) + { + dr->vertex3fv(position[Vertex(e.dart)]); + dr->vertex3fv(position[Vertex(m.phi1(e.dart))]); + }); +} + +template +void add_volume_to_drawer(MAP& m, typename MAP::Volume vo, const typename MAP::template VertexAttributeHandler& position, Drawer* dr) +{ + using Vertex = typename MAP::Vertex; + using Edge = typename MAP::Edge; + m.foreach_incident_edge(vo, [&] (Edge e) + { + dr->vertex3fv(position[Vertex(e.dart)]); + dr->vertex3fv(position[Vertex(m.phi1(e.dart))]); + }); + +} + + + } // namespace rendering From a236601354a28cf50b0ab822ba140293616f64aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 9 Mar 2016 16:08:49 +0100 Subject: [PATCH 299/402] close_hole_topo and close_map : cmap3 --> cmap3_builder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/cmap3.h | 142 ------------------------------ cgogn/core/cmap/cmap3_builder.h | 149 +++++++++++++++++++++++++++++++- 2 files changed, 148 insertions(+), 143 deletions(-) diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 648a406d..d369016a 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -296,148 +296,6 @@ class CMap3_T : public CMap2_T return dres; } - inline void close_hole_topo(Dart d) - { - cgogn_message_assert(phi3(d) == d, "CMap3: close hole called on a dart that is not a phi3 fix point"); - - DartMarkerStore dmarker(*this); - DartMarkerStore boundary_marker(*this); - - std::vector visitedFaces; // Faces that are traversed - visitedFaces.reserve(1024); - - visitedFaces.push_back(d); // Start with the face of d - dmarker.mark_orbit(Face2(d)); - - unsigned int count = 0u; - - // For every face added to the list - for(unsigned int i = 0u; i < visitedFaces.size(); ++i) - { - Dart it = visitedFaces[i]; - Dart f = it; - - const Dart b = this->Inherit::Inherit::add_face_topo(this->degree(Face(f))); - boundary_marker.mark_orbit(Face2(b)); - ++count; - - Dart bit = b; - do - { - Dart e = this->phi3(this->phi2(f));; - bool found = false; - do - { - if (phi3(e) == e) - { - found = true; - if (!dmarker.is_marked(e)) - { - visitedFaces.push_back(e); - dmarker.mark_orbit(Face2(e)); - } - } - else - { - if (boundary_marker.is_marked(e)) - { - found = true; - this->phi2_sew(e, bit); - } - else - e = this->phi3(this->phi2(e)); - } - } while(!found); - - phi3_sew(f, bit); - bit = this->phi_1(bit); - f = this->phi1(f); - } while(f != it); - } - } - - /** - * @brief close_map : /!\ DO NOT USE /!\ Close the map removing topological holes (only for import/creation) - * Add volumes to the map that close every existing hole. - * @return the number of closed holes - */ - inline unsigned int close_map() - { - CGOGN_CHECK_CONCRETE_TYPE; - // Search the map for topological holes (fix points of phi3) - unsigned int nb = 0u; - for (Dart d: (*this)) - { - if (phi3(d) == d) - { - ++nb; - close_hole_topo(d); - const Volume new_volume = phi3(d); - - if (this->template is_embedded()) - { - foreach_dart_of_orbit(new_volume, [this] (Dart d) - { - this->new_orbit_embedding(CDart(d)); - }); - } - - if (this->template is_embedded()) - { - Inherit::foreach_incident_vertex(new_volume, [this] (Vertex2 v) - { - this->new_orbit_embedding(v); - }); - } - - if (this->template is_embedded()) - { - Inherit::foreach_incident_edge(new_volume, [this] (Edge2 e) - { - this->new_orbit_embedding(e); - }); - } - - if (this->template is_embedded()) - { - Inherit::foreach_incident_face(new_volume, [this] (Face2 f) - { - this->new_orbit_embedding(f); - }); - } - - if (this->template is_embedded()) - { - foreach_dart_of_orbit(new_volume, [this] (Dart wd) - { - this->template copy_embedding(wd, this->phi1(phi3(wd))); - }); - } - - if (this->template is_embedded()) - { - foreach_dart_of_orbit(new_volume, [this] (Dart wd) - { - this->template copy_embedding(wd, phi3(wd)); - }); - } - - if (this->template is_embedded()) - { - foreach_dart_of_orbit(new_volume, [this] (Dart wd) - { - this->template copy_embedding(wd, phi3(wd)); - }); - } - - if (this->template is_embedded()) - { - this->new_orbit_embedding(new_volume); - } - } - } - return nb; - } public: diff --git a/cgogn/core/cmap/cmap3_builder.h b/cgogn/core/cmap/cmap3_builder.h index a0210b55..17f51792 100644 --- a/cgogn/core/cmap/cmap3_builder.h +++ b/cgogn/core/cmap/cmap3_builder.h @@ -36,11 +36,20 @@ class CMap3Builder_T using Self = CMap3Builder_T; using CMap3 = cgogn::CMap3; + using CDart = typename CMap3::CDart; using Vertex = typename CMap3::Vertex; + using Vertex2 = typename CMap3::Vertex2; + using Edge = typename CMap3::Edge; + using Edge2 = typename CMap3::Edge2; + using Face = typename CMap3::Face; + using Face2 = typename CMap3::Face2; + using Volume = typename CMap3::Volume; + using DartMarkerStore = typename CMap3::DartMarkerStore; template using ChunkArrayContainer = typename CMap3::template ChunkArrayContainer; + inline CMap3Builder_T(CMap3& map) : map_(map) {} CMap3Builder_T(const Self&) = delete; @@ -106,9 +115,147 @@ class CMap3Builder_T return map_.add_pyramid_topo(nb_edges); } + + inline void close_hole_topo(Dart d) + { + cgogn_message_assert(map_.phi3(d) == d, "CMap3: close hole called on a dart that is not a phi3 fix point"); + + DartMarkerStore dmarker(map_); + DartMarkerStore boundary_marker(map_); + + std::vector visitedFaces; // Faces that are traversed + visitedFaces.reserve(1024); + + visitedFaces.push_back(d); // Start with the face of d + dmarker.mark_orbit(Face2(d)); + + unsigned int count = 0u; + + // For every face added to the list + for(unsigned int i = 0u; i < visitedFaces.size(); ++i) + { + Dart it = visitedFaces[i]; + Dart f = it; + + const Dart b = map_.CMap3::Inherit::Inherit::add_face_topo(map_.degree(Face(f))); + boundary_marker.mark_orbit(Face2(b)); + ++count; + + Dart bit = b; + do + { + Dart e = map_.phi3(map_.phi2(f));; + bool found = false; + do + { + if (map_.phi3(e) == e) + { + found = true; + if (!dmarker.is_marked(e)) + { + visitedFaces.push_back(e); + dmarker.mark_orbit(Face2(e)); + } + } + else + { + if (boundary_marker.is_marked(e)) + { + found = true; + this->phi2_sew(e, bit); + } + else + e = map_.phi3(map_.phi2(e)); + } + } while(!found); + + phi3_sew(f, bit); + bit = map_.phi_1(bit); + f = map_.phi1(f); + } while(f != it); + } + } + + /** + * @brief close_map : /!\ DO NOT USE /!\ Close the map removing topological holes (only for import/creation) + * Add volumes to the map that close every existing hole. + * @return the number of closed holes + */ inline unsigned int close_map() { - return map_.close_map(); + // Search the map for topological holes (fix points of phi3) + unsigned int nb = 0u; + for (Dart d: map_) + { + if (map_.phi3(d) == d) + { + ++nb; + close_hole_topo(d); + const Volume new_volume = map_.phi3(d); + + if (map_.template is_embedded()) + { + map_.foreach_dart_of_orbit(new_volume, [this] (Dart d) + { + map_.new_orbit_embedding(CDart(d)); + }); + } + + if (map_.template is_embedded()) + { + map_.CMap3::Inherit::foreach_incident_vertex(new_volume, [this] (Vertex2 v) + { + map_.new_orbit_embedding(v); + }); + } + + if (map_.template is_embedded()) + { + map_.CMap3::Inherit::foreach_incident_edge(new_volume, [this] (Edge2 e) + { + map_.new_orbit_embedding(e); + }); + } + + if (map_.template is_embedded()) + { + map_.CMap3::Inherit::foreach_incident_face(new_volume, [this] (Face2 f) + { + map_.new_orbit_embedding(f); + }); + } + + if (map_.template is_embedded()) + { + map_.foreach_dart_of_orbit(new_volume, [this] (Dart wd) + { + map_.template copy_embedding(wd, map_.phi1(map_.phi3(wd))); + }); + } + + if (map_.template is_embedded()) + { + map_.foreach_dart_of_orbit(new_volume, [this] (Dart wd) + { + map_.template copy_embedding(wd, map_.phi3(wd)); + }); + } + + if (map_.template is_embedded()) + { + map_.foreach_dart_of_orbit(new_volume, [this] (Dart wd) + { + map_.template copy_embedding(wd, map_.phi3(wd)); + }); + } + + if (map_.template is_embedded()) + { + map_.new_orbit_embedding(new_volume); + } + } + } + return nb; } private: From 97de8e8c69021bc9234b39295db1c8c0b3d39a3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 9 Mar 2016 18:05:48 +0100 Subject: [PATCH 300/402] added support of vtp files and fixed a compilation issue. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/io_utils.cpp | 6 +- cgogn/io/io_utils.h | 49 ++------- cgogn/io/map_import.h | 3 +- cgogn/io/mesh_io_gen.cpp | 2 +- cgogn/io/vtk_io.h | 227 ++++++++++++++++++++++++++++----------- 5 files changed, 177 insertions(+), 110 deletions(-) diff --git a/cgogn/io/io_utils.cpp b/cgogn/io/io_utils.cpp index ed04bab7..2e3eae65 100644 --- a/cgogn/io/io_utils.cpp +++ b/cgogn/io/io_utils.cpp @@ -54,14 +54,14 @@ CGOGN_IO_API std::vector zlib_decompress(const char* input, DataT { word_size = 8u; // we read the first 3 uint64 - header_data = base64_decode(input, 0, 24); + header_data = base64_decode(input, 0, 32); nb_blocks = *reinterpret_cast(&header_data[0]); uncompressed_block_size = *reinterpret_cast(&header_data[8]); last_block_size = *reinterpret_cast(&header_data[16]); compressed_size.resize(nb_blocks); } else { - header_data = base64_decode(input, 0, 12); + header_data = base64_decode(input, 0, 24); nb_blocks = *reinterpret_cast(&header_data[0]); uncompressed_block_size = *reinterpret_cast(&header_data[4]); last_block_size = *reinterpret_cast(&header_data[8]); @@ -217,6 +217,8 @@ CGOGN_IO_API FileType get_file_type(const std::string& filename) return FileType::FileType_VTK_LEGACY; if (extension == "vtu") return FileType::FileType_VTU; + if (extension == "vtp") + return FileType::FileType_VTP; return FileType::FileType_UNKNOWN; } diff --git a/cgogn/io/io_utils.h b/cgogn/io/io_utils.h index 46061cb1..ed302d92 100644 --- a/cgogn/io/io_utils.h +++ b/cgogn/io/io_utils.h @@ -45,7 +45,8 @@ enum FileType FileType_OBJ, FileType_PLY, FileType_VTK_LEGACY, - FileType_VTU + FileType_VTU, + FileType_VTP }; enum DataType @@ -165,31 +166,8 @@ class CGOGN_IO_API CharArrayBuffer : public std::streambuf CharArrayBuffer(const Self&) = delete; Self& operator=(const Self&) = delete; - - inline CharArrayBuffer(Self&& other) : Inherit(std::forward(other)) - { - begin_ = other.begin_; - end_ = other.end_; - current_ = other.current_; - other.begin_ = nullptr; - other.end_ = nullptr; - other.current_ = nullptr; - } - - inline Self& operator=(Self&& other) - { - Inherit::operator =(std::forward(other)); - if (&other != this) - { - begin_ = other.begin_; - end_ = other.end_; - current_ = other.current_; - other.begin_ = nullptr; - other.end_ = nullptr; - other.current_ = nullptr; - } - return *this; - } + CharArrayBuffer(Self&&) = delete; + Self& operator=(Self&&) = delete; virtual ~CharArrayBuffer(); private: @@ -287,23 +265,8 @@ class CGOGN_IO_API IMemoryStream : public std::istream IMemoryStream(const Self&) = delete; Self& operator=(const Self&) = delete; - - inline IMemoryStream(Self&& other) : Inherit(std::forward(other)) - { - this->buffer_ = std::move(other.buffer_); - this->init(&buffer_); - } - - inline Self& operator=(Self&& other) - { - Inherit::operator =(std::forward(other)); - if (&other != this) - { - this->buffer_ = std::move(other.buffer_); - this->init(&buffer_); - } - return *this; - } + IMemoryStream(Self&&) = delete; + Self& operator=(Self&&) = delete; virtual ~IMemoryStream() override; private: diff --git a/cgogn/io/map_import.h b/cgogn/io/map_import.h index 96782996..52711c32 100644 --- a/cgogn/io/map_import.h +++ b/cgogn/io/map_import.h @@ -82,7 +82,8 @@ inline std::unique_ptr> newSurfaceImport(const std::st { case FileType::FileType_OFF : return make_unique>(); case FileType::FileType_VTK_LEGACY: - case FileType::FileType_VTU: return make_unique>(); + case FileType::FileType_VTU: + case FileType::FileType_VTP: return make_unique>(); case FileType::FileType_OBJ: return make_unique>(); case FileType::FileType_PLY: return make_unique>(); default: diff --git a/cgogn/io/mesh_io_gen.cpp b/cgogn/io/mesh_io_gen.cpp index fcc709bb..42301d8b 100644 --- a/cgogn/io/mesh_io_gen.cpp +++ b/cgogn/io/mesh_io_gen.cpp @@ -46,7 +46,7 @@ bool MeshImportGen::import_file(const std::string& filename) std::ifstream fp(filename.c_str(), std::ios::in); if (!fp.good()) { - std::cerr << "Unable to open file \"" << filename << "\"" << std::endl; + std::cerr << "MeshImportGen::import_file : Unable to open file \"" << filename << "\"" << std::endl; return false; } } diff --git a/cgogn/io/vtk_io.h b/cgogn/io/vtk_io.h index 03289afb..3a08683a 100644 --- a/cgogn/io/vtk_io.h +++ b/cgogn/io/vtk_io.h @@ -344,6 +344,8 @@ protected : const bool compressed = (root_node->Attribute("compressor") && (std::string(root_node->Attribute("compressor")) == "vtkZLibDataCompressor")); XMLElement* grid_node = root_node->FirstChildElement("UnstructuredGrid"); + if (grid_node == nullptr) + grid_node = root_node->FirstChildElement("PolyData"); cgogn_assert(grid_node != nullptr); XMLElement* piece_node = grid_node->FirstChildElement("Piece"); cgogn_assert(piece_node != nullptr); @@ -353,12 +355,19 @@ protected : piece_node->QueryUnsignedAttribute("NumberOfPoints",&nb_vertices); piece_node->QueryUnsignedAttribute("NumberOfCells",&nb_cells); + if (nb_cells== 0u) + piece_node->QueryUnsignedAttribute("NumberOfPolys",&nb_cells); if (nb_vertices == 0u|| nb_cells == 0u) return false; XMLElement* points_node = piece_node->FirstChildElement("Points"); cgogn_assert(points_node != nullptr); - XMLElement*const position_data_array_node = points_node->FirstChildElement("DataArray"); + XMLElement* position_data_array_node = points_node->FirstChildElement("DataArray"); + for (XMLElement* elem = position_data_array_node; elem != nullptr ; elem = elem->NextSiblingElement("DataArray")) + { + if (elem->Attribute("Name") && to_lower(std::string(elem->Attribute("Name"))) == "points") + position_data_array_node = elem; + } cgogn_assert(position_data_array_node != nullptr); XMLElement* point_data_node = piece_node->FirstChildElement("PointData"); XMLElement* point_data_array_node = point_data_node ? point_data_node->FirstChildElement("DataArray") : nullptr; @@ -387,22 +396,22 @@ protected : if (binary) binary_data = this->read_binary_xml_data(ascii_data,compressed, get_data_type(header_type)); - IMemoryStream mem_stream; + std::unique_ptr mem_stream; if (binary) - mem_stream = IMemoryStream(reinterpret_cast(&binary_data[0]), binary_data.size()); + mem_stream = make_unique(reinterpret_cast(&binary_data[0]), binary_data.size()); else - mem_stream = IMemoryStream(ascii_data); + mem_stream = make_unique(ascii_data); if (vertex_data == position_data_array_node) { cgogn_assert(nb_comp == 3); auto pos = DataInputGen::template newDataIO(type, nb_comp); - pos->read_n(mem_stream, nb_vertices,binary,!little_endian); + pos->read_n(*mem_stream, nb_vertices,binary,!little_endian); this->add_vertex_attribute(*pos,"position"); this->positions_ = *dynamic_cast_unique_ptr>(pos->simplify()); } else { std::unique_ptr vertex_att = DataInputGen::template newDataIO(type, nb_comp); - vertex_att->read_n(mem_stream, nb_vertices,binary,!little_endian); + vertex_att->read_n(*mem_stream, nb_vertices,binary,!little_endian); this->add_vertex_attribute(*vertex_att, data_name); } } @@ -410,81 +419,147 @@ protected : XMLElement* const cell_node = piece_node->FirstChildElement("Cells"); - cgogn_assert(cell_node != nullptr); - XMLElement* cells_array_node = cell_node->FirstChildElement("DataArray"); - cgogn_assert(cells_array_node != nullptr); - std::vector cell_nodes; - while (cells_array_node) + if (cell_node != nullptr) { - cell_nodes.push_back(cells_array_node); - cells_array_node = cells_array_node->NextSiblingElement("DataArray"); - } + XMLElement* cells_array_node = cell_node->FirstChildElement("DataArray"); + cgogn_assert(cells_array_node != nullptr); + std::vector cell_nodes; + while (cells_array_node) + { + cell_nodes.push_back(cells_array_node); + cells_array_node = cells_array_node->NextSiblingElement("DataArray"); + } - XMLElement* const cell_data_node = piece_node->FirstChildElement("CellData"); - cells_array_node = cell_data_node ? cell_data_node->FirstChildElement("DataArray") : nullptr; - while (cells_array_node) - { - cell_nodes.push_back(cells_array_node); - cells_array_node = cells_array_node->NextSiblingElement("DataArray"); - } + XMLElement* const cell_data_node = piece_node->FirstChildElement("CellData"); + cells_array_node = cell_data_node ? cell_data_node->FirstChildElement("DataArray") : nullptr; + while (cells_array_node) + { + cell_nodes.push_back(cells_array_node); + cells_array_node = cells_array_node->NextSiblingElement("DataArray"); + } - for (XMLElement*& cell_data : cell_nodes) - { - if (to_lower(std::string(cell_data->Attribute("Name"))) == "connectivity" && (cell_data != cell_nodes.back())) + for (XMLElement*& cell_data : cell_nodes) { - std::swap(cell_data, cell_nodes.back()); + if (to_lower(std::string(cell_data->Attribute("Name"))) == "connectivity" && (cell_data != cell_nodes.back())) + { + std::swap(cell_data, cell_nodes.back()); + } + } + + for (XMLElement* cell_data : cell_nodes) + { + const std::string& data_name = to_lower(std::string(cell_data->Attribute("Name"))); + const bool binary = (to_lower(std::string(cell_data->Attribute("format", nullptr))) == "binary"); + unsigned int nb_comp = 1; + cell_data->QueryUnsignedAttribute("NumberOfComponents", &nb_comp); + std::string type = vtk_data_type_to_cgogn_name_of_type(std::string(cell_data->Attribute("type", nullptr))); + + if (data_name.empty()) + std::cerr << "import_VTU : Skipping a cell DataArray without \"Name\" attribute." << std::endl; + else { + const char* ascii_data = cell_data->GetText(); + std::vector binary_data; + if (binary) + binary_data = this->read_binary_xml_data(ascii_data,compressed, get_data_type(header_type)); + + std::unique_ptr mem_stream; + if (binary) + mem_stream = make_unique(reinterpret_cast(&binary_data[0]), binary_data.size()); + else + mem_stream = make_unique(ascii_data); + if (data_name == "connectivity") + { + const unsigned int last_offset = this->offsets_.get_vec()->back(); + auto cells = DataInputGen::template newDataIO(type); + cells->read_n(*mem_stream, last_offset,binary,!little_endian); + this->cells_ = *dynamic_cast_unique_ptr>(cells->simplify()); + } + else { + if (data_name == "offsets") + { + auto offsets = DataInputGen::template newDataIO(type); + offsets->read_n(*mem_stream, nb_cells,binary,!little_endian); + this->offsets_ = *dynamic_cast_unique_ptr>(offsets->simplify()); + } + else { + if (data_name == "types") + { + auto types = DataInputGen::template newDataIO(type); + types->read_n(*mem_stream, nb_cells,binary,!little_endian); + this->cell_types_ = *dynamic_cast_unique_ptr>(types->simplify()); + } + else { + std::cout << "Reading cell attribute \"" << data_name << "\" of type " << type << "." << std::endl; + auto cell_att = DataInputGen::template newDataIO(type, nb_comp); + cell_att->read_n(*mem_stream, nb_cells,binary,!little_endian); + this->add_cell_attribute(*cell_att, data_name); + } + } + } + } } } - for (XMLElement* cell_data : cell_nodes) + XMLElement* const poly_node = piece_node->FirstChildElement("Polys"); + if (poly_node) { - const std::string& data_name = to_lower(std::string(cell_data->Attribute("Name"))); - const bool binary = (to_lower(std::string(cell_data->Attribute("format", nullptr))) == "binary"); - unsigned int nb_comp = 1; - cell_data->QueryUnsignedAttribute("NumberOfComponents", &nb_comp); - std::string type = vtk_data_type_to_cgogn_name_of_type(std::string(cell_data->Attribute("type", nullptr))); - - if (data_name.empty()) - std::cerr << "import_VTU : Skipping a cell DataArray without \"Name\" attribute." << std::endl; - else { - const char* ascii_data = cell_data->GetText(); - std::vector binary_data; - if (binary) - binary_data = this->read_binary_xml_data(ascii_data,compressed, get_data_type(header_type)); + XMLElement* polys_array_node = poly_node->FirstChildElement("DataArray"); + cgogn_assert(polys_array_node != nullptr); + std::vector poly_nodes; + while (polys_array_node) + { + poly_nodes.push_back(polys_array_node); + polys_array_node = polys_array_node->NextSiblingElement("DataArray"); + } - IMemoryStream mem_stream; - if (binary) - mem_stream = IMemoryStream(reinterpret_cast(&binary_data[0]), binary_data.size()); - else - mem_stream = IMemoryStream(ascii_data); - if (data_name == "connectivity") + for (XMLElement*& poly_data_array : poly_nodes) + { + if (poly_data_array->Attribute("Name") && to_lower(std::string(poly_data_array->Attribute("Name"))) == "connectivity" && (poly_data_array != poly_nodes.back())) { - const unsigned int last_offset = this->offsets_.get_vec()->back(); - auto cells = DataInputGen::template newDataIO(type); - cells->read_n(mem_stream, last_offset,binary,!little_endian); - this->cells_ = *dynamic_cast_unique_ptr>(cells->simplify()); + std::swap(poly_data_array, poly_nodes.back()); } + } + + for (XMLElement* poly_data_array : poly_nodes) + { + const std::string& data_name = to_lower(std::string(poly_data_array->Attribute("Name"))); + const bool binary = (poly_data_array->Attribute("format") && to_lower(std::string(poly_data_array->Attribute("format", nullptr))) == "binary"); + unsigned int nb_comp = 1; + poly_data_array->QueryUnsignedAttribute("NumberOfComponents", &nb_comp); + std::string type; + if (poly_data_array->Attribute("type", nullptr)) + type = vtk_data_type_to_cgogn_name_of_type(std::string(poly_data_array->Attribute("type", nullptr))); + + if (data_name.empty()) + std::cerr << "import_VTU : Skipping a cell DataArray without \"Name\" attribute." << std::endl; else { - if (data_name == "offsets") + const char* ascii_data = poly_data_array->GetText(); + std::vector binary_data; + if (binary) + binary_data = this->read_binary_xml_data(ascii_data,compressed, get_data_type(header_type)); + + std::unique_ptr mem_stream; + if (binary) + mem_stream = make_unique(reinterpret_cast(&binary_data[0]), binary_data.size()); + else + mem_stream = make_unique(ascii_data); + if (data_name == "connectivity") { - auto offsets = DataInputGen::template newDataIO(type); - offsets->read_n(mem_stream, nb_cells,binary,!little_endian); - this->offsets_ = *dynamic_cast_unique_ptr>(offsets->simplify()); + const unsigned int last_offset = this->offsets_.get_vec()->back(); + auto cells = DataInputGen::template newDataIO(type); + cells->read_n(*mem_stream, last_offset,binary,!little_endian); + this->cells_ = *dynamic_cast_unique_ptr>(cells->simplify()); } else { - if (data_name == "types") + if (data_name == "offsets") { - auto types = DataInputGen::template newDataIO(type); - types->read_n(mem_stream, nb_cells,binary,!little_endian); - this->cell_types_ = *dynamic_cast_unique_ptr>(types->simplify()); - } - else { - std::cout << "Reading cell attribute \"" << data_name << "\" of type " << type << "." << std::endl; - auto cell_att = DataInputGen::template newDataIO(type, nb_comp); - cell_att->read_n(mem_stream, nb_cells,binary,!little_endian); - this->add_cell_attribute(*cell_att, data_name); + auto offsets = DataInputGen::template newDataIO(type); + offsets->read_n(*mem_stream, nb_cells,binary,!little_endian); + this->offsets_ = *dynamic_cast_unique_ptr>(offsets->simplify()); } + else + std::cout << "Ignoring cell attribute \"" << data_name << "\" of type " << type << "." << std::endl; } } } @@ -554,6 +629,30 @@ class VtkSurfaceImport : public VtkIO: return true; } + inline bool read_vtp_file(const std::string& filename) + { + if (!Inherit_Vtk::parse_xml_vtu(filename)) + return false; + this->fill_surface_import(); + + this->nb_vertices_ = this->positions_.size(); + this->nb_faces_ = this->offsets_.size(); + + auto cells_it = this->cells_.get_vec()->begin(); + unsigned int last_offset = 0u; + for(auto offset_it =this->offsets_.get_vec()->begin(), offset_end = this->offsets_.get_vec()->end() ; offset_it != offset_end; ++offset_it) + { + const unsigned int curr_offset = *offset_it; + const unsigned int nb_vertices = curr_offset - last_offset; + this->faces_nb_edges_.push_back(nb_vertices); + for (unsigned int i = 0u ; i < nb_vertices; ++i) + this->faces_vertex_indices_.push_back(*cells_it++); + last_offset = *offset_it; + } + + return true; + } + virtual void add_vertex_attribute(const DataInputGen& attribute_data, const std::string& attribute_name) override { attribute_data.to_chunk_array(attribute_data.add_attribute(this->vertex_attributes_, attribute_name)); @@ -575,6 +674,8 @@ class VtkSurfaceImport : public VtkIO: } case FileType::FileType_VTU: return this->read_xml_file(filename); + case FileType::FileType_VTP: + return this->read_vtp_file(filename); default: std::cerr << "VtkSurfaceImport does not handle the files of type \"" << get_extension(filename) << "\"." << std::endl; return false; From acb3203ea55b8bd521057d692b7121f4a9d25569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 9 Mar 2016 18:06:52 +0100 Subject: [PATCH 301/402] added a vtp example mesh. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- data/meshes/SaladBowl.vtp | 1685 +++++++++++++++++++++++++++++++++++++ 1 file changed, 1685 insertions(+) create mode 100644 data/meshes/SaladBowl.vtp diff --git a/data/meshes/SaladBowl.vtp b/data/meshes/SaladBowl.vtp new file mode 100644 index 00000000..e8aa1a48 --- /dev/null +++ b/data/meshes/SaladBowl.vtp @@ -0,0 +1,1685 @@ + + + + + + 9.9999999748e-07 0 -1 -0.31992700696 -0.0026030000299 -0.94743901491 + -0.46657600999 -0.0022120000795 -0.88447898626 -0.58159202337 -0.001575000002 -0.81347900629 + -0.6715850234 -0.0013719999697 -0.7409260273 -0.76173901558 -0.0015490000369 -0.64788198471 + -0.84907901287 -0.0012969999807 -0.52826398611 -0.91169202328 -0.00077699997928 -0.41087499261 + -0.95059800148 -0.000503999996 -0.31042599678 -0.96054798365 -0.094605997205 -0.26153001189 + -0.99689602852 -0.0010260000126 -0.078726001084 -0.75940597057 0.009105999954 0.65055298805 + -0.44186401367 -0.043519999832 0.89602601528 0.94002300501 -0.00035799999023 0.34110999107 + 0.91229200363 -0.00055499997688 0.40953999758 0.86407399178 -0.0010509999702 0.50336402655 + 0.78544402122 -0.0015360000543 0.61892998219 0.69887501001 -0.0012550000101 0.71524202824 + 0.62436699867 -0.0011709999526 0.78113001585 0.53038698435 -0.0019300000276 0.84775298834 + 0.40063598752 -0.0023300000466 0.91623401642 0.32841798663 0.032345999032 0.94397902489 + 9.9999999748e-07 0 -1 -0.31327199936 -0.064967997372 -0.94743901491 + -0.45717900991 -0.093194000423 -0.88447898626 -0.57010900974 -0.11500699818 -0.81347900629 + -0.65841299295 -0.13236500323 -0.7409260273 -0.74680000544 -0.15012699366 -0.64788198471 + -0.83251202106 -0.16692000628 -0.52826398611 -0.89402198792 -0.17862400413 -0.41087400913 + -0.93223398924 -0.18594700098 -0.31042599678 -1.9210959673 -0.18921199441 -0.52305901051 + -0.97754001617 -0.19549100101 -0.078726999462 -0.74659097195 -0.13922099769 0.65055298805 + -0.88372498751 -0.087039001286 1.7920529842 0.92203098536 0.18303799629 0.34110999107 + 0.89487099648 0.17743499577 0.40953999758 0.84767597914 0.16754199564 0.50336402655 + 0.77065199614 0.15172599256 0.61893099546 0.68569201231 0.13511200249 0.71524202824 + 0.61259901524 0.12065900117 0.78113001585 0.52057301998 0.10158000141 0.84775298834 + 0.3933930099 0.075874999166 0.91623401642 0.65683597326 0.064692996442 1.8879569769 + 9.9999999748e-07 0 -1 -0.294577986 -0.12483599782 -0.94743901491 + -0.43021300435 -0.18059399724 -0.88447898626 -0.5367180109 -0.22402000427 -0.81347900629 + -0.61993902922 -0.25827199221 -0.7409260273 -0.70316302776 -0.29293599725 -0.64788198471 + -0.78395098448 -0.3261269927 -0.52826297283 -0.84199601412 -0.34960699081 -0.41087400913 + -0.87804502249 -0.36424300075 -0.31042599678 -1.8472690582 -0.56036299467 -0.52306002378 + -0.92061901093 -0.38244399428 -0.078726001084 -0.70508497953 -0.28219899535 0.65055298805 + -0.8497620225 -0.25777301192 1.7920540571 0.86860501766 0.35940000415 0.34110999107 + 0.84306001663 0.34860700369 0.40953999758 0.79870200157 0.32969599962 0.50336301327 + 0.72624397278 0.29915699363 0.61892998219 0.64615702629 0.26628801227 0.71524202824 + 0.57728797197 0.23785300553 0.78113001585 0.49075201154 0.20118799806 0.84775298834 + 0.37103098631 0.15116399527 0.91623401642 0.63159400225 0.19159199297 1.8879569769 + 9.9999999748e-07 -0 -1 -0.26456299424 -0.1799069941 -0.94743901491 + -0.38671499491 -0.26105499268 -0.88447797298 -0.48270100355 -0.32442399859 -0.81347900629 + -0.55764102936 -0.37425398827 -0.7409260273 -0.63250297308 -0.42448699474 -0.64788198471 + -0.70526301861 -0.47280201316 -0.52826297283 -0.75761198997 -0.50715500116 -0.41087400913 + -0.79011297226 -0.52854299545 -0.31042599678 -1.7024519444 -0.90997999907 -0.52306002378 + -0.82831799984 -0.5546990037 -0.078726001084 -0.63648200035 -0.4143320024 0.65055298805 + -0.78314602375 -0.41860100627 1.7920529842 0.78179997206 0.52195101976 0.34110999107 + 0.75885099173 0.50638097525 0.40953999758 0.71903502941 0.47918000817 0.50336301327 + 0.65392702818 0.43509200215 0.61892998219 0.58179098368 0.38723000884 0.71524202824 + 0.519792974 0.34590598941 0.78113001585 0.44207298756 0.29306301475 0.84775298834 + 0.33441099524 0.22064399719 0.91623401642 0.58207899332 0.31112998724 1.8879569769 + 0 0 -1 -0.2243809998 -0.22806300223 -0.94743901491 + -0.32835501432 -0.33148300648 -0.88447797298 -0.41013398767 -0.41236099601 -0.81347900629 + -0.47391200066 -0.47585299611 -0.7409260273 -0.53753602505 -0.53972601891 -0.64788198471 + -0.59947299957 -0.60130697489 -0.52826297283 -0.64411401749 -0.64521199465 -0.41087400913 + -0.67181801796 -0.67252999544 -0.31042599678 -1.4922120571 -1.224627018 -0.52306002378 + -0.70418602228 -0.70563697815 -0.078726001084 -0.54342001677 -0.53054201603 0.65055298805 + -0.68643397093 -0.56334102154 1.7920540571 0.66495001316 0.66444402933 0.34110999107 + 0.64547997713 0.64469599724 0.40953999758 0.61173498631 0.61024999619 0.50336301327 + 0.5564789772 0.55430698395 0.61892998219 0.49506700039 0.49329200387 0.71524202824 + 0.44232299924 0.44066599011 0.78113001585 0.37640500069 0.37367600203 0.84775298834 + 0.28494000435 0.28164499998 0.91623401642 0.51019698381 0.41870799661 1.8879569769 + 0 0 -1 -0.17557699978 -0.26745599508 -0.94743901491 + -0.25737598538 -0.38917198777 -0.88447898626 -0.32180601358 -0.48445099592 -0.81347900629 + -0.37197199464 -0.55916500092 -0.7409260273 -0.42191201448 -0.63422298431 -0.64788198471 + -0.47064501047 -0.7067040205 -0.52826398611 -0.50586301088 -0.75847500563 -0.41087400913 + -0.52770501375 -0.7906730175 -0.31042599678 -1.224627018 -1.4922120571 -0.52306002378 + -0.55299198627 -0.82945901155 -0.078726999462 -0.42947500944 -0.62636399269 0.65055298805 + -0.56334102154 -0.68643301725 1.7920540571 0.52254700661 0.78140199184 0.34110999107 + 0.5073029995 0.75823497772 0.40953999758 0.48092699051 0.71786797047 0.50336402655 + 0.43764701486 0.65222001076 0.61892998219 0.38931798935 0.58039599657 0.71524202824 + 0.34785398841 0.51849102974 0.78113001585 0.29627200961 0.43992900848 0.84775298834 + 0.22451899946 0.33182200789 0.91623401642 0.41870900989 0.51019799709 1.8879569769 + 0 9.9999999748e-07 -1 -0.12002500147 -0.29657000303 -0.94743901491 + -0.17650699615 -0.43190601468 -0.88447898626 -0.22111099958 -0.5379229784 -0.81347900629 + -0.25573700666 -0.62098902464 -0.7409260273 -0.29007399082 -0.70434802771 -0.64788198471 + -0.32372999191 -0.78494399786 -0.52826398611 -0.34817200899 -0.8425899744 -0.41087499261 + -0.36331298947 -0.87843000889 -0.31042599678 -0.90997999907 -1.7024530172 -0.52306002378 + -0.38054698706 -0.9214040041 -0.078726999462 -0.29902499914 -0.69811600447 0.65055197477 + -0.41859900951 -0.78314399719 1.7920550108 0.36006298661 0.86833101511 0.34110999107 + 0.34963199496 0.84263598919 0.40953999758 0.33163800836 0.79789799452 0.50336402655 + 0.30199599266 0.72506797314 0.61892998219 0.26860800385 0.6451960206 0.71524202824 + 0.24001699686 0.57639199495 0.78113001585 0.20475299656 0.48927500844 0.84775298834 + 0.15546900034 0.36924800277 0.91623401642 0.31112900376 0.5820800066 1.8879569769 + 0 9.9999999748e-07 -1 -0.059861000627 -0.31428799033 -0.94743901491 + -0.08885499835 -0.45804199576 -0.88447898626 -0.11191800237 -0.57072401047 -0.81347900629 + -0.12967400253 -0.65894901752 -0.7409260273 -0.14708900452 -0.74740499258 -0.64788198471 + -0.16437500715 -0.83301800489 -0.52826297283 -0.17710100114 -0.89432501793 -0.41087499261 + -0.18495799601 -0.93243002892 -0.31042599678 -0.56036299467 -1.8472690582 -0.52306002378 + -0.19347800314 -0.97794097662 -0.078723996878 -0.15708400309 -0.74303799868 0.65055298805 + -0.25777199864 -0.84976100922 1.7920550108 0.18374100327 0.92189097404 0.3411090076 + 0.17852300406 0.89465397596 0.40953999758 0.16960300505 0.84726601839 0.50336301327 + 0.15474000573 0.77005302906 0.61892998219 0.13757500052 0.68520200253 0.71524202824 + 0.12295699865 0.61214202642 0.78113001585 0.10536599904 0.51981902122 0.84775298834 + 0.080444999039 0.39248299599 0.91623401642 0.19159199297 0.63159400225 1.8879569769 + 0 9.9999999748e-07 -1 0.0026030000299 -0.31992700696 -0.94743901491 + 0.0022120000795 -0.46657600999 -0.88447898626 0.001575000002 -0.58159202337 -0.81347900629 + 0.0013719999697 -0.67158597708 -0.7409260273 0.0015490000369 -0.76173901558 -0.64788198471 + 0.0012969999807 -0.84907901287 -0.52826398611 0.00077699997928 -0.91169202328 -0.41087400913 + 0.000503999996 -0.95059800148 -0.31042599678 -0.18921099603 -1.9210959673 -0.52305901051 + 0.0010260000126 -0.99689602852 -0.078725002706 -0.009105999954 -0.7594050169 0.65055400133 + -0.087039001286 -0.88372498751 1.7920529842 0.00035799999023 0.94002300501 0.34110999107 + 0.00055499997688 0.91229200363 0.40953999758 0.0010499999626 0.86407399178 0.50336402655 + 0.0015360000543 0.7854449749 0.61892998219 0.0012560000177 0.69887501001 0.71524202824 + 0.0011719999602 0.62436699867 0.78113001585 0.0019300000276 0.53038698435 0.84775298834 + 0.0023300000466 0.40063598752 0.91623401642 0.064692996442 0.65683597326 1.8879569769 + -0 9.9999999748e-07 -1 0.064967997372 -0.31327199936 -0.94743901491 + 0.093193002045 -0.45717900991 -0.88447898626 0.11500699818 -0.57010900974 -0.81347900629 + 0.13236500323 -0.65841400623 -0.7409260273 0.15012699366 -0.74680101871 -0.64788198471 + 0.166918993 -0.83251202106 -0.52826398611 0.17862400413 -0.89402198792 -0.41087400913 + 0.1859460026 -0.93223398924 -0.31042599678 0.18921199441 -1.9210950136 -0.52305901051 + 0.19549100101 -0.97754001617 -0.078725002706 0.13922099769 -0.74659001827 0.65055400133 + 0.087039999664 -0.88372498751 1.7920529842 -0.18303799629 0.92203098536 0.34110999107 + -0.17743499577 0.89487099648 0.40953999758 -0.16754199564 0.84767597914 0.50336402655 + -0.15172599256 0.77065199614 0.61892998219 -0.13511200249 0.68569201231 0.71524202824 + -0.12065900117 0.61259901524 0.78113001585 -0.10158099979 0.5205720067 0.84775298834 + -0.075874999166 0.3933930099 0.91623401642 -0.064692996442 0.65683597326 1.8879569769 + -0 9.9999999748e-07 -1 0.12483599782 -0.294577986 -0.94743901491 + 0.18059399724 -0.43021300435 -0.88447898626 0.22402000427 -0.5367180109 -0.81347900629 + 0.25827199221 -0.61993902922 -0.7409260273 0.29293599725 -0.70316302776 -0.64788198471 + 0.3261269927 -0.78395098448 -0.52826398611 0.34960699081 -0.84199601412 -0.41087400913 + 0.36424401402 -0.87804502249 -0.31042599678 0.56036299467 -1.8472690582 -0.52306002378 + 0.38244399428 -0.92061901093 -0.078726001084 0.28219899535 -0.70508497953 0.65055298805 + 0.25777301192 -0.84976398945 1.7920529842 -0.35940000415 0.86860501766 0.34110999107 + -0.34860700369 0.84306001663 0.40953999758 -0.32969599962 0.79870200157 0.50336402655 + -0.29915699363 0.72624397278 0.61892998219 -0.26628801227 0.64615702629 0.71524202824 + -0.23785200715 0.57728797197 0.78113001585 -0.20118699968 0.49075201154 0.84775298834 + -0.15116399527 0.37103098631 0.91623401642 -0.19159199297 0.63159400225 1.8879569769 + -0 9.9999999748e-07 -1 0.1799069941 -0.26456299424 -0.94743901491 + 0.26105499268 -0.38671499491 -0.88447797298 0.32442501187 -0.48270100355 -0.81347900629 + 0.37425398827 -0.55764001608 -0.7409260273 0.42448699474 -0.63250297308 -0.64788198471 + 0.47280201316 -0.70526301861 -0.52826297283 0.50715500116 -0.75761198997 -0.41087499261 + 0.52854299545 -0.79011297226 -0.3104250133 0.90998202562 -1.7024519444 -0.52306002378 + 0.5546990037 -0.82831799984 -0.078726999462 0.4143320024 -0.63648200035 0.65055298805 + 0.41860100627 -0.78314697742 1.7920529842 -0.52195101976 0.78179997206 0.34110999107 + -0.50638198853 0.75885099173 0.40953999758 -0.47918099165 0.71903502941 0.50336301327 + -0.43509200215 0.65392702818 0.61892998219 -0.38723099232 0.58179098368 0.71524202824 + -0.34590598941 0.519792974 0.78113001585 -0.29306301475 0.44207298756 0.84775298834 + -0.22064399719 0.33441099524 0.91623401642 -0.31112900376 0.5820800066 1.8879569769 + -0 0 -1 0.22806300223 -0.2243809998 -0.94743901491 + 0.33148300648 -0.32835501432 -0.88447797298 0.41236099601 -0.41013398767 -0.81347900629 + 0.47585299611 -0.47391200066 -0.7409260273 0.53972601891 -0.53753602505 -0.64788198471 + 0.60130697489 -0.59947299957 -0.52826297283 0.64521300793 -0.64411401749 -0.41087400913 + 0.67252999544 -0.67181700468 -0.31042599678 1.224627018 -1.4922120571 -0.52305901051 + 0.70563799143 -0.70418602228 -0.078727997839 0.53054201603 -0.54342001677 0.65055298805 + 0.56334197521 -0.68643301725 1.7920529842 -0.66444301605 0.66495001316 0.34110999107 + -0.64469599724 0.64547997713 0.40953999758 -0.61024999619 0.61173599958 0.50336301327 + -0.55430698395 0.5564789772 0.61892998219 -0.49329200387 0.49506700039 0.71524202824 + -0.44066599011 0.44232299924 0.78113001585 -0.37367600203 0.37640500069 0.84775298834 + -0.28164499998 0.28494000435 0.91623401642 -0.41870900989 0.51019799709 1.8879569769 + -0 0 -1 0.26745599508 -0.17557699978 -0.94743901491 + 0.38917198777 -0.25737598538 -0.88447898626 0.48445099592 -0.32180601358 -0.81347900629 + 0.55916500092 -0.37197199464 -0.7409260273 0.63422298431 -0.42191201448 -0.64788198471 + 0.70670497417 -0.47064501047 -0.52826297283 0.75847500563 -0.50586301088 -0.41087400913 + 0.7906730175 -0.52770501375 -0.31042599678 1.4922130108 -1.2246259451 -0.52306002378 + 0.82945901155 -0.55299198627 -0.078727997839 0.62636500597 -0.42947500944 0.65055197477 + 0.68643200397 -0.56333899498 1.7920550108 -0.78140199184 0.52254700661 0.34110999107 + -0.75823497772 0.5073029995 0.40953999758 -0.71786797047 0.48092699051 0.50336301327 + -0.65221899748 0.43764701486 0.61893099546 -0.58039599657 0.38931798935 0.71524202824 + -0.51849198341 0.34785398841 0.78113001585 -0.43992900848 0.29627200961 0.84775298834 + -0.33182200789 0.22451899946 0.91623401642 -0.51019698381 0.41870799661 1.8879569769 + -9.9999999748e-07 -0 -1 0.29657000303 -0.12002599984 -0.94743901491 + 0.43190601468 -0.17650699615 -0.88447797298 0.5379229784 -0.22111099958 -0.81347900629 + 0.62098902464 -0.25573700666 -0.7409260273 0.70434802771 -0.29007399082 -0.64788198471 + 0.78494298458 -0.32372999191 -0.52826398611 0.8425899744 -0.34817200899 -0.41087499261 + 0.87843000889 -0.36331298947 -0.31042599678 1.7024519444 -0.90998101234 -0.52306002378 + 0.9214040041 -0.38054800034 -0.078725002706 0.69811600447 -0.29902601242 0.65055197477 + 0.78314501047 -0.41859900951 1.7920550108 -0.86833101511 0.36006298661 0.34110999107 + -0.84263598919 0.34963101149 0.40953999758 -0.7978990078 0.33163699508 0.50336301327 + -0.72506797314 0.30199599266 0.61892998219 -0.6451960206 0.26860800385 0.71524202824 + -0.57639199495 0.24001699686 0.78113001585 -0.48927500844 0.20475299656 0.84775298834 + -0.36924800277 0.15546900034 0.91623401642 -0.58207899332 0.31112900376 1.8879569769 + -9.9999999748e-07 0 -1 0.31428700686 -0.059861000627 -0.94743901491 + 0.45804199576 -0.08885499835 -0.88447898626 0.57072401047 -0.11191900074 -0.81347900629 + 0.65894901752 -0.12967500091 -0.7409260273 0.7474039793 -0.14709000289 -0.64788198471 + 0.83301800489 -0.16437500715 -0.52826297283 0.89432501793 -0.17710100114 -0.41087499261 + 0.93243002892 -0.18495799601 -0.31042599678 1.8472690582 -0.56036299467 -0.52306002378 + 0.97794097662 -0.19347800314 -0.078725002706 0.74303799868 -0.15708400309 0.65055298805 + 0.84976500273 -0.2577739954 1.7920529842 -0.92189097404 0.18374100327 0.34110999107 + -0.89465397596 0.17852400243 0.40953999758 -0.84726601839 0.16960300505 0.50336402655 + -0.77005302906 0.15474000573 0.61892998219 -0.68520200253 0.1375759989 0.71524202824 + -0.61214202642 0.12295699865 0.78113001585 -0.51981902122 0.10536599904 0.84775298834 + -0.39248299599 0.080444999039 0.91623401642 -0.63159400225 0.1915909946 1.8879569769 + -9.9999999748e-07 0 -1 0.31992700696 0.0026030000299 -0.94743901491 + 0.46657600999 0.0022110000718 -0.88447898626 0.58159202337 0.0015739999944 -0.81347900629 + 0.6715850234 0.0013719999697 -0.7409260273 0.76173901558 0.0015480000293 -0.64788198471 + 0.84908002615 0.0012969999807 -0.52826297283 0.91169202328 0.00077599997167 -0.41087400913 + 0.9505969882 0.000503999996 -0.31042599678 1.9210950136 -0.18921099603 -0.52306002378 + 0.99689602852 0.0010270000203 -0.078727997839 0.75940698385 -0.009105999954 0.65055197477 + 0.88372701406 -0.087039001286 1.7920520306 -0.94002300501 0.00035799999023 0.34110999107 + -0.91229200363 0.00055499997688 0.40953999758 -0.86407399178 0.0010509999702 0.50336402655 + -0.78544402122 0.0015369999455 0.61892998219 -0.69887501001 0.0012560000177 0.71524202824 + -0.62436699867 0.0011719999602 0.78113001585 -0.53038698435 0.0019300000276 0.84775298834 + -0.40063598752 0.0023300000466 0.91623401642 -0.65683597326 0.064692996442 1.8879569769 + -9.9999999748e-07 -0 -1 0.31327199936 0.064967997372 -0.94743901491 + 0.45717900991 0.093194000423 -0.88447898626 0.57010900974 0.11500699818 -0.81348001957 + 0.65841400623 0.13236500323 -0.7409260273 0.74680000544 0.15012699366 -0.64788198471 + 0.83251100779 0.16692000628 -0.52826398611 0.89402198792 0.17862400413 -0.41087499261 + 0.93223398924 0.18594700098 -0.31042599678 1.9210959673 0.18921099603 -0.52305901051 + 0.97754001617 0.19549199939 -0.078726999462 0.74659198523 0.13922199607 0.65055197477 + 0.88372498751 0.087039999664 1.7920529842 -0.92203098536 -0.18303799629 0.34110999107 + -0.89487099648 -0.17743599415 0.40953999758 -0.84767597914 -0.16754199564 0.50336402655 + -0.77065199614 -0.15172599256 0.61892998219 -0.68569099903 -0.13511200249 0.71524298191 + -0.61259901524 -0.12065900117 0.78113001585 -0.5205720067 -0.10158000141 0.84775298834 + -0.39339199662 -0.075874999166 0.91623401642 -0.65683597326 -0.064691998065 1.8879569769 + -9.9999999748e-07 -0 -1 0.29457700253 0.12483599782 -0.94743901491 + 0.43021300435 0.18059399724 -0.88447898626 0.5367180109 0.22402000427 -0.81348001957 + 0.61993902922 0.25827199221 -0.7409260273 0.70316302776 0.29293599725 -0.64788198471 + 0.78395098448 0.3261269927 -0.52826297283 0.84199601412 0.34960699081 -0.41087499261 + 0.87804502249 0.36424401402 -0.31042599678 1.8472679853 0.56036400795 -0.52306002378 + 0.92061901093 0.38244399428 -0.078726001084 0.70508599281 0.28220000863 0.65055197477 + 0.84976297617 0.25777301192 1.7920540571 -0.86860501766 -0.35940000415 0.34110999107 + -0.84306001663 -0.34860700369 0.40953999758 -0.79870200157 -0.32969599962 0.50336402655 + -0.72624397278 -0.29915699363 0.61892998219 -0.64615702629 -0.26628801227 0.71524202824 + -0.57728898525 -0.23785300553 0.78113001585 -0.49075201154 -0.20118699968 0.84775298834 + -0.37103098631 -0.15116399527 0.91623401642 -0.63159400225 -0.19159199297 1.8879569769 + -0 -1.999999995e-06 -1 0.26456299424 0.17990599573 -0.94743901491 + 0.38671401143 0.2610540092 -0.88447898626 0.48270100355 0.32442399859 -0.81347900629 + 0.55764001608 0.37425398827 -0.7409260273 0.63250201941 0.42448699474 -0.64788198471 + 0.70526301861 0.47280201316 -0.52826297283 0.75761198997 0.50715500116 -0.41087499261 + 0.79011297226 0.52854299545 -0.31042599678 1.7024519444 0.90998101234 -0.52305901051 + 0.82831799984 0.5546990037 -0.078726999462 0.63648200035 0.4143320024 0.65055298805 + 0.78314602375 0.41860100627 1.7920540571 -0.78179997206 -0.52195101976 0.34110999107 + -0.75885099173 -0.50638097525 0.40953999758 -0.71903502941 -0.47918000817 0.50336402655 + -0.65392702818 -0.43509200215 0.61892998219 -0.58179098368 -0.38723000884 0.71524202824 + -0.519792974 -0.34590598941 0.78113001585 -0.44207298756 -0.29306301475 0.84775298834 + -0.33441099524 -0.22064399719 0.91623401642 -0.5820800066 -0.31112799048 1.8879569769 + -9.9999999748e-07 -9.9999999748e-07 -1 0.22438199818 0.22806300223 -0.94743901491 + 0.32835501432 0.3314819932 -0.88447898626 0.41013398767 0.41236099601 -0.81347900629 + 0.47391301394 0.47585299611 -0.7409260273 0.53753602505 0.53972601891 -0.64788198471 + 0.59947198629 0.60130697489 -0.52826398611 0.64411401749 0.64521199465 -0.41087400913 + 0.67181801796 0.67252999544 -0.31042599678 1.4922120571 1.224627018 -0.52306002378 + 0.70418602228 0.70563799143 -0.078726999462 0.54342001677 0.53054201603 0.65055298805 + 0.68643301725 0.56334102154 1.7920540571 -0.66495001316 -0.66444301605 0.34110999107 + -0.64547997713 -0.64469599724 0.40953999758 -0.61173498631 -0.61024999619 0.50336402655 + -0.5564789772 -0.55430698395 0.61892998219 -0.49506700039 -0.49329200387 0.71524202824 + -0.44232299924 -0.44066599011 0.78113001585 -0.37640500069 -0.37367600203 0.84775298834 + -0.28494000435 -0.28164499998 0.91623401642 -0.51019799709 -0.41870799661 1.8879569769 + -9.9999999748e-07 -9.9999999748e-07 -1 0.17557699978 0.26745599508 -0.94743901491 + 0.25737598538 0.38917198777 -0.88447898626 0.32180601358 0.48445001245 -0.81347900629 + 0.37197199464 0.55916500092 -0.7409260273 0.42191201448 0.63422298431 -0.64788198471 + 0.47064501047 0.7067040205 -0.52826398611 0.50586301088 0.75847500563 -0.41087499261 + 0.52770501375 0.7906730175 -0.31042599678 1.2246259451 1.4922120571 -0.52306097746 + 0.55299198627 0.82945901155 -0.078726001084 0.42947500944 0.62636399269 0.65055298805 + 0.56334102154 0.68643301725 1.7920540571 -0.52254700661 -0.78140199184 0.34110999107 + -0.5073029995 -0.75823497772 0.40953999758 -0.48092699051 -0.71786797047 0.50336402655 + -0.43764701486 -0.65222001076 0.61892998219 -0.38931798935 -0.58039599657 0.71524202824 + -0.34785398841 -0.51849198341 0.78113001585 -0.29627200961 -0.43992900848 0.84775298834 + -0.22451899946 -0.33182200789 0.91623401642 -0.41870799661 -0.51019799709 1.8879569769 + -9.9999999748e-07 -9.9999999748e-07 -1 0.12002500147 0.29657000303 -0.94743901491 + 0.17650699615 0.43190601468 -0.88447898626 0.22111000121 0.5379229784 -0.81347900629 + 0.25573700666 0.62098902464 -0.7409260273 0.29007399082 0.70434802771 -0.64788198471 + 0.32372999191 0.78494399786 -0.52826398611 0.34817200899 0.8425899744 -0.41087400913 + 0.363312006 0.87843000889 -0.31042599678 0.90997898579 1.7024530172 -0.52306002378 + 0.38054698706 0.9214040041 -0.078727997839 0.29902499914 0.69811499119 0.65055298805 + 0.41859999299 0.78314602375 1.7920529842 -0.36006200314 -0.86833101511 0.34110999107 + -0.34963101149 -0.84263598919 0.40953999758 -0.33163699508 -0.79789799452 0.50336402655 + -0.30199599266 -0.72506797314 0.61892998219 -0.26860800385 -0.6451960206 0.71524298191 + -0.24001699686 -0.57639199495 0.78113001585 -0.20475299656 -0.48927500844 0.84775298834 + -0.15546900034 -0.36924800277 0.91623401642 -0.31112799048 -0.5820800066 1.8879569769 + -0 -9.9999999748e-07 -1 0.059861000627 0.31428700686 -0.94743901491 + 0.08885499835 0.45804199576 -0.88447898626 0.11191800237 0.57072401047 -0.81347900629 + 0.12967400253 0.65894800425 -0.7409260273 0.14708900452 0.74740499258 -0.64788198471 + 0.16437500715 0.83301800489 -0.52826398611 0.17710100114 0.89432501793 -0.41087400913 + 0.18495799601 0.93243002892 -0.31042599678 0.56036198139 1.8472690582 -0.52306002378 + 0.19347800314 0.97794097662 -0.078727997839 0.15708400309 0.74303901196 0.65055197477 + 0.25777199864 0.84976297617 1.7920540571 -0.18374100327 -0.92189097404 0.34110999107 + -0.17852300406 -0.89465397596 0.40953999758 -0.16960300505 -0.84726601839 0.50336402655 + -0.15473900735 -0.77005201578 0.61892998219 -0.13757500052 -0.68520200253 0.71524202824 + -0.12295699865 -0.61214101315 0.78113001585 -0.10536599904 -0.51981902122 0.84775298834 + -0.080444999039 -0.39248299599 0.91623401642 -0.1915909946 -0.63159400225 1.8879569769 + -0 -9.9999999748e-07 -1 -0.0026040000375 0.31992700696 -0.94743901491 + -0.0022120000795 0.46657499671 -0.88447898626 -0.001575000002 0.58159202337 -0.81347900629 + -0.0013719999697 0.6715850234 -0.7409260273 -0.0015490000369 0.76173901558 -0.64788198471 + -0.0012969999807 0.84907901287 -0.52826398611 -0.00077699997928 0.91169101 -0.41087499261 + -0.000503999996 0.9505969882 -0.31042599678 0.18921099603 1.9210950136 -0.52306002378 + -0.0010260000126 0.99689602852 -0.078726999462 0.009105999954 0.75940698385 0.65055298805 + 0.087039001286 0.88372302055 1.7920540571 -0.00035799999023 -0.94002300501 0.34110999107 + -0.00055499997688 -0.91229200363 0.40953999758 -0.0010499999626 -0.86407399178 0.50336402655 + -0.0015360000543 -0.78544402122 0.61893099546 -0.0012550000101 -0.69887501001 0.71524202824 + -0.0011719999602 -0.62436699867 0.78113001585 -0.0019300000276 -0.53038698435 0.84775400162 + -0.0023300000466 -0.40063598752 0.91623401642 -0.064692996442 -0.65683597326 1.8879569769 + 0 -9.9999999748e-07 -1 -0.064967997372 0.31327199936 -0.94743901491 + -0.093194000423 0.45717900991 -0.88447898626 -0.11500799656 0.57010900974 -0.81347900629 + -0.13236500323 0.65841299295 -0.7409260273 -0.15012699366 0.74680000544 -0.64788198471 + -0.166918993 0.83251202106 -0.52826297283 -0.17862400413 0.89402198792 -0.41087499261 + -0.18594700098 0.93223398924 -0.31042599678 -0.18921199441 1.9210950136 -0.52306097746 + -0.19549100101 0.97754001617 -0.078726999462 -0.13922199607 0.74659097195 0.65055298805 + -0.087039001286 0.88372302055 1.7920540571 0.18303799629 -0.92203098536 0.34110999107 + 0.17743499577 -0.89487099648 0.40953999758 0.16754199564 -0.84767597914 0.50336402655 + 0.15172599256 -0.77065199614 0.61892998219 0.13511200249 -0.68569201231 0.71524202824 + 0.12065900117 -0.61259901524 0.78113001585 0.10158099979 -0.5205720067 0.84775298834 + 0.075874999166 -0.39339199662 0.91623401642 0.064692996442 -0.65683597326 1.8879569769 + 0 -9.9999999748e-07 -1 -0.12483599782 0.294577986 -0.94743901491 + -0.18059399724 0.43021300435 -0.88447898626 -0.22402000427 0.5367180109 -0.81347900629 + -0.25827199221 0.61993902922 -0.7409260273 -0.29293599725 0.70316201448 -0.64788198471 + -0.3261269927 0.78395098448 -0.52826398611 -0.34960699081 0.84199601412 -0.41087400913 + -0.36424300075 0.87804502249 -0.31042599678 -0.56036299467 1.8472679853 -0.52306097746 + -0.38244399428 0.92061901093 -0.078726999462 -0.28219899535 0.70508497953 0.65055298805 + -0.25777301192 0.8497620225 1.7920540571 0.35940000415 -0.86860501766 0.34110999107 + 0.34860700369 -0.84306001663 0.40953999758 0.32969599962 -0.79870200157 0.50336402655 + 0.29915699363 -0.72624397278 0.61892998219 0.26628801227 -0.64615702629 0.71524202824 + 0.23785300553 -0.57728797197 0.78113001585 0.20118799806 -0.49075201154 0.84775298834 + 0.15116399527 -0.37103098631 0.91623401642 0.19159199297 -0.63159400225 1.8879569769 + 9.9999999748e-07 -9.9999999748e-07 -1 -0.1799069941 0.26456299424 -0.94743901491 + -0.2610540092 0.38671401143 -0.88447898626 -0.32442399859 0.48270100355 -0.81347900629 + -0.37425398827 0.55764001608 -0.7409260273 -0.42448699474 0.63250201941 -0.64788198471 + -0.47280201316 0.70526301861 -0.52826398611 -0.50715500116 0.75761198997 -0.41087499261 + -0.52854299545 0.79011297226 -0.31042599678 -0.90998101234 1.7024519444 -0.52306002378 + -0.5546990037 0.82831799984 -0.078726001084 -0.4143320024 0.63648301363 0.65055298805 + -0.41860100627 0.78314602375 1.7920529842 0.52195101976 -0.78179997206 0.34110999107 + 0.50638097525 -0.75885099173 0.40953999758 0.47918000817 -0.71903502941 0.50336402655 + 0.43509200215 -0.6539260149 0.61892998219 0.38723099232 -0.58179098368 0.71524202824 + 0.34590598941 -0.519792974 0.78113001585 0.29306301475 -0.44207298756 0.84775298834 + 0.22064399719 -0.33441099524 0.91623401642 0.31112900376 -0.5820800066 1.8879569769 + 9.9999999748e-07 -9.9999999748e-07 -1 -0.22806300223 0.22438199818 -0.94743901491 + -0.33148300648 0.32835501432 -0.88447898626 -0.41236099601 0.41013398767 -0.81347900629 + -0.47585299611 0.47391301394 -0.7409260273 -0.53972601891 0.53753602505 -0.64788198471 + -0.60130697489 0.59947299957 -0.52826398611 -0.64521199465 0.64411401749 -0.41087400913 + -0.67252999544 0.67181801796 -0.31042599678 -1.224627018 1.4922120571 -0.52306002378 + -0.70563697815 0.70418602228 -0.078726001084 -0.53054201603 0.54342097044 0.65055298805 + -0.56334197521 0.68643397093 1.7920529842 0.66444301605 -0.66495001316 0.34110999107 + 0.64469599724 -0.64547997713 0.40953999758 0.61024999619 -0.61173498631 0.50336402655 + 0.55430698395 -0.5564789772 0.61893099546 0.49329200387 -0.49506700039 0.71524202824 + 0.44066599011 -0.44232299924 0.78113001585 0.37367600203 -0.37640500069 0.84775298834 + 0.28164499998 -0.28494000435 0.91623401642 0.41870900989 -0.51019698381 1.8879569769 + 9.9999999748e-07 -9.9999999748e-07 -1 -0.26745599508 0.17557699978 -0.94743901491 + -0.38917198777 0.25737699866 -0.88447898626 -0.48445001245 0.32180601358 -0.81347900629 + -0.55916500092 0.37197199464 -0.7409260273 -0.63422298431 0.42191201448 -0.64788198471 + -0.7067040205 0.47064501047 -0.52826398611 -0.75847500563 0.50586301088 -0.41087400913 + -0.7906730175 0.52770501375 -0.31042599678 -1.4922120571 1.224627018 -0.52306002378 + -0.82945901155 0.55299198627 -0.078726001084 -0.62636399269 0.42947500944 0.65055298805 + -0.68643301725 0.56334102154 1.7920540571 0.78140199184 -0.52254700661 0.34110999107 + 0.75823497772 -0.5073029995 0.40953999758 0.71786701679 -0.48092699051 0.50336402655 + 0.65221899748 -0.43764701486 0.61893099546 0.58039599657 -0.38931900263 0.71524202824 + 0.51849102974 -0.34785398841 0.78113001585 0.43992900848 -0.29627200961 0.84775298834 + 0.33182200789 -0.22451800108 0.91623401642 0.51019698381 -0.41870900989 1.8879569769 + 0 -1.999999995e-06 -1 -0.29657000303 0.12002500147 -0.94743901491 + -0.43190601468 0.17650699615 -0.88447898626 -0.5379229784 0.22111099958 -0.81347900629 + -0.62098902464 0.25573700666 -0.7409260273 -0.70434802771 0.29007399082 -0.64788198471 + -0.78494399786 0.32372999191 -0.52826398611 -0.8425899744 0.34817200899 -0.41087400913 + -0.87843000889 0.363312006 -0.31042599678 -1.7024530172 0.90997898579 -0.52306097746 + -0.92140501738 0.38054698706 -0.078725002706 -0.69811499119 0.29902499914 0.65055298805 + -0.78314602375 0.41859999299 1.7920540571 0.86833101511 -0.36006200314 0.34110999107 + 0.84263598919 -0.34963101149 0.40953999758 0.79789799452 -0.33163699508 0.50336402655 + 0.72506797314 -0.30199599266 0.61892998219 0.6451960206 -0.26860800385 0.71524202824 + 0.57639199495 -0.24001699686 0.78113001585 0.48927500844 -0.20475299656 0.84775298834 + 0.36924800277 -0.15546900034 0.91623401642 0.58208101988 -0.31112700701 1.8879569769 + 0 -0 -1 9.9999999748e-07 -0 -1 + -0.31428700686 0.059861000627 -0.94743901491 -0.45804199576 0.08885499835 -0.88447898626 + -0.57072401047 0.11191800237 -0.81348001957 -0.65894901752 0.12967400253 -0.7409260273 + -0.74740499258 0.14708900452 -0.64788198471 -0.83301800489 0.16437500715 -0.52826398611 + -0.89432501793 0.17710000277 -0.41087499261 -0.93243002892 0.18495799601 -0.31042599678 + -1.8472690582 0.56036198139 -0.52306002378 -0.97794097662 0.19347800314 -0.078725002706 + -0.74303799868 0.15708400309 0.65055298805 -0.84976297617 0.25777199864 1.7920529842 + 0.92189097404 -0.18374100327 0.34110999107 0.89465397596 -0.17852300406 0.40953999758 + 0.84726601839 -0.16960300505 0.50336301327 0.77005201578 -0.15473900735 0.61892998219 + 0.68520200253 -0.13757500052 0.71524202824 0.61214202642 -0.12295699865 0.78113001585 + 0.51981902122 -0.10536599904 0.84775298834 0.39248299599 -0.080444999039 0.91623401642 + 0.63159400225 -0.1915909946 1.8879569769 -0 0 1 + + + + + + + -0.098132997751 0 0 -0.1264770031 -0 0.0069989999756 + -0.15419499576 -0 0.019021999091 -0.18128700554 -0 0.036068998277 + -0.20863799751 -0 0.058177001774 -0.23536400497 -0 0.085308998823 + -0.25881099701 -0 0.11735200137 -0.27809399366 -0 0.15426999331 + -0.29409900308 -0 0.19609899819 -0.30682599545 -0 0.24284000695 + -0.3122189939 -0 0.25372600555 -0.30972000957 -0 0.26173099875 + -0.29932999611 -0 0.26685500145 -0.28191199899 -0 0.21355000138 + -0.2634640038 -0 0.16741199791 -0.24398499727 -0 0.12844100595 + -0.2233120054 -0 0.09766100347 -0.20160800219 -0 0.074046999216 + -0.17936399579 -0 0.054531000555 -0.1567440033 -0 0.038090001792 + -0.13358299434 -0 0.025746000931 -0.10988099873 0 0.017500000075 + -0.096247002482 -0.019145000726 0 -0.12404599786 -0.024674000219 0.0069989999756 + -0.15123200417 -0.030082000419 0.019021999091 -0.17780399323 -0.035367000848 0.036068998277 + -0.204629004 -0.040702998638 0.058177001774 -0.23084099591 -0.045917000622 0.085308998823 + -0.25383800268 -0.050491001457 0.11735200137 -0.2727510035 -0.054253999144 0.15426999331 + -0.28844800591 -0.05737600103 0.19609899819 -0.30092999339 -0.059859000146 0.24284000695 + -0.30621999502 -0.060910999775 0.25372600555 -0.30376899242 -0.060423001647 0.26173099875 + -0.29357799888 -0.058396000415 0.26685500145 -0.27649500966 -0.054997999221 0.21355000138 + -0.25840198994 -0.051398999989 0.16741199791 -0.23929700255 -0.047598998994 0.12844100595 + -0.21902100742 -0.043565999717 0.09766100347 -0.19773499668 -0.039331998676 0.074046999216 + -0.17591799796 -0.034991998225 0.054531000555 -0.15373200178 -0.030579000711 0.038090001792 + -0.13101600111 -0.026061000302 0.025746000931 -0.10777000338 -0.021437000483 0.017500000075 + -0.090663000941 -0.037553999573 0 -0.11684899777 -0.048401001841 0.0069989999756 + -0.14245699346 -0.059007998556 0.019021999091 -0.16748699546 -0.069375999272 0.036068998277 + -0.19275699556 -0.0798420012 0.058177001774 -0.21744799614 -0.090070001781 0.085308998823 + -0.23910999298 -0.099042996764 0.11735200137 -0.25692600012 -0.10642199963 0.15426999331 + -0.27171200514 -0.11254700273 0.19609899819 -0.2834700048 -0.11741700023 0.24284000695 + -0.28845199943 -0.11948099732 0.25372600555 -0.28614398837 -0.11852499843 0.26173099875 + -0.27654498816 -0.11454900354 0.26685500145 -0.26045298576 -0.10788299888 0.21355000138 + -0.24340899289 -0.10082300007 0.16741199791 -0.22541299462 -0.09336899966 0.12844100595 + -0.20631399751 -0.085458002985 0.09766100347 -0.18626199663 -0.077151998878 0.074046999216 + -0.16571100056 -0.068640001118 0.054531000555 -0.14481200278 -0.059983000159 0.038090001792 + -0.12341400236 -0.051120001823 0.025746000931 -0.1015169993 -0.04205000028 0.017500000075 + -0.081595003605 -0.054519999772 0 -0.10516099632 -0.070266999304 0.0069989999756 + -0.12820799649 -0.085666000843 0.019021999091 -0.15073500574 -0.10071799904 0.036068998277 + -0.17347599566 -0.11591300368 0.058177001774 -0.19569799304 -0.13076099753 0.085308998823 + -0.21519300342 -0.14378799498 0.11735200137 -0.23122699559 -0.15450100601 0.15426999331 + -0.24453499913 -0.16339300573 0.19609899819 -0.25511598587 -0.17046299577 0.24284000695 + -0.25960001349 -0.17345899343 0.25372600555 -0.25752300024 -0.17207099497 0.26173099875 + -0.24888299406 -0.16629900038 0.26685500145 -0.23440100253 -0.15662199259 0.21355000138 + -0.21906200051 -0.14637300372 0.16741199791 -0.20286600292 -0.1355510056 0.12844100595 + -0.18567700684 -0.12406600267 0.09766100347 -0.16763100028 -0.11200799793 0.074046999216 + -0.14913600683 -0.099648997188 0.054531000555 -0.13032700121 -0.087081998587 0.038090001792 + -0.11106999964 -0.07421399653 0.025746000931 -0.09136299789 -0.061046998948 0.017500000075 + -0.069390997291 -0.069390997291 0 -0.089432001114 -0.089432001114 0.0069989999756 + -0.10903199762 -0.10903199762 0.019021999091 -0.12818899751 -0.12818899751 0.036068998277 + -0.147529006 -0.147529006 0.058177001774 -0.16642700136 -0.16642700136 0.085308998823 + -0.18300700188 -0.18300700188 0.11735200137 -0.1966419965 -0.1966419965 0.15426999331 + -0.20795999467 -0.20795999467 0.19609899819 -0.21695800126 -0.21695899963 0.24284000695 + -0.22077199817 -0.22077199817 0.25372600555 -0.21900500357 -0.21900500357 0.26173099875 + -0.21165800095 -0.21165800095 0.26685500145 -0.1993419975 -0.1993419975 0.21355000138 + -0.18629699945 -0.18629699945 0.16741199791 -0.17252400517 -0.17252400517 0.12844100595 + -0.15790599585 -0.15790599585 0.09766100347 -0.14255900681 -0.14255900681 0.074046999216 + -0.12682999671 -0.12682999671 0.054531000555 -0.11083400249 -0.11083400249 0.038090001792 + -0.094457000494 -0.094457000494 0.025746000931 -0.077697999775 -0.077697999775 0.017500000075 + -0.054519999772 -0.081595003605 0 -0.070266999304 -0.10516099632 0.0069989999756 + -0.085666000843 -0.12820799649 0.019021999091 -0.10071799904 -0.15073500574 0.036068998277 + -0.11591300368 -0.17347599566 0.058177001774 -0.13076099753 -0.19569799304 0.085308998823 + -0.14378799498 -0.21519300342 0.11735200137 -0.15450100601 -0.23122699559 0.15426999331 + -0.16339300573 -0.24453499913 0.19609899819 -0.17046299577 -0.25511598587 0.24284000695 + -0.17345899343 -0.25960001349 0.25372600555 -0.17207099497 -0.25752300024 0.26173099875 + -0.16629900038 -0.24888400733 0.26685500145 -0.15662199259 -0.23440100253 0.21355000138 + -0.14637300372 -0.21906200051 0.16741199791 -0.1355510056 -0.20286600292 0.12844100595 + -0.12406600267 -0.18567700684 0.09766100347 -0.11200799793 -0.16763100028 0.074046999216 + -0.099648997188 -0.14913600683 0.054531000555 -0.087081998587 -0.13032799959 0.038090001792 + -0.07421399653 -0.11106999964 0.025746000931 -0.061046998948 -0.09136299789 0.017500000075 + -0.037553999573 -0.090663000941 0 -0.048399999738 -0.11684899777 0.0069989999756 + -0.059007998556 -0.14245699346 0.019021999091 -0.069375000894 -0.16748699546 0.036068998277 + -0.0798420012 -0.19275699556 0.058177001774 -0.090070001781 -0.21744799614 0.085308998823 + -0.099042996764 -0.23910999298 0.11735200137 -0.10642199963 -0.25692600012 0.15426999331 + -0.11254700273 -0.27171200514 0.19609899819 -0.11741700023 -0.2834700048 0.24284000695 + -0.11948099732 -0.28845199943 0.25372600555 -0.11852499843 -0.28614398837 0.26173099875 + -0.11454799771 -0.27654498816 0.26685500145 -0.10788299888 -0.26045298576 0.21355000138 + -0.10082300007 -0.24340899289 0.16741199791 -0.09336899966 -0.22541299462 0.12844100595 + -0.085458002985 -0.20631399751 0.09766100347 -0.077151998878 -0.18626199663 0.074046999216 + -0.068640001118 -0.16571100056 0.054531000555 -0.059983000159 -0.14481200278 0.038090001792 + -0.051120001823 -0.12341400236 0.025746000931 -0.04205000028 -0.1015169993 0.017500000075 + -0.019145000726 -0.096247002482 0 -0.024674000219 -0.12404599786 0.0069989999756 + -0.030082000419 -0.15123200417 0.019021999091 -0.035367000848 -0.17780399323 0.036068998277 + -0.040702998638 -0.204629004 0.058177001774 -0.045917000622 -0.23084099591 0.085308998823 + -0.050491001457 -0.25383800268 0.11735200137 -0.054253000766 -0.2727510035 0.15426999331 + -0.05737600103 -0.28844800591 0.19609899819 -0.059859000146 -0.30092999339 0.24284000695 + -0.060910999775 -0.30621999502 0.25372600555 -0.060423001647 -0.30376899242 0.26173099875 + -0.058396000415 -0.29357799888 0.26685500145 -0.054997999221 -0.27649500966 0.21355000138 + -0.051398999989 -0.25840198994 0.16741199791 -0.047598998994 -0.23929700255 0.12844100595 + -0.043565999717 -0.21902100742 0.09766100347 -0.039331998676 -0.19773499668 0.074046999216 + -0.034991998225 -0.17591799796 0.054531000555 -0.030579000711 -0.15373200178 0.038090001792 + -0.026061000302 -0.13101600111 0.025746000931 -0.021437000483 -0.10777000338 0.017500000075 + 0 -0.098132997751 0 0 -0.1264770031 0.0069989999756 + 0 -0.15419499576 0.019021999091 0 -0.18128700554 0.036068998277 + 0 -0.20863799751 0.058177001774 0 -0.23536400497 0.085308998823 + 0 -0.25881099701 0.11735200137 0 -0.27809399366 0.15426999331 + 0 -0.29409900308 0.19609899819 0 -0.30682599545 0.24284000695 + 0 -0.3122189939 0.25372600555 0 -0.30972000957 0.26173099875 + 0 -0.29932999611 0.26685500145 0 -0.28191199899 0.21355000138 + 0 -0.2634640038 0.16741199791 0 -0.24398499727 0.12844100595 + 0 -0.2233120054 0.09766100347 0 -0.20160800219 0.074046999216 + 0 -0.17936399579 0.054531000555 0 -0.1567440033 0.038090001792 + 0 -0.13358299434 0.025746000931 0 -0.10988099873 0.017500000075 + 0.019145000726 -0.096247002482 0 0.024674000219 -0.12404599786 0.0069989999756 + 0.030082000419 -0.15123200417 0.019021999091 0.035367000848 -0.17780399323 0.036068998277 + 0.040702998638 -0.204629004 0.058177001774 0.045917000622 -0.23084099591 0.085308998823 + 0.050491001457 -0.25383800268 0.11735200137 0.054253999144 -0.2727510035 0.15426999331 + 0.05737600103 -0.28844800591 0.19609899819 0.059859000146 -0.30092999339 0.24284000695 + 0.060910999775 -0.30621999502 0.25372600555 0.060423001647 -0.30376899242 0.26173099875 + 0.058396000415 -0.29357799888 0.26685500145 0.054997999221 -0.27649500966 0.21355000138 + 0.051398999989 -0.25840198994 0.16741199791 0.047598998994 -0.23929700255 0.12844100595 + 0.043565999717 -0.21902100742 0.09766100347 0.039331998676 -0.19773499668 0.074046999216 + 0.034991998225 -0.17591799796 0.054531000555 0.030579000711 -0.15373200178 0.038090001792 + 0.026061000302 -0.13101600111 0.025746000931 0.021437000483 -0.10777000338 0.017500000075 + 0.037553999573 -0.090663000941 0 0.048401001841 -0.11684899777 0.0069989999756 + 0.059007998556 -0.14245699346 0.019021999091 0.069375999272 -0.16748699546 0.036068998277 + 0.0798420012 -0.19275699556 0.058177001774 0.090070001781 -0.21744799614 0.085308998823 + 0.099042996764 -0.23910999298 0.11735200137 0.10642199963 -0.25692600012 0.15426999331 + 0.11254700273 -0.27171200514 0.19609899819 0.11741700023 -0.2834700048 0.24284000695 + 0.11948099732 -0.28845199943 0.25372600555 0.11852499843 -0.28614398837 0.26173099875 + 0.11454900354 -0.27654498816 0.26685500145 0.10788299888 -0.26045298576 0.21355000138 + 0.10082300007 -0.24340899289 0.16741199791 0.09336899966 -0.22541299462 0.12844100595 + 0.085458002985 -0.20631399751 0.09766100347 0.077151998878 -0.18626199663 0.074046999216 + 0.068640001118 -0.16571100056 0.054531000555 0.059983000159 -0.14481200278 0.038090001792 + 0.051120001823 -0.12341400236 0.025746000931 0.04205000028 -0.1015169993 0.017500000075 + 0.054519999772 -0.081595003605 0 0.070266999304 -0.10516099632 0.0069989999756 + 0.085666000843 -0.12820799649 0.019021999091 0.10071799904 -0.15073500574 0.036068998277 + 0.11591300368 -0.17347599566 0.058177001774 0.13076099753 -0.19569799304 0.085308998823 + 0.14378799498 -0.21519300342 0.11735200137 0.15450100601 -0.23122699559 0.15426999331 + 0.16339300573 -0.24453499913 0.19609899819 0.17046299577 -0.25511598587 0.24284000695 + 0.17346000671 -0.25960001349 0.25372600555 0.17207099497 -0.25752300024 0.26173099875 + 0.16629900038 -0.24888299406 0.26685500145 0.15662199259 -0.23440100253 0.21355000138 + 0.14637300372 -0.21906200051 0.16741199791 0.1355510056 -0.20286600292 0.12844100595 + 0.12406600267 -0.18567700684 0.09766100347 0.11200799793 -0.16763100028 0.074046999216 + 0.099650003016 -0.14913600683 0.054531000555 0.087081998587 -0.13032700121 0.038090001792 + 0.074215002358 -0.11106999964 0.025746000931 0.061046998948 -0.09136299789 0.017500000075 + 0.069390997291 -0.069390997291 0 0.089432001114 -0.089432001114 0.0069989999756 + 0.10903199762 -0.10903199762 0.019021999091 0.12818899751 -0.12818899751 0.036068998277 + 0.147529006 -0.147529006 0.058177001774 0.16642700136 -0.16642700136 0.085308998823 + 0.18300700188 -0.18300700188 0.11735200137 0.1966419965 -0.1966419965 0.15426999331 + 0.20795999467 -0.20795999467 0.19609899819 0.21695899963 -0.21695800126 0.24284000695 + 0.22077199817 -0.22077199817 0.25372600555 0.21900500357 -0.21900500357 0.26173099875 + 0.21165800095 -0.21165800095 0.26685500145 0.1993419975 -0.1993419975 0.21355000138 + 0.18629699945 -0.18629699945 0.16741199791 0.17252400517 -0.17252400517 0.12844100595 + 0.15790599585 -0.15790599585 0.09766100347 0.14255900681 -0.14255900681 0.074046999216 + 0.12682999671 -0.12682999671 0.054531000555 0.11083400249 -0.11083400249 0.038090001792 + 0.094457000494 -0.094457000494 0.025746000931 0.077697999775 -0.077697999775 0.017500000075 + 0.081595003605 -0.054519999772 0 0.10516099632 -0.070266999304 0.0069989999756 + 0.12820799649 -0.085666000843 0.019021999091 0.15073500574 -0.10071799904 0.036068998277 + 0.17347599566 -0.11591300368 0.058177001774 0.19569799304 -0.13076099753 0.085308998823 + 0.21519300342 -0.1437869966 0.11735200137 0.23122699559 -0.15450100601 0.15426999331 + 0.24453499913 -0.16339300573 0.19609899819 0.25511598587 -0.17046299577 0.24284000695 + 0.25960001349 -0.17345899343 0.25372600555 0.25752300024 -0.17207099497 0.26173099875 + 0.24888400733 -0.16629900038 0.26685500145 0.2344020009 -0.15662199259 0.21355000138 + 0.21906200051 -0.14637300372 0.16741199791 0.20286600292 -0.1355510056 0.12844100595 + 0.18567700684 -0.12406600267 0.09766100347 0.16763100028 -0.11200799793 0.074046999216 + 0.14913600683 -0.099648997188 0.054531000555 0.13032799959 -0.087081998587 0.038090001792 + 0.11106999964 -0.07421399653 0.025746000931 0.09136299789 -0.061046998948 0.017500000075 + 0.090663000941 -0.037553999573 0 0.11684899777 -0.048399999738 0.0069989999756 + 0.14245699346 -0.059007998556 0.019021999091 0.16748699546 -0.069375000894 0.036068998277 + 0.19275699556 -0.0798420012 0.058177001774 0.21744799614 -0.090070001781 0.085308998823 + 0.23910999298 -0.099041998386 0.11735200137 0.25692600012 -0.10642199963 0.15426999331 + 0.27171298862 -0.11254700273 0.19609899819 0.2834700048 -0.11741700023 0.24284000695 + 0.2884530127 -0.11948099732 0.25372600555 0.28614398837 -0.11852499843 0.26173099875 + 0.27654498816 -0.11454799771 0.26685500145 0.26045298576 -0.10788299888 0.21355000138 + 0.24340899289 -0.10082300007 0.16741199791 0.22541299462 -0.09336899966 0.12844100595 + 0.20631399751 -0.085458002985 0.09766100347 0.18626199663 -0.077151998878 0.074046999216 + 0.16571100056 -0.068640001118 0.054531000555 0.14481200278 -0.059983000159 0.038090001792 + 0.12341400236 -0.051120001823 0.025746000931 0.1015169993 -0.04205000028 0.017500000075 + 0.096247002482 -0.019145000726 0 0.12404599786 -0.024674000219 0.0069989999756 + 0.15123200417 -0.030082000419 0.019021999091 0.17780399323 -0.035367000848 0.036068998277 + 0.204629004 -0.040702998638 0.058177001774 0.23084099591 -0.045917000622 0.085308998823 + 0.25383800268 -0.050491001457 0.11735200137 0.2727510035 -0.054253000766 0.15426999331 + 0.28844800591 -0.05737600103 0.19609899819 0.30092999339 -0.059859000146 0.24284000695 + 0.30621999502 -0.060910999775 0.25372600555 0.30376899242 -0.060423001647 0.26173099875 + 0.29357799888 -0.058396000415 0.26685500145 0.27649500966 -0.054997999221 0.21355000138 + 0.25840198994 -0.051398999989 0.16741199791 0.23929700255 -0.047598998994 0.12844100595 + 0.21902100742 -0.043565999717 0.09766100347 0.19773499668 -0.039331998676 0.074046999216 + 0.17591799796 -0.034991998225 0.054531000555 0.15373200178 -0.030579000711 0.038090001792 + 0.13101600111 -0.026061000302 0.025746000931 0.10777000338 -0.021437000483 0.017500000075 + 0.098132997751 0 0 0.1264770031 0 0.0069989999756 + 0.15419499576 0 0.019021999091 0.18128700554 0 0.036068998277 + 0.20863799751 0 0.058177001774 0.23536400497 0 0.085308998823 + 0.25881099701 0 0.11735200137 0.27809399366 0 0.15426999331 + 0.29409998655 0 0.19609899819 0.30682599545 0 0.24284000695 + 0.3122189939 0 0.25372600555 0.30972000957 0 0.26173099875 + 0.29932999611 0 0.26685500145 0.28191199899 0 0.21355000138 + 0.2634640038 0 0.16741199791 0.24398499727 0 0.12844100595 + 0.2233120054 0 0.09766100347 0.20160800219 0 0.074046999216 + 0.17936399579 0 0.054531000555 0.1567440033 0 0.038090001792 + 0.13358299434 0 0.025746000931 0.10988099873 0 0.017500000075 + 0.09624800086 0.019145000726 0 0.12404599786 0.024674000219 0.0069989999756 + 0.15123200417 0.030082000419 0.019021999091 0.17780399323 0.035367000848 0.036068998277 + 0.204629004 0.040702998638 0.058177001774 0.23084099591 0.045917000622 0.085308998823 + 0.25383800268 0.050491999835 0.11735200137 0.2727510035 0.054253999144 0.15426999331 + 0.28844800591 0.05737600103 0.19609899819 0.30092999339 0.059859000146 0.24284000695 + 0.30621999502 0.060910999775 0.25372600555 0.30376899242 0.060424000025 0.26173099875 + 0.29357799888 0.058396000415 0.26685500145 0.27649500966 0.054997999221 0.21355000138 + 0.25840198994 0.051398999989 0.16741199791 0.23929700255 0.047598998994 0.12844100595 + 0.21902100742 0.043565999717 0.09766100347 0.19773499668 0.039331998676 0.074046999216 + 0.17591799796 0.034991998225 0.054531000555 0.15373200178 0.030579000711 0.038090001792 + 0.13101600111 0.026061000302 0.025746000931 0.10777000338 0.021437000483 0.017500000075 + 0.090663000941 0.037553999573 0 0.11684899777 0.048401001841 0.0069989999756 + 0.14245699346 0.059007998556 0.019021999091 0.16748699546 0.069375999272 0.036068998277 + 0.19275699556 0.0798420012 0.058177001774 0.21744799614 0.090070001781 0.085308998823 + 0.23910999298 0.099042996764 0.11735200137 0.25692600012 0.10642199963 0.15426999331 + 0.27171200514 0.11254700273 0.19609899819 0.2834700048 0.11741700023 0.24284000695 + 0.28845199943 0.11948099732 0.25372600555 0.28614398837 0.11852499843 0.26173099875 + 0.27654498816 0.11454900354 0.26685500145 0.26045298576 0.10788299888 0.21355000138 + 0.24340899289 0.10082300007 0.16741199791 0.22541299462 0.09336899966 0.12844100595 + 0.20631399751 0.085458002985 0.09766100347 0.18626199663 0.077151998878 0.074046999216 + 0.16571100056 0.068640001118 0.054531000555 0.14481200278 0.059983000159 0.038090001792 + 0.12341400236 0.051120001823 0.025746000931 0.1015169993 0.04205000028 0.017500000075 + 0.081595003605 0.054519999772 0 0.10516099632 0.070266999304 0.0069989999756 + 0.12820799649 0.085666000843 0.019021999091 0.15073500574 0.10071799904 0.036068998277 + 0.17347599566 0.11591300368 0.058177001774 0.19569799304 0.13076099753 0.085308998823 + 0.21519300342 0.14378799498 0.11735200137 0.23122699559 0.15450100601 0.15426999331 + 0.24453499913 0.16339300573 0.19609899819 0.25511598587 0.17046299577 0.24284000695 + 0.25960001349 0.17346000671 0.25372600555 0.25752300024 0.17207099497 0.26173099875 + 0.24888299406 0.16629900038 0.26685500145 0.23440100253 0.15662199259 0.21355000138 + 0.21906200051 0.14637300372 0.16741199791 0.20286600292 0.1355510056 0.12844100595 + 0.18567700684 0.12406600267 0.09766100347 0.16763100028 0.11200799793 0.074046999216 + 0.14913600683 0.099650003016 0.054531000555 0.13032799959 0.087081998587 0.038090001792 + 0.11106999964 0.074215002358 0.025746000931 0.09136299789 0.061046998948 0.017500000075 + 0.069390997291 0.069390997291 0 0.089432001114 0.089432001114 0.0069989999756 + 0.10903199762 0.10903199762 0.019021999091 0.12818899751 0.12818899751 0.036068998277 + 0.147529006 0.147529006 0.058177001774 0.16642700136 0.16642700136 0.085308998823 + 0.18300700188 0.18300700188 0.11735200137 0.1966419965 0.19664299488 0.15426999331 + 0.20795999467 0.20795999467 0.19609899819 0.21695800126 0.21695899963 0.24284000695 + 0.22077199817 0.22077199817 0.25372600555 0.21900500357 0.21900500357 0.26173099875 + 0.21165800095 0.21165800095 0.26685500145 0.1993419975 0.1993419975 0.21355000138 + 0.18629699945 0.18629699945 0.16741199791 0.17252400517 0.17252400517 0.12844100595 + 0.15790599585 0.15790599585 0.09766100347 0.14255900681 0.14255900681 0.074046999216 + 0.12682999671 0.12682999671 0.054531000555 0.11083400249 0.11083400249 0.038090001792 + 0.094457000494 0.094457000494 0.025746000931 0.077697999775 0.077697999775 0.017500000075 + 0.054519999772 0.081595003605 0 0.070266999304 0.10516099632 0.0069989999756 + 0.085666000843 0.12820799649 0.019021999091 0.10071799904 0.15073500574 0.036068998277 + 0.11591300368 0.17347599566 0.058177001774 0.13076099753 0.19569799304 0.085308998823 + 0.1437869966 0.21519300342 0.11735200137 0.15450100601 0.23122699559 0.15426999331 + 0.16339300573 0.24453499913 0.19609899819 0.17046299577 0.25511598587 0.24284000695 + 0.17345899343 0.25960001349 0.25372600555 0.17207099497 0.25752300024 0.26173099875 + 0.16629900038 0.24888400733 0.26685500145 0.15662199259 0.2344020009 0.21355000138 + 0.14637300372 0.21906299889 0.16741199791 0.1355510056 0.20286600292 0.12844100595 + 0.12406600267 0.18567700684 0.09766100347 0.11200799793 0.16763100028 0.074046999216 + 0.099648997188 0.14913600683 0.054531000555 0.087081998587 0.13032799959 0.038090001792 + 0.07421399653 0.11106999964 0.025746000931 0.061046998948 0.09136299789 0.017500000075 + 0.037553999573 0.090663000941 0 0.048399999738 0.11684899777 0.0069989999756 + 0.059007998556 0.14245699346 0.019021999091 0.069375000894 0.16748699546 0.036068998277 + 0.0798420012 0.19275699556 0.058177001774 0.090070001781 0.21744799614 0.085308998823 + 0.099041998386 0.23910999298 0.11735200137 0.10642199963 0.25692600012 0.15426999331 + 0.11254700273 0.27171298862 0.19609899819 0.11741700023 0.2834700048 0.24284000695 + 0.11948099732 0.2884530127 0.25372600555 0.11852499843 0.28614398837 0.26173099875 + 0.11454799771 0.27654498816 0.26685500145 0.10788299888 0.26045298576 0.21355000138 + 0.10082300007 0.24340899289 0.16741199791 0.09336899966 0.22541299462 0.12844100595 + 0.085458002985 0.20631399751 0.09766100347 0.077151998878 0.18626199663 0.074046999216 + 0.068640001118 0.16571100056 0.054531000555 0.059983000159 0.14481200278 0.038090001792 + 0.051120001823 0.12341400236 0.025746000931 0.04205000028 0.1015169993 0.017500000075 + 0.019145000726 0.096247002482 0 0.024674000219 0.12404599786 0.0069989999756 + 0.030082000419 0.15123200417 0.019021999091 0.035367000848 0.17780399323 0.036068998277 + 0.040702998638 0.204629004 0.058177001774 0.045917000622 0.23084099591 0.085308998823 + 0.050491001457 0.25383800268 0.11735200137 0.054253999144 0.2727510035 0.15426999331 + 0.05737600103 0.28844800591 0.19609899819 0.059859000146 0.30092999339 0.24284000695 + 0.060910999775 0.30621999502 0.25372600555 0.060423001647 0.30376899242 0.26173099875 + 0.058396000415 0.29357799888 0.26685500145 0.054997999221 0.27649500966 0.21355000138 + 0.051398999989 0.25840198994 0.16741199791 0.047598998994 0.23929700255 0.12844100595 + 0.043565999717 0.21902100742 0.09766100347 0.039331998676 0.19773499668 0.074046999216 + 0.034991998225 0.17591799796 0.054531000555 0.030579000711 0.15373200178 0.038090001792 + 0.026061000302 0.13101600111 0.025746000931 0.021437000483 0.10777000338 0.017500000075 + 0 0.098132997751 0 -0 0.1264770031 0.0069989999756 + -0 0.15419499576 0.019021999091 -0 0.18128700554 0.036068998277 + -0 0.20863799751 0.058177001774 -0 0.23536400497 0.085308998823 + -0 0.25881099701 0.11735200137 -0 0.27809500694 0.15426999331 + -0 0.29409900308 0.19609899819 -0 0.30682599545 0.24284000695 + -0 0.3122189939 0.25372600555 -0 0.30972000957 0.26173099875 + -0 0.29932999611 0.26685500145 -0 0.28191199899 0.21355000138 + -0 0.2634640038 0.16741199791 -0 0.24398499727 0.12844100595 + -0 0.2233120054 0.09766100347 -0 0.20160800219 0.074046999216 + -0 0.17936399579 0.054531000555 -0 0.1567440033 0.038090001792 + -0 0.13358299434 0.025746000931 -0 0.10988099873 0.017500000075 + -0.019145000726 0.096247002482 0 -0.024674000219 0.12404599786 0.0069989999756 + -0.030082000419 0.15123200417 0.019021999091 -0.035367000848 0.17780399323 0.036068998277 + -0.040702998638 0.204629004 0.058177001774 -0.045917000622 0.23084099591 0.085308998823 + -0.050491999835 0.25383800268 0.11735200137 -0.054253999144 0.2727510035 0.15426999331 + -0.05737600103 0.28844800591 0.19609899819 -0.059859000146 0.30092999339 0.24284000695 + -0.060910999775 0.30621999502 0.25372600555 -0.060423001647 0.30376899242 0.26173099875 + -0.058396000415 0.29357799888 0.26685500145 -0.054997999221 0.27649500966 0.21355000138 + -0.051398999989 0.25840198994 0.16741199791 -0.047598998994 0.23929700255 0.12844100595 + -0.043565999717 0.21902100742 0.09766100347 -0.039331998676 0.19773499668 0.074046999216 + -0.034991998225 0.17591799796 0.054531000555 -0.030579000711 0.15373200178 0.038090001792 + -0.026061000302 0.13101600111 0.025746000931 -0.021437000483 0.10777000338 0.017500000075 + -0.037553999573 0.090663000941 0 -0.048401001841 0.11684899777 0.0069989999756 + -0.059007998556 0.14245699346 0.019021999091 -0.069375999272 0.16748699546 0.036068998277 + -0.0798420012 0.19275599718 0.058177001774 -0.090070001781 0.21744799614 0.085308998823 + -0.099042996764 0.23910999298 0.11735200137 -0.10642199963 0.25692600012 0.15426999331 + -0.11254700273 0.27171200514 0.19609899819 -0.11741700023 0.2834700048 0.24284000695 + -0.11948099732 0.28845199943 0.25372600555 -0.11852499843 0.28614398837 0.26173099875 + -0.11454900354 0.27654498816 0.26685500145 -0.10788299888 0.26045298576 0.21355000138 + -0.10082300007 0.24340899289 0.16741199791 -0.09336899966 0.22541299462 0.12844100595 + -0.085458002985 0.20631399751 0.09766100347 -0.077151998878 0.18626199663 0.074046999216 + -0.068640001118 0.16571100056 0.054531000555 -0.059983000159 0.14481200278 0.038090001792 + -0.051120001823 0.12341400236 0.025746000931 -0.04205000028 0.1015169993 0.017500000075 + -0.054519999772 0.081595003605 0 -0.070266999304 0.10516099632 0.0069989999756 + -0.085666000843 0.12820799649 0.019021999091 -0.10071799904 0.15073500574 0.036068998277 + -0.11591300368 0.17347599566 0.058177001774 -0.13076099753 0.19569799304 0.085308998823 + -0.14378799498 0.21519300342 0.11735200137 -0.15450100601 0.23122699559 0.15426999331 + -0.16339300573 0.24453499913 0.19609899819 -0.17046299577 0.25511598587 0.24284000695 + -0.17346000671 0.25960001349 0.25372600555 -0.17207099497 0.25752300024 0.26173099875 + -0.16629900038 0.24888299406 0.26685500145 -0.15662199259 0.23440100253 0.21355000138 + -0.14637300372 0.21906200051 0.16741199791 -0.1355510056 0.20286600292 0.12844100595 + -0.12406600267 0.18567700684 0.09766100347 -0.11200799793 0.16763100028 0.074046999216 + -0.099650003016 0.14913600683 0.054531000555 -0.087081998587 0.13032700121 0.038090001792 + -0.074215002358 0.11106999964 0.025746000931 -0.061046998948 0.09136299789 0.017500000075 + -0.069390997291 0.069390997291 0 -0.089432001114 0.089432001114 0.0069989999756 + -0.10903199762 0.10903199762 0.019021999091 -0.12818899751 0.12818899751 0.036068998277 + -0.14753000438 0.147529006 0.058177001774 -0.16642700136 0.16642700136 0.085308998823 + -0.18300700188 0.18300700188 0.11735200137 -0.19664299488 0.1966419965 0.15426999331 + -0.20795999467 0.20795999467 0.19609899819 -0.21695899963 0.21695800126 0.24284000695 + -0.22077199817 0.22077199817 0.25372600555 -0.21900500357 0.21900500357 0.26173099875 + -0.21165800095 0.21165800095 0.26685500145 -0.1993419975 0.1993419975 0.21355000138 + -0.18629699945 0.18629699945 0.16741199791 -0.17252400517 0.17252400517 0.12844100595 + -0.15790599585 0.15790499747 0.09766100347 -0.14255900681 0.14255900681 0.074046999216 + -0.12682999671 0.12682999671 0.054531000555 -0.11083400249 0.11083400249 0.038090001792 + -0.094457000494 0.094457000494 0.025746000931 -0.077697999775 0.077697999775 0.017500000075 + -0.081595003605 0.054519999772 0 -0.10516099632 0.070266999304 0.0069989999756 + -0.12820799649 0.085666000843 0.019021999091 -0.15073500574 0.10071799904 0.036068998277 + -0.17347599566 0.11591300368 0.058177001774 -0.19569799304 0.13076099753 0.085308998823 + -0.21519300342 0.14378799498 0.11735200137 -0.23122699559 0.15450100601 0.15426999331 + -0.24453499913 0.16339300573 0.19609899819 -0.25511598587 0.17046299577 0.24284000695 + -0.25960001349 0.17345899343 0.25372600555 -0.25752300024 0.17207099497 0.26173099875 + -0.24888400733 0.16629900038 0.26685500145 -0.2344020009 0.15662199259 0.21355000138 + -0.21906200051 0.14637300372 0.16741199791 -0.20286600292 0.1355510056 0.12844100595 + -0.18567700684 0.12406600267 0.09766100347 -0.16763100028 0.11200799793 0.074046999216 + -0.14913600683 0.099648997188 0.054531000555 -0.13032700121 0.087081998587 0.038090001792 + -0.11106999964 0.07421399653 0.025746000931 -0.09136299789 0.061046998948 0.017500000075 + -0.090663000941 0.037553999573 0 -0.11684899777 0.048399999738 0.0069989999756 + -0.14245699346 0.059007998556 0.019021999091 -0.16748699546 0.069375000894 0.036068998277 + -0.19275699556 0.0798420012 0.058177001774 -0.21744799614 0.090070001781 0.085308998823 + -0.23910999298 0.099042996764 0.11735200137 -0.25692600012 0.10642199963 0.15426999331 + -0.27171298862 0.11254700273 0.19609899819 -0.2834700048 0.11741700023 0.24284000695 + -0.2884530127 0.11948099732 0.25372600555 -0.28614398837 0.11852499843 0.26173099875 + -0.27654498816 0.11454799771 0.26685500145 -0.26045298576 0.10788299888 0.21355000138 + -0.24340899289 0.10082300007 0.16741199791 -0.22541299462 0.09336899966 0.12844100595 + -0.20631399751 0.085458002985 0.09766100347 -0.18626199663 0.077151998878 0.074046999216 + -0.16571100056 0.068640001118 0.054531000555 -0.14481200278 0.059983000159 0.038090001792 + -0.12341400236 0.051120001823 0.025746000931 -0.1015169993 0.04205000028 0.017500000075 + 0 -0 0 -0.096247002482 0.019145000726 0 + -0.12404599786 0.024674000219 0.0069989999756 -0.15123200417 0.030082000419 0.019021999091 + -0.17780399323 0.035367000848 0.036068998277 -0.204629004 0.040702998638 0.058177001774 + -0.23084099591 0.045917000622 0.085308998823 -0.25383800268 0.050491001457 0.11735200137 + -0.2727510035 0.054253000766 0.15426999331 -0.28844800591 0.05737600103 0.19609899819 + -0.30092999339 0.059859000146 0.24284000695 -0.30621999502 0.060910999775 0.25372600555 + -0.30376899242 0.060423001647 0.26173099875 -0.29357799888 0.058396000415 0.26685500145 + -0.27649500966 0.054997999221 0.21355000138 -0.25840198994 0.051398999989 0.16741199791 + -0.23929700255 0.047598998994 0.12844100595 -0.21902100742 0.043565999717 0.09766100347 + -0.19773499668 0.039331998676 0.074046999216 -0.17591799796 0.034991998225 0.054531000555 + -0.15373200178 0.030579000711 0.038090001792 -0.13101600111 0.026061000302 0.025746000931 + -0.10777000338 0.021437000483 0.017500000075 0 -0 0.017500000075 + + + + + + + + + + + + + + + + + + + + + + + 682 22 0 23 1 0 + 0 22 23 24 2 1 + 1 23 24 25 3 2 + 2 24 25 26 4 3 + 3 25 26 27 5 4 + 4 26 27 28 6 5 + 5 27 28 29 7 6 + 6 28 29 30 8 7 + 7 29 30 31 9 8 + 8 30 31 9 31 32 + 32 10 9 10 32 33 + 33 11 10 11 33 34 + 34 12 11 35 13 12 + 12 34 35 36 14 13 + 13 35 36 37 15 14 + 14 36 37 38 16 15 + 15 37 38 39 17 16 + 16 38 39 40 18 17 + 17 39 40 41 19 18 + 18 40 41 42 20 19 + 19 41 42 43 21 20 + 20 42 43 21 43 705 + 682 44 22 45 23 22 + 22 44 45 46 24 23 + 23 45 46 47 25 24 + 24 46 47 48 26 25 + 25 47 48 49 27 26 + 26 48 49 50 28 27 + 27 49 50 51 29 28 + 28 50 51 52 30 29 + 29 51 52 53 31 30 + 30 52 53 31 53 54 + 54 32 31 32 54 55 + 55 33 32 33 55 56 + 56 34 33 57 35 34 + 34 56 57 58 36 35 + 35 57 58 59 37 36 + 36 58 59 60 38 37 + 37 59 60 61 39 38 + 38 60 61 62 40 39 + 39 61 62 63 41 40 + 40 62 63 64 42 41 + 41 63 64 65 43 42 + 42 64 65 43 65 705 + 682 66 44 67 45 44 + 44 66 67 68 46 45 + 45 67 68 69 47 46 + 46 68 69 70 48 47 + 47 69 70 71 49 48 + 48 70 71 72 50 49 + 49 71 72 73 51 50 + 50 72 73 74 52 51 + 51 73 74 75 53 52 + 52 74 75 53 75 76 + 76 54 53 54 76 77 + 77 55 54 55 77 78 + 78 56 55 79 57 56 + 56 78 79 80 58 57 + 57 79 80 81 59 58 + 58 80 81 82 60 59 + 59 81 82 83 61 60 + 60 82 83 84 62 61 + 61 83 84 85 63 62 + 62 84 85 86 64 63 + 63 85 86 87 65 64 + 64 86 87 65 87 705 + 682 88 66 89 67 66 + 66 88 89 90 68 67 + 67 89 90 91 69 68 + 68 90 91 92 70 69 + 69 91 92 93 71 70 + 70 92 93 94 72 71 + 71 93 94 95 73 72 + 72 94 95 96 74 73 + 73 95 96 97 75 74 + 74 96 97 75 97 98 + 98 76 75 76 98 99 + 99 77 76 77 99 100 + 100 78 77 101 79 78 + 78 100 101 102 80 79 + 79 101 102 103 81 80 + 80 102 103 104 82 81 + 81 103 104 105 83 82 + 82 104 105 106 84 83 + 83 105 106 107 85 84 + 84 106 107 108 86 85 + 85 107 108 109 87 86 + 86 108 109 87 109 705 + 682 110 88 111 89 88 + 88 110 111 112 90 89 + 89 111 112 113 91 90 + 90 112 113 114 92 91 + 91 113 114 115 93 92 + 92 114 115 116 94 93 + 93 115 116 117 95 94 + 94 116 117 118 96 95 + 95 117 118 119 97 96 + 96 118 119 97 119 120 + 120 98 97 98 120 121 + 121 99 98 99 121 122 + 122 100 99 123 101 100 + 100 122 123 124 102 101 + 101 123 124 125 103 102 + 102 124 125 126 104 103 + 103 125 126 127 105 104 + 104 126 127 128 106 105 + 105 127 128 129 107 106 + 106 128 129 130 108 107 + 107 129 130 131 109 108 + 108 130 131 109 131 705 + 682 132 110 133 111 110 + 110 132 133 134 112 111 + 111 133 134 135 113 112 + 112 134 135 136 114 113 + 113 135 136 137 115 114 + 114 136 137 138 116 115 + 115 137 138 139 117 116 + 116 138 139 140 118 117 + 117 139 140 141 119 118 + 118 140 141 119 141 142 + 142 120 119 120 142 143 + 143 121 120 121 143 144 + 144 122 121 145 123 122 + 122 144 145 146 124 123 + 123 145 146 147 125 124 + 124 146 147 148 126 125 + 125 147 148 149 127 126 + 126 148 149 150 128 127 + 127 149 150 151 129 128 + 128 150 151 152 130 129 + 129 151 152 153 131 130 + 130 152 153 131 153 705 + 682 154 132 155 133 132 + 132 154 155 156 134 133 + 133 155 156 157 135 134 + 134 156 157 158 136 135 + 135 157 158 159 137 136 + 136 158 159 160 138 137 + 137 159 160 161 139 138 + 138 160 161 162 140 139 + 139 161 162 163 141 140 + 140 162 163 141 163 164 + 164 142 141 142 164 165 + 165 143 142 143 165 166 + 166 144 143 167 145 144 + 144 166 167 168 146 145 + 145 167 168 169 147 146 + 146 168 169 170 148 147 + 147 169 170 171 149 148 + 148 170 171 172 150 149 + 149 171 172 173 151 150 + 150 172 173 174 152 151 + 151 173 174 175 153 152 + 152 174 175 153 175 705 + 682 176 154 177 155 154 + 154 176 177 178 156 155 + 155 177 178 179 157 156 + 156 178 179 180 158 157 + 157 179 180 181 159 158 + 158 180 181 182 160 159 + 159 181 182 183 161 160 + 160 182 183 184 162 161 + 161 183 184 185 163 162 + 162 184 185 163 185 186 + 186 164 163 164 186 187 + 187 165 164 165 187 188 + 188 166 165 189 167 166 + 166 188 189 190 168 167 + 167 189 190 191 169 168 + 168 190 191 192 170 169 + 169 191 192 193 171 170 + 170 192 193 194 172 171 + 171 193 194 195 173 172 + 172 194 195 196 174 173 + 173 195 196 197 175 174 + 174 196 197 175 197 705 + 682 198 176 199 177 176 + 176 198 199 200 178 177 + 177 199 200 201 179 178 + 178 200 201 202 180 179 + 179 201 202 203 181 180 + 180 202 203 204 182 181 + 181 203 204 205 183 182 + 182 204 205 206 184 183 + 183 205 206 207 185 184 + 184 206 207 185 207 208 + 208 186 185 186 208 209 + 209 187 186 187 209 210 + 210 188 187 211 189 188 + 188 210 211 212 190 189 + 189 211 212 213 191 190 + 190 212 213 214 192 191 + 191 213 214 215 193 192 + 192 214 215 216 194 193 + 193 215 216 217 195 194 + 194 216 217 218 196 195 + 195 217 218 219 197 196 + 196 218 219 197 219 705 + 682 220 198 221 199 198 + 198 220 221 222 200 199 + 199 221 222 223 201 200 + 200 222 223 224 202 201 + 201 223 224 225 203 202 + 202 224 225 226 204 203 + 203 225 226 227 205 204 + 204 226 227 228 206 205 + 205 227 228 229 207 206 + 206 228 229 207 229 230 + 230 208 207 208 230 231 + 231 209 208 209 231 232 + 232 210 209 233 211 210 + 210 232 233 234 212 211 + 211 233 234 235 213 212 + 212 234 235 236 214 213 + 213 235 236 237 215 214 + 214 236 237 238 216 215 + 215 237 238 239 217 216 + 216 238 239 240 218 217 + 217 239 240 241 219 218 + 218 240 241 219 241 705 + 682 242 220 243 221 220 + 220 242 243 244 222 221 + 221 243 244 245 223 222 + 222 244 245 246 224 223 + 223 245 246 247 225 224 + 224 246 247 248 226 225 + 225 247 248 249 227 226 + 226 248 249 250 228 227 + 227 249 250 251 229 228 + 228 250 251 229 251 252 + 252 230 229 230 252 253 + 253 231 230 231 253 254 + 254 232 231 255 233 232 + 232 254 255 256 234 233 + 233 255 256 257 235 234 + 234 256 257 258 236 235 + 235 257 258 259 237 236 + 236 258 259 260 238 237 + 237 259 260 261 239 238 + 238 260 261 262 240 239 + 239 261 262 263 241 240 + 240 262 263 241 263 705 + 682 264 242 265 243 242 + 242 264 265 266 244 243 + 243 265 266 267 245 244 + 244 266 267 268 246 245 + 245 267 268 269 247 246 + 246 268 269 270 248 247 + 247 269 270 271 249 248 + 248 270 271 272 250 249 + 249 271 272 273 251 250 + 250 272 273 251 273 274 + 274 252 251 252 274 275 + 275 253 252 253 275 276 + 276 254 253 277 255 254 + 254 276 277 278 256 255 + 255 277 278 279 257 256 + 256 278 279 280 258 257 + 257 279 280 281 259 258 + 258 280 281 282 260 259 + 259 281 282 283 261 260 + 260 282 283 284 262 261 + 261 283 284 285 263 262 + 262 284 285 263 285 705 + 682 286 264 287 265 264 + 264 286 287 288 266 265 + 265 287 288 289 267 266 + 266 288 289 290 268 267 + 267 289 290 291 269 268 + 268 290 291 292 270 269 + 269 291 292 293 271 270 + 270 292 293 294 272 271 + 271 293 294 295 273 272 + 272 294 295 273 295 296 + 296 274 273 274 296 297 + 297 275 274 275 297 298 + 298 276 275 299 277 276 + 276 298 299 300 278 277 + 277 299 300 301 279 278 + 278 300 301 302 280 279 + 279 301 302 303 281 280 + 280 302 303 304 282 281 + 281 303 304 305 283 282 + 282 304 305 306 284 283 + 283 305 306 307 285 284 + 284 306 307 285 307 705 + 682 308 286 309 287 286 + 286 308 309 310 288 287 + 287 309 310 311 289 288 + 288 310 311 312 290 289 + 289 311 312 313 291 290 + 290 312 313 314 292 291 + 291 313 314 315 293 292 + 292 314 315 316 294 293 + 293 315 316 317 295 294 + 294 316 317 295 317 318 + 318 296 295 296 318 319 + 319 297 296 297 319 320 + 320 298 297 321 299 298 + 298 320 321 322 300 299 + 299 321 322 323 301 300 + 300 322 323 324 302 301 + 301 323 324 325 303 302 + 302 324 325 326 304 303 + 303 325 326 327 305 304 + 304 326 327 328 306 305 + 305 327 328 329 307 306 + 306 328 329 307 329 705 + 682 330 308 331 309 308 + 308 330 331 332 310 309 + 309 331 332 333 311 310 + 310 332 333 334 312 311 + 311 333 334 335 313 312 + 312 334 335 336 314 313 + 313 335 336 337 315 314 + 314 336 337 338 316 315 + 315 337 338 339 317 316 + 316 338 339 317 339 340 + 340 318 317 318 340 341 + 341 319 318 319 341 342 + 342 320 319 343 321 320 + 320 342 343 344 322 321 + 321 343 344 345 323 322 + 322 344 345 346 324 323 + 323 345 346 347 325 324 + 324 346 347 348 326 325 + 325 347 348 349 327 326 + 326 348 349 350 328 327 + 327 349 350 351 329 328 + 328 350 351 329 351 705 + 682 352 330 353 331 330 + 330 352 353 354 332 331 + 331 353 354 355 333 332 + 332 354 355 356 334 333 + 333 355 356 357 335 334 + 334 356 357 358 336 335 + 335 357 358 359 337 336 + 336 358 359 360 338 337 + 337 359 360 361 339 338 + 338 360 361 339 361 362 + 362 340 339 340 362 363 + 363 341 340 341 363 364 + 364 342 341 365 343 342 + 342 364 365 366 344 343 + 343 365 366 367 345 344 + 344 366 367 368 346 345 + 345 367 368 369 347 346 + 346 368 369 370 348 347 + 347 369 370 371 349 348 + 348 370 371 372 350 349 + 349 371 372 373 351 350 + 350 372 373 351 373 705 + 682 374 352 375 353 352 + 352 374 375 376 354 353 + 353 375 376 377 355 354 + 354 376 377 378 356 355 + 355 377 378 379 357 356 + 356 378 379 380 358 357 + 357 379 380 381 359 358 + 358 380 381 382 360 359 + 359 381 382 383 361 360 + 360 382 383 361 383 384 + 384 362 361 362 384 385 + 385 363 362 363 385 386 + 386 364 363 387 365 364 + 364 386 387 388 366 365 + 365 387 388 389 367 366 + 366 388 389 390 368 367 + 367 389 390 391 369 368 + 368 390 391 392 370 369 + 369 391 392 393 371 370 + 370 392 393 394 372 371 + 371 393 394 395 373 372 + 372 394 395 373 395 705 + 682 396 374 397 375 374 + 374 396 397 398 376 375 + 375 397 398 399 377 376 + 376 398 399 400 378 377 + 377 399 400 401 379 378 + 378 400 401 402 380 379 + 379 401 402 403 381 380 + 380 402 403 404 382 381 + 381 403 404 405 383 382 + 382 404 405 383 405 406 + 406 384 383 384 406 407 + 407 385 384 385 407 408 + 408 386 385 409 387 386 + 386 408 409 410 388 387 + 387 409 410 411 389 388 + 388 410 411 412 390 389 + 389 411 412 413 391 390 + 390 412 413 414 392 391 + 391 413 414 415 393 392 + 392 414 415 416 394 393 + 393 415 416 417 395 394 + 394 416 417 395 417 705 + 682 418 396 419 397 396 + 396 418 419 420 398 397 + 397 419 420 421 399 398 + 398 420 421 422 400 399 + 399 421 422 423 401 400 + 400 422 423 424 402 401 + 401 423 424 425 403 402 + 402 424 425 426 404 403 + 403 425 426 427 405 404 + 404 426 427 405 427 428 + 428 406 405 406 428 429 + 429 407 406 407 429 430 + 430 408 407 431 409 408 + 408 430 431 432 410 409 + 409 431 432 433 411 410 + 410 432 433 434 412 411 + 411 433 434 435 413 412 + 412 434 435 436 414 413 + 413 435 436 437 415 414 + 414 436 437 438 416 415 + 415 437 438 439 417 416 + 416 438 439 417 439 705 + 682 440 418 441 419 418 + 418 440 441 442 420 419 + 419 441 442 443 421 420 + 420 442 443 444 422 421 + 421 443 444 445 423 422 + 422 444 445 446 424 423 + 423 445 446 447 425 424 + 424 446 447 448 426 425 + 425 447 448 449 427 426 + 426 448 449 427 449 450 + 450 428 427 428 450 451 + 451 429 428 429 451 452 + 452 430 429 453 431 430 + 430 452 453 454 432 431 + 431 453 454 455 433 432 + 432 454 455 456 434 433 + 433 455 456 457 435 434 + 434 456 457 458 436 435 + 435 457 458 459 437 436 + 436 458 459 460 438 437 + 437 459 460 461 439 438 + 438 460 461 439 461 705 + 682 462 440 463 441 440 + 440 462 463 464 442 441 + 441 463 464 465 443 442 + 442 464 465 466 444 443 + 443 465 466 467 445 444 + 444 466 467 468 446 445 + 445 467 468 469 447 446 + 446 468 469 470 448 447 + 447 469 470 471 449 448 + 448 470 471 449 471 472 + 472 450 449 450 472 473 + 473 451 450 451 473 474 + 474 452 451 475 453 452 + 452 474 475 476 454 453 + 453 475 476 477 455 454 + 454 476 477 478 456 455 + 455 477 478 479 457 456 + 456 478 479 480 458 457 + 457 479 480 481 459 458 + 458 480 481 482 460 459 + 459 481 482 483 461 460 + 460 482 483 461 483 705 + 682 484 462 485 463 462 + 462 484 485 486 464 463 + 463 485 486 487 465 464 + 464 486 487 488 466 465 + 465 487 488 489 467 466 + 466 488 489 490 468 467 + 467 489 490 491 469 468 + 468 490 491 492 470 469 + 469 491 492 493 471 470 + 470 492 493 471 493 494 + 494 472 471 472 494 495 + 495 473 472 473 495 496 + 496 474 473 497 475 474 + 474 496 497 498 476 475 + 475 497 498 499 477 476 + 476 498 499 500 478 477 + 477 499 500 501 479 478 + 478 500 501 502 480 479 + 479 501 502 503 481 480 + 480 502 503 504 482 481 + 481 503 504 505 483 482 + 482 504 505 483 505 705 + 682 506 484 507 485 484 + 484 506 507 508 486 485 + 485 507 508 509 487 486 + 486 508 509 510 488 487 + 487 509 510 511 489 488 + 488 510 511 512 490 489 + 489 511 512 513 491 490 + 490 512 513 514 492 491 + 491 513 514 515 493 492 + 492 514 515 493 515 516 + 516 494 493 494 516 517 + 517 495 494 495 517 518 + 518 496 495 519 497 496 + 496 518 519 520 498 497 + 497 519 520 521 499 498 + 498 520 521 522 500 499 + 499 521 522 523 501 500 + 500 522 523 524 502 501 + 501 523 524 525 503 502 + 502 524 525 526 504 503 + 503 525 526 527 505 504 + 504 526 527 505 527 705 + 682 528 506 529 507 506 + 506 528 529 530 508 507 + 507 529 530 531 509 508 + 508 530 531 532 510 509 + 509 531 532 533 511 510 + 510 532 533 534 512 511 + 511 533 534 535 513 512 + 512 534 535 536 514 513 + 513 535 536 537 515 514 + 514 536 537 515 537 538 + 538 516 515 516 538 539 + 539 517 516 517 539 540 + 540 518 517 541 519 518 + 518 540 541 542 520 519 + 519 541 542 543 521 520 + 520 542 543 544 522 521 + 521 543 544 545 523 522 + 522 544 545 546 524 523 + 523 545 546 547 525 524 + 524 546 547 548 526 525 + 525 547 548 549 527 526 + 526 548 549 527 549 705 + 682 550 528 551 529 528 + 528 550 551 552 530 529 + 529 551 552 553 531 530 + 530 552 553 554 532 531 + 531 553 554 555 533 532 + 532 554 555 556 534 533 + 533 555 556 557 535 534 + 534 556 557 558 536 535 + 535 557 558 559 537 536 + 536 558 559 537 559 560 + 560 538 537 538 560 561 + 561 539 538 539 561 562 + 562 540 539 563 541 540 + 540 562 563 564 542 541 + 541 563 564 565 543 542 + 542 564 565 566 544 543 + 543 565 566 567 545 544 + 544 566 567 568 546 545 + 545 567 568 569 547 546 + 546 568 569 570 548 547 + 547 569 570 571 549 548 + 548 570 571 549 571 705 + 682 572 550 573 551 550 + 550 572 573 574 552 551 + 551 573 574 575 553 552 + 552 574 575 576 554 553 + 553 575 576 577 555 554 + 554 576 577 578 556 555 + 555 577 578 579 557 556 + 556 578 579 580 558 557 + 557 579 580 581 559 558 + 558 580 581 559 581 582 + 582 560 559 560 582 583 + 583 561 560 561 583 584 + 584 562 561 585 563 562 + 562 584 585 586 564 563 + 563 585 586 587 565 564 + 564 586 587 588 566 565 + 565 587 588 589 567 566 + 566 588 589 590 568 567 + 567 589 590 591 569 568 + 568 590 591 592 570 569 + 569 591 592 593 571 570 + 570 592 593 571 593 705 + 682 594 572 595 573 572 + 572 594 595 596 574 573 + 573 595 596 597 575 574 + 574 596 597 598 576 575 + 575 597 598 599 577 576 + 576 598 599 600 578 577 + 577 599 600 601 579 578 + 578 600 601 602 580 579 + 579 601 602 603 581 580 + 580 602 603 581 603 604 + 604 582 581 582 604 605 + 605 583 582 583 605 606 + 606 584 583 607 585 584 + 584 606 607 608 586 585 + 585 607 608 609 587 586 + 586 608 609 610 588 587 + 587 609 610 611 589 588 + 588 610 611 612 590 589 + 589 611 612 613 591 590 + 590 612 613 614 592 591 + 591 613 614 615 593 592 + 592 614 615 593 615 705 + 682 616 594 617 595 594 + 594 616 617 618 596 595 + 595 617 618 619 597 596 + 596 618 619 620 598 597 + 597 619 620 621 599 598 + 598 620 621 622 600 599 + 599 621 622 623 601 600 + 600 622 623 624 602 601 + 601 623 624 625 603 602 + 602 624 625 603 625 626 + 626 604 603 604 626 627 + 627 605 604 605 627 628 + 628 606 605 629 607 606 + 606 628 629 630 608 607 + 607 629 630 631 609 608 + 608 630 631 632 610 609 + 609 631 632 633 611 610 + 610 632 633 634 612 611 + 611 633 634 635 613 612 + 612 634 635 636 614 613 + 613 635 636 637 615 614 + 614 636 637 615 637 705 + 682 638 616 639 617 616 + 616 638 639 640 618 617 + 617 639 640 641 619 618 + 618 640 641 642 620 619 + 619 641 642 643 621 620 + 620 642 643 644 622 621 + 621 643 644 645 623 622 + 622 644 645 646 624 623 + 623 645 646 647 625 624 + 624 646 647 625 647 648 + 648 626 625 626 648 649 + 649 627 626 627 649 650 + 650 628 627 651 629 628 + 628 650 651 652 630 629 + 629 651 652 653 631 630 + 630 652 653 654 632 631 + 631 653 654 655 633 632 + 632 654 655 656 634 633 + 633 655 656 657 635 634 + 634 656 657 658 636 635 + 635 657 658 659 637 636 + 636 658 659 637 659 705 + 682 660 638 661 639 638 + 638 660 661 662 640 639 + 639 661 662 663 641 640 + 640 662 663 664 642 641 + 641 663 664 665 643 642 + 642 664 665 666 644 643 + 643 665 666 667 645 644 + 644 666 667 668 646 645 + 645 667 668 669 647 646 + 646 668 669 647 669 670 + 670 648 647 648 670 671 + 671 649 648 649 671 672 + 672 650 649 673 651 650 + 650 672 673 674 652 651 + 651 673 674 675 653 652 + 652 674 675 676 654 653 + 653 675 676 677 655 654 + 654 676 677 678 656 655 + 655 677 678 679 657 656 + 656 678 679 680 658 657 + 657 679 680 681 659 658 + 658 680 681 659 681 705 + 682 683 660 684 661 660 + 660 683 684 685 662 661 + 661 684 685 686 663 662 + 662 685 686 687 664 663 + 663 686 687 688 665 664 + 664 687 688 689 666 665 + 665 688 689 690 667 666 + 666 689 690 691 668 667 + 667 690 691 692 669 668 + 668 691 692 669 692 693 + 693 670 669 670 693 694 + 694 671 670 671 694 695 + 695 672 671 696 673 672 + 672 695 696 697 674 673 + 673 696 697 698 675 674 + 674 697 698 699 676 675 + 675 698 699 700 677 676 + 676 699 700 701 678 677 + 677 700 701 702 679 678 + 678 701 702 703 680 679 + 679 702 703 704 681 680 + 680 703 704 681 704 705 + 682 0 683 1 684 683 + 683 0 1 2 685 684 + 684 1 2 3 686 685 + 685 2 3 4 687 686 + 686 3 4 5 688 687 + 687 4 5 6 689 688 + 688 5 6 7 690 689 + 689 6 7 8 691 690 + 690 7 8 9 692 691 + 691 8 9 692 9 10 + 10 693 692 693 10 11 + 11 694 693 694 11 12 + 12 695 694 13 696 695 + 695 12 13 14 697 696 + 696 13 14 15 698 697 + 697 14 15 16 699 698 + 698 15 16 17 700 699 + 699 16 17 18 701 700 + 700 17 18 19 702 701 + 701 18 19 20 703 702 + 702 19 20 21 704 703 + 703 20 21 704 21 705 + + + 3 6 9 12 15 18 + 21 24 27 30 33 36 + 39 42 45 48 51 54 + 57 60 63 66 69 72 + 75 78 81 84 87 90 + 93 96 99 102 105 108 + 111 114 117 120 123 126 + 129 132 135 138 141 144 + 147 150 153 156 159 162 + 165 168 171 174 177 180 + 183 186 189 192 195 198 + 201 204 207 210 213 216 + 219 222 225 228 231 234 + 237 240 243 246 249 252 + 255 258 261 264 267 270 + 273 276 279 282 285 288 + 291 294 297 300 303 306 + 309 312 315 318 321 324 + 327 330 333 336 339 342 + 345 348 351 354 357 360 + 363 366 369 372 375 378 + 381 384 387 390 393 396 + 399 402 405 408 411 414 + 417 420 423 426 429 432 + 435 438 441 444 447 450 + 453 456 459 462 465 468 + 471 474 477 480 483 486 + 489 492 495 498 501 504 + 507 510 513 516 519 522 + 525 528 531 534 537 540 + 543 546 549 552 555 558 + 561 564 567 570 573 576 + 579 582 585 588 591 594 + 597 600 603 606 609 612 + 615 618 621 624 627 630 + 633 636 639 642 645 648 + 651 654 657 660 663 666 + 669 672 675 678 681 684 + 687 690 693 696 699 702 + 705 708 711 714 717 720 + 723 726 729 732 735 738 + 741 744 747 750 753 756 + 759 762 765 768 771 774 + 777 780 783 786 789 792 + 795 798 801 804 807 810 + 813 816 819 822 825 828 + 831 834 837 840 843 846 + 849 852 855 858 861 864 + 867 870 873 876 879 882 + 885 888 891 894 897 900 + 903 906 909 912 915 918 + 921 924 927 930 933 936 + 939 942 945 948 951 954 + 957 960 963 966 969 972 + 975 978 981 984 987 990 + 993 996 999 1002 1005 1008 + 1011 1014 1017 1020 1023 1026 + 1029 1032 1035 1038 1041 1044 + 1047 1050 1053 1056 1059 1062 + 1065 1068 1071 1074 1077 1080 + 1083 1086 1089 1092 1095 1098 + 1101 1104 1107 1110 1113 1116 + 1119 1122 1125 1128 1131 1134 + 1137 1140 1143 1146 1149 1152 + 1155 1158 1161 1164 1167 1170 + 1173 1176 1179 1182 1185 1188 + 1191 1194 1197 1200 1203 1206 + 1209 1212 1215 1218 1221 1224 + 1227 1230 1233 1236 1239 1242 + 1245 1248 1251 1254 1257 1260 + 1263 1266 1269 1272 1275 1278 + 1281 1284 1287 1290 1293 1296 + 1299 1302 1305 1308 1311 1314 + 1317 1320 1323 1326 1329 1332 + 1335 1338 1341 1344 1347 1350 + 1353 1356 1359 1362 1365 1368 + 1371 1374 1377 1380 1383 1386 + 1389 1392 1395 1398 1401 1404 + 1407 1410 1413 1416 1419 1422 + 1425 1428 1431 1434 1437 1440 + 1443 1446 1449 1452 1455 1458 + 1461 1464 1467 1470 1473 1476 + 1479 1482 1485 1488 1491 1494 + 1497 1500 1503 1506 1509 1512 + 1515 1518 1521 1524 1527 1530 + 1533 1536 1539 1542 1545 1548 + 1551 1554 1557 1560 1563 1566 + 1569 1572 1575 1578 1581 1584 + 1587 1590 1593 1596 1599 1602 + 1605 1608 1611 1614 1617 1620 + 1623 1626 1629 1632 1635 1638 + 1641 1644 1647 1650 1653 1656 + 1659 1662 1665 1668 1671 1674 + 1677 1680 1683 1686 1689 1692 + 1695 1698 1701 1704 1707 1710 + 1713 1716 1719 1722 1725 1728 + 1731 1734 1737 1740 1743 1746 + 1749 1752 1755 1758 1761 1764 + 1767 1770 1773 1776 1779 1782 + 1785 1788 1791 1794 1797 1800 + 1803 1806 1809 1812 1815 1818 + 1821 1824 1827 1830 1833 1836 + 1839 1842 1845 1848 1851 1854 + 1857 1860 1863 1866 1869 1872 + 1875 1878 1881 1884 1887 1890 + 1893 1896 1899 1902 1905 1908 + 1911 1914 1917 1920 1923 1926 + 1929 1932 1935 1938 1941 1944 + 1947 1950 1953 1956 1959 1962 + 1965 1968 1971 1974 1977 1980 + 1983 1986 1989 1992 1995 1998 + 2001 2004 2007 2010 2013 2016 + 2019 2022 2025 2028 2031 2034 + 2037 2040 2043 2046 2049 2052 + 2055 2058 2061 2064 2067 2070 + 2073 2076 2079 2082 2085 2088 + 2091 2094 2097 2100 2103 2106 + 2109 2112 2115 2118 2121 2124 + 2127 2130 2133 2136 2139 2142 + 2145 2148 2151 2154 2157 2160 + 2163 2166 2169 2172 2175 2178 + 2181 2184 2187 2190 2193 2196 + 2199 2202 2205 2208 2211 2214 + 2217 2220 2223 2226 2229 2232 + 2235 2238 2241 2244 2247 2250 + 2253 2256 2259 2262 2265 2268 + 2271 2274 2277 2280 2283 2286 + 2289 2292 2295 2298 2301 2304 + 2307 2310 2313 2316 2319 2322 + 2325 2328 2331 2334 2337 2340 + 2343 2346 2349 2352 2355 2358 + 2361 2364 2367 2370 2373 2376 + 2379 2382 2385 2388 2391 2394 + 2397 2400 2403 2406 2409 2412 + 2415 2418 2421 2424 2427 2430 + 2433 2436 2439 2442 2445 2448 + 2451 2454 2457 2460 2463 2466 + 2469 2472 2475 2478 2481 2484 + 2487 2490 2493 2496 2499 2502 + 2505 2508 2511 2514 2517 2520 + 2523 2526 2529 2532 2535 2538 + 2541 2544 2547 2550 2553 2556 + 2559 2562 2565 2568 2571 2574 + 2577 2580 2583 2586 2589 2592 + 2595 2598 2601 2604 2607 2610 + 2613 2616 2619 2622 2625 2628 + 2631 2634 2637 2640 2643 2646 + 2649 2652 2655 2658 2661 2664 + 2667 2670 2673 2676 2679 2682 + 2685 2688 2691 2694 2697 2700 + 2703 2706 2709 2712 2715 2718 + 2721 2724 2727 2730 2733 2736 + 2739 2742 2745 2748 2751 2754 + 2757 2760 2763 2766 2769 2772 + 2775 2778 2781 2784 2787 2790 + 2793 2796 2799 2802 2805 2808 + 2811 2814 2817 2820 2823 2826 + 2829 2832 2835 2838 2841 2844 + 2847 2850 2853 2856 2859 2862 + 2865 2868 2871 2874 2877 2880 + 2883 2886 2889 2892 2895 2898 + 2901 2904 2907 2910 2913 2916 + 2919 2922 2925 2928 2931 2934 + 2937 2940 2943 2946 2949 2952 + 2955 2958 2961 2964 2967 2970 + 2973 2976 2979 2982 2985 2988 + 2991 2994 2997 3000 3003 3006 + 3009 3012 3015 3018 3021 3024 + 3027 3030 3033 3036 3039 3042 + 3045 3048 3051 3054 3057 3060 + 3063 3066 3069 3072 3075 3078 + 3081 3084 3087 3090 3093 3096 + 3099 3102 3105 3108 3111 3114 + 3117 3120 3123 3126 3129 3132 + 3135 3138 3141 3144 3147 3150 + 3153 3156 3159 3162 3165 3168 + 3171 3174 3177 3180 3183 3186 + 3189 3192 3195 3198 3201 3204 + 3207 3210 3213 3216 3219 3222 + 3225 3228 3231 3234 3237 3240 + 3243 3246 3249 3252 3255 3258 + 3261 3264 3267 3270 3273 3276 + 3279 3282 3285 3288 3291 3294 + 3297 3300 3303 3306 3309 3312 + 3315 3318 3321 3324 3327 3330 + 3333 3336 3339 3342 3345 3348 + 3351 3354 3357 3360 3363 3366 + 3369 3372 3375 3378 3381 3384 + 3387 3390 3393 3396 3399 3402 + 3405 3408 3411 3414 3417 3420 + 3423 3426 3429 3432 3435 3438 + 3441 3444 3447 3450 3453 3456 + 3459 3462 3465 3468 3471 3474 + 3477 3480 3483 3486 3489 3492 + 3495 3498 3501 3504 3507 3510 + 3513 3516 3519 3522 3525 3528 + 3531 3534 3537 3540 3543 3546 + 3549 3552 3555 3558 3561 3564 + 3567 3570 3573 3576 3579 3582 + 3585 3588 3591 3594 3597 3600 + 3603 3606 3609 3612 3615 3618 + 3621 3624 3627 3630 3633 3636 + 3639 3642 3645 3648 3651 3654 + 3657 3660 3663 3666 3669 3672 + 3675 3678 3681 3684 3687 3690 + 3693 3696 3699 3702 3705 3708 + 3711 3714 3717 3720 3723 3726 + 3729 3732 3735 3738 3741 3744 + 3747 3750 3753 3756 3759 3762 + 3765 3768 3771 3774 3777 3780 + 3783 3786 3789 3792 3795 3798 + 3801 3804 3807 3810 3813 3816 + 3819 3822 3825 3828 3831 3834 + 3837 3840 3843 3846 3849 3852 + 3855 3858 3861 3864 3867 3870 + 3873 3876 3879 3882 3885 3888 + 3891 3894 3897 3900 3903 3906 + 3909 3912 3915 3918 3921 3924 + 3927 3930 3933 3936 3939 3942 + 3945 3948 3951 3954 3957 3960 + 3963 3966 3969 3972 3975 3978 + 3981 3984 3987 3990 3993 3996 + 3999 4002 4005 4008 4011 4014 + 4017 4020 4023 4026 4029 4032 + 4035 4038 4041 4044 4047 4050 + 4053 4056 4059 4062 4065 4068 + 4071 4074 4077 4080 4083 4086 + 4089 4092 4095 4098 4101 4104 + 4107 4110 4113 4116 4119 4122 + 4125 4128 4131 4134 4137 4140 + 4143 4146 4149 4152 4155 4158 + 4161 4164 4167 4170 4173 4176 + 4179 4182 4185 4188 4191 4194 + 4197 4200 4203 4206 4209 4212 + 4215 4218 4221 4224 + + + + + From 8191ddbf543100a979325641128e05d81e19a8c8 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Wed, 9 Mar 2016 18:43:08 +0100 Subject: [PATCH 302/402] remove feature supported only in Qt 5.5 --- cgogn/rendering/examples/picking_viewer.cpp | 23 +++++++-------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/cgogn/rendering/examples/picking_viewer.cpp b/cgogn/rendering/examples/picking_viewer.cpp index e9bc3fa8..1d28517b 100644 --- a/cgogn/rendering/examples/picking_viewer.cpp +++ b/cgogn/rendering/examples/picking_viewer.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -70,7 +71,7 @@ class Viewer : public QOGLViewer private: - void rayClick(QMouseEvent* event, QVector3D& P, QVector3D& Q); + void rayClick(QMouseEvent* event, qoglviewer::Vec& P, qoglviewer::Vec& Q); QRect viewport_; @@ -176,20 +177,10 @@ void Viewer::init() } -void Viewer::rayClick(QMouseEvent* event, QVector3D& P, QVector3D& Q) +void Viewer::rayClick(QMouseEvent* event, qoglviewer::Vec& P, qoglviewer::Vec& Q) { - int vp[4]; - glGetIntegerv(GL_VIEWPORT, vp); - QRect viewport = QRect(vp[0],vp[1],vp[2],vp[3]); - - unsigned int x = event->x()*devicePixelRatio(); - unsigned int y = (this->height()-event->y())*devicePixelRatio(); - - QVector3D wp(x,y,0.01); - P = wp.unproject(view_,proj_,viewport); - QVector3D wq(x,y,0.99); - Q = wq.unproject(view_,proj_,viewport); - + P = camera()->unprojectedCoordinatesOf(qoglviewer::Vec(event->x(),event->y(),0.01)); + Q = camera()->unprojectedCoordinatesOf(qoglviewer::Vec(event->x(),event->y(),0.99)); } @@ -218,8 +209,8 @@ void Viewer::mousePressEvent(QMouseEvent* event) { if (event->modifiers() & Qt::ShiftModifier) { - QVector3D P; - QVector3D Q; + qoglviewer::Vec P; + qoglviewer::Vec Q; rayClick(event,P,Q); Vec3 A(P[0],P[1],P[2]); From 817af4c1a97d9664ff4fe07f3aa2da1831c8e897 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Wed, 9 Mar 2016 19:15:56 +0100 Subject: [PATCH 303/402] ray_intersection not line (check direction) --- cgogn/geometry/functions/intersection.h | 33 ++++++++++----------- cgogn/rendering/examples/picking_viewer.cpp | 4 +-- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/cgogn/geometry/functions/intersection.h b/cgogn/geometry/functions/intersection.h index 818815ec..d7dab710 100644 --- a/cgogn/geometry/functions/intersection.h +++ b/cgogn/geometry/functions/intersection.h @@ -46,40 +46,39 @@ bool intersection_ray_triangle(const VEC3_T& P, const VEC3_T& Dir, const VEC3_T& unsigned int np = 0 ; unsigned int nn = 0 ; - unsigned int nz = 0 ; if (x >Scalar(0)) ++np ; - else if (x Scalar(0)) ++np ; - else if (y Scalar(0)) ++np ; - else if (z unprojectedCoordinatesOf(qoglviewer::Vec(event->x(),event->y(),0.01)); - Q = camera()->unprojectedCoordinatesOf(qoglviewer::Vec(event->x(),event->y(),0.99)); + P = camera()->unprojectedCoordinatesOf(qoglviewer::Vec(event->x(),event->y(),0.0)); + Q = camera()->unprojectedCoordinatesOf(qoglviewer::Vec(event->x(),event->y(),1.0)); } From e05fa35f6e22fdaaf0c2b3e8723361be96946be4 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Thu, 10 Mar 2016 09:30:20 +0100 Subject: [PATCH 304/402] resolv endianness warning --- cgogn/core/cmap/cmap2_builder.h | 2 +- cgogn/core/utils/endian.h | 116 ++++++++++++++++++++++---------- 2 files changed, 82 insertions(+), 36 deletions(-) diff --git a/cgogn/core/cmap/cmap2_builder.h b/cgogn/core/cmap/cmap2_builder.h index 4d6b120b..f4f30de7 100644 --- a/cgogn/core/cmap/cmap2_builder.h +++ b/cgogn/core/cmap/cmap2_builder.h @@ -76,7 +76,7 @@ class CMap2Builder_T template inline void new_orbit_embedding(CellType c) { - map_.template new_orbit_embedding(c); + map_.new_orbit_embedding(c); } inline void phi2_sew(Dart d, Dart e) diff --git a/cgogn/core/utils/endian.h b/cgogn/core/utils/endian.h index 7df8feb1..7ab308ee 100644 --- a/cgogn/core/utils/endian.h +++ b/cgogn/core/utils/endian.h @@ -117,40 +117,86 @@ inline double swap_endianness_double(double x) return u.as_f64; } -template -inline T swap_endianness_if(T x) -{ - static_assert( std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value, "This function is specialized for 8,16, 32 or 64 bits (u))ints, floats and doubles."); +template< bool COND> +inline char swap_endianness_if(char x) +{ + return x; +} + +template< bool COND> +inline std::uint8_t swap_endianness_if(std::uint8_t x) +{ + return x; +} + +template< bool COND> +inline std::uint16_t swap_endianness_if(std::uint16_t x) +{ if (COND) - { - if (std::is_same::value) - return swap_endianness16u(x); - if (std::is_same::value) - return swap_endianness32u(x); - if (std::is_same::value) - return swap_endianness64u(x); - if (std::is_same::value) - return swap_endianness16(x); - if (std::is_same::value) - return swap_endianness32(x); - if (std::is_same::value) - return swap_endianness64(x); - if (std::is_same::value) - return swap_endianness_float(x); - if (std::is_same::value) - return swap_endianness_double(x); - } + return swap_endianness16u(x); + return x; +} + +template< bool COND> +inline std::uint32_t swap_endianness_if(std::uint32_t x) +{ + if (COND) + return swap_endianness32u(x); + return x; +} + +template< bool COND> +inline std::uint64_t swap_endianness_if(std::uint64_t x) +{ + if (COND) + return swap_endianness64u(x); + return x; +} + +template< bool COND> +inline std::int8_t swap_endianness_if(std::int8_t x) +{ + return x; +} + +template< bool COND> +inline std::int16_t swap_endianness_if(std::int16_t x) +{ + if (COND) + return swap_endianness16(x); + return x; +} + +template< bool COND> +inline std::int32_t swap_endianness_if(std::int32_t x) +{ + if (COND) + return swap_endianness32(x); + return x; +} + +template< bool COND> +inline std::int64_t swap_endianness_if(std::int64_t x) +{ + if (COND) + return swap_endianness64(x); + return x; +} + +template< bool COND> +inline float swap_endianness_if(float x) +{ + if (COND) + return swap_endianness_float(x); + return x; +} + +template< bool COND> +inline double swap_endianness_if(double x) +{ + if (COND) + return swap_endianness_double(x); return x; } @@ -159,19 +205,19 @@ inline T swap_endianness_if(T x) template inline T swap_endianness(T x) { - return internal::swap_endianness_if(x); + return internal::swap_endianness_if(x); } template inline T swap_endianness_native_big(T x) { - return internal::swap_endianness_if(x); + return internal::swap_endianness_if(x); } template inline T swap_endianness_native_little(T x) { - return internal::swap_endianness_if(x); + return internal::swap_endianness_if(x); } } // namespace cgogn From 2884f61af0763b5a9b4250f476042c219130e510 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Thu, 10 Mar 2016 09:32:29 +0100 Subject: [PATCH 305/402] resolv io warning --- cgogn/io/data_io.h | 16 ++++++++++------ cgogn/io/io_utils.cpp | 8 ++++---- cgogn/io/volume_import.h | 4 ++-- cgogn/io/vtk_io.h | 18 +++++++++--------- 4 files changed, 25 insertions(+), 21 deletions(-) diff --git a/cgogn/io/data_io.h b/cgogn/io/data_io.h index c1691a2c..5952b781 100644 --- a/cgogn/io/data_io.h +++ b/cgogn/io/data_io.h @@ -154,19 +154,20 @@ class DataInput : public DataInputGen std::string line; line.reserve(256); std::size_t i = 0ul; - BUFFER_T buff; +// BUFFER_T buff; for (; i < n && (!fp.eof()) && (!fp.bad()); ) { - bool no_error = true; std::getline(fp,line); std::istringstream line_stream(line); // we need to avoid the specialization of istringstream operator>> for chars using type = typename std::conditional::type; type buff; - while (i < n && (no_error = static_cast(internal::parse(line_stream, buff)))) + bool no_error = static_cast(internal::parse(line_stream, buff)); + while (i < n && no_error) { data_[i+old_size] = internal::convert(buff); ++i; + no_error = static_cast(internal::parse(line_stream, buff)); } if (!no_error && (!line_stream.eof())) break; @@ -191,11 +192,14 @@ class DataInput : public DataInputGen std::size_t i = 0ul; for (; i < n && (!fp.eof()) && (!fp.bad()); ) { - bool no_error = true; std::getline(fp,line); std::istringstream line_stream(line); - while (i < n && (no_error = static_cast(line_stream.ignore(1, ' ')))) + bool no_error = static_cast(line_stream.ignore(1, ' ')); + while (i < n && no_error) + { ++i; + no_error = static_cast(line_stream.ignore(1, ' ')); + } if (!no_error && (!line_stream.eof())) break; } @@ -212,7 +216,7 @@ class DataInput : public DataInputGen virtual ChunkArray* add_attribute(ChunkArrayContainer& cac, const std::string& att_name) const override { - for (unsigned i = cac.capacity(), end = data_.size(); i < end; i+=PRIM_SIZE) + for (std::size_t i = cac.capacity(), end = data_.size(); i < end; i+=PRIM_SIZE) cac.template insert_lines(); return cac.template add_attribute(att_name); } diff --git a/cgogn/io/io_utils.cpp b/cgogn/io/io_utils.cpp index 2e3eae65..71abaef3 100644 --- a/cgogn/io/io_utils.cpp +++ b/cgogn/io/io_utils.cpp @@ -77,11 +77,11 @@ CGOGN_IO_API std::vector zlib_decompress(const char* input, DataT if (header_type == DataType::UINT64) { for (unsigned int i = 0; i < nb_blocks; ++i) - compressed_size[i] = *reinterpret_cast(&header_data[8u*i]); + compressed_size[i] = static_cast(*reinterpret_cast(&header_data[8u * i])); } else { for (unsigned int i = 0; i < nb_blocks; ++i) - compressed_size[i] = *reinterpret_cast(&header_data[4u*i]); + compressed_size[i] = static_cast(*reinterpret_cast(&header_data[4u * i])); } std::vector data = base64_decode(input, header_end +length); @@ -100,12 +100,12 @@ CGOGN_IO_API std::vector zlib_decompress(const char* input, DataT ret = inflateInit(&zstream); zstream.avail_in = compressed_size[i]; zstream.next_in = &data[in_data_it]; - zstream.avail_out = (i == nb_blocks -1u) ? last_block_size : uncompressed_block_size; + zstream.avail_out = static_cast( (i == nb_blocks - 1u) ? last_block_size : uncompressed_block_size ); zstream.next_out = &res[out_data_it]; ret = inflate(&zstream, Z_NO_FLUSH); ret = inflateEnd(&zstream); in_data_it += compressed_size[i]; - out_data_it+=uncompressed_block_size; + out_data_it += static_cast(uncompressed_block_size); } return res; } diff --git a/cgogn/io/volume_import.h b/cgogn/io/volume_import.h index b472c3b6..b09b6fbf 100644 --- a/cgogn/io/volume_import.h +++ b/cgogn/io/volume_import.h @@ -349,7 +349,7 @@ class VolumeImport : public MeshImportGen } template - void add_pyramid(ChunkArrayconst& pos,unsigned int& p0, unsigned int& p1, unsigned int& p2, unsigned int& p3, unsigned int& p4) + void add_pyramid(ChunkArrayconst& /*pos*/,unsigned int& p0, unsigned int& p1, unsigned int& p2, unsigned int& p3, unsigned int& p4) { this->volumes_nb_vertices_.push_back(5u); this->volumes_vertex_indices_.push_back(p0); @@ -360,7 +360,7 @@ class VolumeImport : public MeshImportGen } template - void add_triangular_prism(ChunkArrayconst& pos,unsigned int& p0, unsigned int& p1, unsigned int& p2, unsigned int& p3, unsigned int& p4, unsigned int& p5) + void add_triangular_prism(ChunkArrayconst& /*pos*/,unsigned int& p0, unsigned int& p1, unsigned int& p2, unsigned int& p3, unsigned int& p4, unsigned int& p5) { this->volumes_nb_vertices_.push_back(6u); this->volumes_vertex_indices_.push_back(p0); diff --git a/cgogn/io/vtk_io.h b/cgogn/io/vtk_io.h index 3a08683a..176754a4 100644 --- a/cgogn/io/vtk_io.h +++ b/cgogn/io/vtk_io.h @@ -635,8 +635,8 @@ class VtkSurfaceImport : public VtkIO: return false; this->fill_surface_import(); - this->nb_vertices_ = this->positions_.size(); - this->nb_faces_ = this->offsets_.size(); + this->nb_vertices_ = static_cast(this->positions_.size()); + this->nb_faces_ = static_cast(this->offsets_.size()); auto cells_it = this->cells_.get_vec()->begin(); unsigned int last_offset = 0u; @@ -685,8 +685,8 @@ class VtkSurfaceImport : public VtkIO: private: inline void fill_surface_import() { - this->nb_vertices_ = this->positions_.size(); - this->nb_faces_ = this->cell_types_.size(); + this->nb_vertices_ = static_cast(this->positions_.size()); + this->nb_faces_ = static_cast(this->cell_types_.size()); auto cells_it = static_cast*>(this->cells_.get_data())->begin(); const std::vector* cell_types_vec = static_cast*>(this->cell_types_.get_data()); @@ -697,7 +697,7 @@ class VtkSurfaceImport : public VtkIO: if (cell_type != VTK_CELL_TYPES::VTK_TRIANGLE_STRIP) { - this->faces_nb_edges_.push_back(nb_vert); + this->faces_nb_edges_.push_back(static_cast(nb_vert)); for (std::size_t i = 0ul ; i < nb_vert;++i) { this->faces_vertex_indices_.push_back(*cells_it++); @@ -749,8 +749,8 @@ class VtkVolumeImport : public VtkIO:: if (!Inherit_Vtk::parse_vtk_legacy_file(fp)) return false; - this->nb_vertices_ = this->positions_.size(); - this->nb_volumes_ = this->cell_types_.size(); + this->nb_vertices_ = static_cast(this->positions_.size()); + this->nb_volumes_ = static_cast(this->cell_types_.size()); const std::vector* cell_types_vec = this->cell_types_.get_vec(); const std::vector* cells_vec = this->cells_.get_vec(); @@ -794,8 +794,8 @@ class VtkVolumeImport : public VtkIO:: if (!Inherit_Vtk::parse_xml_vtu(filename)) return false; - this->nb_vertices_ = this->positions_.size(); - this->nb_volumes_ = this->cell_types_.size(); + this->nb_vertices_ = static_cast(this->positions_.size()); + this->nb_volumes_ = static_cast(this->cell_types_.size()); const std::vector* cell_types_vec = this->cell_types_.get_vec(); const std::vector* cells_vec = this->cells_.get_vec(); From abd7d54381395eee2909538d6e658649d67cb837 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Thu, 10 Mar 2016 09:36:01 +0100 Subject: [PATCH 306/402] resolv mr warnings --- cgogn/multiresolution/cph/ihcmap2.h | 9 ++++++++- cgogn/multiresolution/cph/ihcmap2_adaptive.h | 4 ++-- cgogn/multiresolution/cph/ihcmap3.h | 1 + 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/cgogn/multiresolution/cph/ihcmap2.h b/cgogn/multiresolution/cph/ihcmap2.h index a35fa4e6..e9c7d000 100644 --- a/cgogn/multiresolution/cph/ihcmap2.h +++ b/cgogn/multiresolution/cph/ihcmap2.h @@ -50,6 +50,7 @@ class ContainerCPHBrowser : public ContainerBrowser virtual void enable() {} virtual void disable() {} virtual ~ContainerCPHBrowser() {} + ContainerCPHBrowser& operator=(const ContainerCPHBrowser&) = delete; }; template @@ -264,13 +265,19 @@ class IHCMap2_T : public CMap2_T, public CPH2 }); if (this->template is_embedded()) + { cgogn_assert_not_reached("Not implemented"); - + } + if (this->template is_embedded()) + { cgogn_assert_not_reached("Not implemented"); + } if (this->template is_embedded()) + { cgogn_assert_not_reached("Not implemented"); + } return f; } diff --git a/cgogn/multiresolution/cph/ihcmap2_adaptive.h b/cgogn/multiresolution/cph/ihcmap2_adaptive.h index 8c61aeeb..31dceeb1 100644 --- a/cgogn/multiresolution/cph/ihcmap2_adaptive.h +++ b/cgogn/multiresolution/cph/ihcmap2_adaptive.h @@ -340,14 +340,14 @@ class IHCMap2Adaptive_T : public IHCMap2_T } protected: - inline Vertex cut_edge_update_emb(Dart e, Dart e2, Dart nd) + inline Vertex cut_edge_update_emb(Dart /*e*/, Dart /*e2*/, Dart /*nd*/) { CGOGN_CHECK_CONCRETE_TYPE; std::cerr << "IHCMap2Adaptive_T::cut_edge_update_emb method is not implemented yet." << std::endl; return Vertex(); } - inline void cut_face_update_emb(Dart e, Dart e2) + inline void cut_face_update_emb(Dart /*e*/, Dart /*e2*/) { CGOGN_CHECK_CONCRETE_TYPE; std::cerr << "IHCMap2Adaptive_T::cut_face_update_emb method is not implemented yet." << std::endl; diff --git a/cgogn/multiresolution/cph/ihcmap3.h b/cgogn/multiresolution/cph/ihcmap3.h index e300ef3b..1a218e26 100644 --- a/cgogn/multiresolution/cph/ihcmap3.h +++ b/cgogn/multiresolution/cph/ihcmap3.h @@ -99,6 +99,7 @@ class IHCMap3_T :public CMap3_T, public CPH3 virtual void enable() {} virtual void disable() {} virtual ~ContainerCPHBrowser() {} + ContainerCPHBrowser& operator=(const ContainerCPHBrowser&) = delete; }; protected: From e22a41b469e7c23aa25908ac12c25fca2ec19d3e Mon Sep 17 00:00:00 2001 From: thery Date: Thu, 10 Mar 2016 13:10:08 +0100 Subject: [PATCH 307/402] vs2015 warnings --- .../multithreading/bench_multithreading.cpp | 62 +++++++++---------- cgogn/io/off_io.h | 46 +++++++------- cgogn/io/surface_import.h | 2 +- cgogn/io/volume_import.h | 2 +- cgogn/io/vtk_io.h | 4 +- .../libQGLViewer/QOGLViewer/quaternion.h | 4 +- 6 files changed, 61 insertions(+), 59 deletions(-) diff --git a/benchmarks/multithreading/bench_multithreading.cpp b/benchmarks/multithreading/bench_multithreading.cpp index 18fcf557..7114e5cf 100644 --- a/benchmarks/multithreading/bench_multithreading.cpp +++ b/benchmarks/multithreading/bench_multithreading.cpp @@ -33,7 +33,7 @@ #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) using Map2 = cgogn::CMap2; -Map2 map; +Map2 bench_map; using Vertex = Map2::Vertex; const cgogn::Orbit VERTEX = Vertex::ORBIT; @@ -56,7 +56,7 @@ static void BENCH_Dart_count_single_threaded(benchmark::State& state) while (state.KeepRunning()) { unsigned nb_darts = 0u; - map.foreach_dart([&nb_darts] (cgogn::Dart) { nb_darts++; }); + bench_map.foreach_dart([&nb_darts] (cgogn::Dart) { nb_darts++; }); } } @@ -69,14 +69,14 @@ static void BENCH_Dart_count_multi_threaded(benchmark::State& state) for (auto& n : nb_darts_per_thread) n = 0u; nb_darts_2 = 0u; - map.parallel_foreach_dart([&nb_darts_per_thread] (cgogn::Dart, unsigned int thread_index) + bench_map.parallel_foreach_dart([&nb_darts_per_thread] (cgogn::Dart, unsigned int thread_index) { nb_darts_per_thread[thread_index]++; }); for (unsigned int n : nb_darts_per_thread) nb_darts_2 += n; - cgogn_assert(nb_darts_2 == map.nb_darts()); + cgogn_assert(nb_darts_2 == bench_map.nb_darts()); } } @@ -86,15 +86,15 @@ static void BENCH_faces_normals_single_threaded(benchmark::State& state) while(state.KeepRunning()) { state.PauseTiming(); - VertexAttributeHandler vertex_position = map.get_attribute("position"); + VertexAttributeHandler vertex_position = bench_map.get_attribute("position"); cgogn_assert(vertex_position.is_valid()); - FaceAttributeHandler face_normal = map.get_attribute("normal"); + FaceAttributeHandler face_normal = bench_map.get_attribute("normal"); cgogn_assert(face_normal.is_valid()); state.ResumeTiming(); - map.template foreach_cell([&] (Face f) + bench_map.template foreach_cell([&] (Face f) { - face_normal[f] = cgogn::geometry::face_normal(map, f, vertex_position); + face_normal[f] = cgogn::geometry::face_normal(bench_map, f, vertex_position); }); } } @@ -105,22 +105,22 @@ static void BENCH_faces_normals_multi_threaded(benchmark::State& state) while(state.KeepRunning()) { state.PauseTiming(); - VertexAttributeHandler vertex_position = map.get_attribute("position"); + VertexAttributeHandler vertex_position = bench_map.get_attribute("position"); cgogn_assert(vertex_position.is_valid()); - FaceAttributeHandler face_normal_mt = map.get_attribute("normal_mt"); + FaceAttributeHandler face_normal_mt = bench_map.get_attribute("normal_mt"); cgogn_assert(face_normal_mt.is_valid()); state.ResumeTiming(); - map.template parallel_foreach_cell([&] (Face f,unsigned int) + bench_map.template parallel_foreach_cell([&] (Face f,unsigned int) { - face_normal_mt[f] = cgogn::geometry::face_normal(map, f, vertex_position); + face_normal_mt[f] = cgogn::geometry::face_normal(bench_map, f, vertex_position); }); { state.PauseTiming(); - FaceAttributeHandler face_normal = map.get_attribute("normal"); - map.template foreach_cell([&] (Face f) + FaceAttributeHandler face_normal = bench_map.get_attribute("normal"); + bench_map.template foreach_cell([&] (Face f) { Vec3 error = face_normal[f] - face_normal_mt[f]; if (!cgogn::almost_equal_absolute(error.squaredNorm(), 0., 1e-9 )) @@ -144,15 +144,15 @@ static void BENCH_vertices_normals_single_threaded(benchmark::State& state) while(state.KeepRunning()) { state.PauseTiming(); - VertexAttributeHandler vertex_position = map.get_attribute("position"); + VertexAttributeHandler vertex_position = bench_map.get_attribute("position"); cgogn_assert(vertex_position.is_valid()); - VertexAttributeHandler vartices_normal = map.get_attribute("normal"); + VertexAttributeHandler vartices_normal = bench_map.get_attribute("normal"); cgogn_assert(vartices_normal.is_valid()); state.ResumeTiming(); - map.template foreach_cell([&] (Vertex v) + bench_map.template foreach_cell([&] (Vertex v) { - vartices_normal[v] = cgogn::geometry::vertex_normal(map, v, vertex_position); + vartices_normal[v] = cgogn::geometry::vertex_normal(bench_map, v, vertex_position); }); } } @@ -163,22 +163,22 @@ static void BENCH_vertices_normals_multi_threaded(benchmark::State& state) while(state.KeepRunning()) { state.PauseTiming(); - VertexAttributeHandler vertex_position = map.get_attribute("position"); + VertexAttributeHandler vertex_position = bench_map.get_attribute("position"); cgogn_assert(vertex_position.is_valid()); - VertexAttributeHandler vertices_normal_mt = map.get_attribute("normal_mt"); + VertexAttributeHandler vertices_normal_mt = bench_map.get_attribute("normal_mt"); cgogn_assert(vertices_normal_mt.is_valid()); state.ResumeTiming(); - map.template parallel_foreach_cell([&] (Vertex v, unsigned int) + bench_map.template parallel_foreach_cell([&] (Vertex v, unsigned int) { - vertices_normal_mt[v] = cgogn::geometry::vertex_normal(map, v, vertex_position); + vertices_normal_mt[v] = cgogn::geometry::vertex_normal(bench_map, v, vertex_position); }); { state.PauseTiming(); - VertexAttributeHandler vertices_normal = map.get_attribute("normal"); - map.template foreach_cell([&] (Vertex v) + VertexAttributeHandler vertices_normal = bench_map.get_attribute("normal"); + bench_map.template foreach_cell([&] (Vertex v) { Vec3 error = vertices_normal[v] - vertices_normal_mt[v]; if (!cgogn::almost_equal_absolute(error.squaredNorm(), 0., 1e-9 )) @@ -226,14 +226,14 @@ int main(int argc, char** argv) else surfaceMesh = std::string(argv[1]); - cgogn::io::import_surface(map, surfaceMesh); + cgogn::io::import_surface(bench_map, surfaceMesh); - map.add_attribute("normal"); - map.add_attribute("normal_mt"); - map.add_attribute("normal"); - map.add_attribute("normal_mt"); - map.enable_topo_cache(); - map.enable_topo_cache(); + bench_map.add_attribute("normal"); + bench_map.add_attribute("normal_mt"); + bench_map.add_attribute("normal"); + bench_map.add_attribute("normal_mt"); + bench_map.enable_topo_cache(); + bench_map.enable_topo_cache(); ::benchmark::RunSpecifiedBenchmarks(); return 0; diff --git a/cgogn/io/off_io.h b/cgogn/io/off_io.h index 20c3d665..f7920b95 100644 --- a/cgogn/io/off_io.h +++ b/cgogn/io/off_io.h @@ -128,33 +128,35 @@ class OffSurfaceImport : public SurfaceImport { std::vector vertices_id; vertices_id.reserve(this->nb_vertices_); - unsigned j = BUFFER_SZ; - for (unsigned int i = 0; i < this->nb_vertices_; ++i,++j) - { - if (j == BUFFER_SZ) + { // limit j scope + unsigned j = BUFFER_SZ; + for (unsigned int i = 0; i < this->nb_vertices_; ++i, ++j) { - j = 0; - // read from file into buffer - if (i+BUFFER_SZ < this->nb_vertices_) - fp.read(reinterpret_cast(buff_pos),3*sizeof(float)*BUFFER_SZ); - else - fp.read(reinterpret_cast(buff_pos),3*sizeof(float)*(this->nb_vertices_-i)); - - //endian - unsigned int* ptr = reinterpret_cast(buff_pos); - for (unsigned int k=0; k< 3*BUFFER_SZ;++k) + if (j == BUFFER_SZ) { - *ptr = swap_endianness_native_big(*ptr); - ++ptr; + j = 0; + // read from file into buffer + if (i + BUFFER_SZ < this->nb_vertices_) + fp.read(reinterpret_cast(buff_pos), 3 * sizeof(float)*BUFFER_SZ); + else + fp.read(reinterpret_cast(buff_pos), 3 * sizeof(float)*(this->nb_vertices_ - i)); + + //endian + unsigned int* ptr = reinterpret_cast(buff_pos); + for (unsigned int k = 0; k < 3 * BUFFER_SZ; ++k) + { + *ptr = swap_endianness_native_big(*ptr); + ++ptr; + } } - } - VEC3 pos{buff_pos[3*j], buff_pos[3*j+1], buff_pos[3*j+2]}; + VEC3 pos{ buff_pos[3 * j], buff_pos[3 * j + 1], buff_pos[3 * j + 2] }; - unsigned int vertex_id = this->vertex_attributes_.template insert_lines<1>(); - (*position)[vertex_id] = pos; + unsigned int vertex_id = this->vertex_attributes_.template insert_lines<1>(); + (*position)[vertex_id] = pos; - vertices_id.push_back(vertex_id); + vertices_id.push_back(vertex_id); + } } delete[] buff_pos; @@ -173,7 +175,7 @@ class OffSurfaceImport : public SurfaceImport { { fp.read(reinterpret_cast(buff_ind),BUFFER_SZ*sizeof(unsigned int)); ptr = buff_ind; - for (unsigned int i=0; i< BUFFER_SZ;++i) + for (unsigned int k=0; k< BUFFER_SZ;++k) { *ptr = swap_endianness_native_big(*ptr); ++ptr; diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index 99631567..f7c3dae2 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -56,7 +56,7 @@ class SurfaceImport : public MeshImportGen static const unsigned int CHUNK_SIZE = MAP_TRAITS::CHUNK_SIZE; template - using ChunkArray = ChunkArray; + using ChunkArray = cgogn::ChunkArray; using ChunkArrayContainer = cgogn::ChunkArrayContainer; template using AttributeHandler = AttributeHandler; diff --git a/cgogn/io/volume_import.h b/cgogn/io/volume_import.h index b09b6fbf..c3cf22bc 100644 --- a/cgogn/io/volume_import.h +++ b/cgogn/io/volume_import.h @@ -60,7 +60,7 @@ class VolumeImport : public MeshImportGen static const unsigned int CHUNK_SIZE = MAP_TRAITS::CHUNK_SIZE; template - using ChunkArray = ChunkArray; + using ChunkArray = cgogn::ChunkArray; using ChunkArrayContainer = cgogn::ChunkArrayContainer; template diff --git a/cgogn/io/vtk_io.h b/cgogn/io/vtk_io.h index 176754a4..0c72114d 100644 --- a/cgogn/io/vtk_io.h +++ b/cgogn/io/vtk_io.h @@ -268,7 +268,7 @@ protected : sstream.clear(); std::string data_name; unsigned int nb_comp; - unsigned int nb_data; + //unsigned int nb_data; already declared std::string data_type; sstream >> data_name >> nb_comp >> nb_data >> data_type; std::cout << "reading field \"" << data_name << "\" of type " << data_type << " (" << nb_comp << " components)." << std::endl; @@ -283,7 +283,7 @@ protected : if (word == "LOOKUP_TABLE") { std::string table_name; - unsigned int nb_data = 0u; + /*unsigned int*/ nb_data = 0u; sstream >> table_name >> nb_data; std::cout << "ignoring the definition of the lookuptable named \"" << table_name << "\"" << std::endl; if (ascii_file) diff --git a/thirdparty/libQGLViewer/QOGLViewer/quaternion.h b/thirdparty/libQGLViewer/QOGLViewer/quaternion.h index e07cdac4..a9438d2f 100644 --- a/thirdparty/libQGLViewer/QOGLViewer/quaternion.h +++ b/thirdparty/libQGLViewer/QOGLViewer/quaternion.h @@ -175,9 +175,9 @@ class QGLVIEWER_EXPORT Quaternion \note For efficiency reasons, the resulting Quaternion is not normalized. You may normalize() it after each application in case of numerical drift. */ - Quaternion& operator*=(const Quaternion &q) + Quaternion& operator*=(const Quaternion &qa) { - *this = (*this)*q; + *this = (*this)*qa; return *this; } From 2edd8e59dd0a47cd07879d3f312578a0240bb036 Mon Sep 17 00:00:00 2001 From: thery Date: Thu, 10 Mar 2016 13:11:06 +0100 Subject: [PATCH 308/402] fix debug compil pb (/bigobj) --- cmake/CompilerOptions.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/CompilerOptions.cmake b/cmake/CompilerOptions.cmake index 32e69990..5102b61c 100644 --- a/cmake/CompilerOptions.cmake +++ b/cmake/CompilerOptions.cmake @@ -129,6 +129,6 @@ else() # MSVC # C4505 - unreferenced local function has been removed (impossible to deactive selectively) # C4910 - __declspec(dllexport)' and 'extern' are incompatible on an explicit instantiation # C4251 - 'identifier' : class 'type' needs to have dll-interface to be used by clients of class 'type2' - add_flags(CMAKE_CXX_FLAGS "/EHsc /wd4127 /wd4505 /wd4714 /wd4910 /wd4251") - + add_flags(CMAKE_CXX_FLAGS "/EHsc /wd4127 /wd4505 /wd4714 /wd4910 /wd4251 /bigobj") + endif() From c5f7a13420506c3f6b1abc3ba33becc54a853f87 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Thu, 10 Mar 2016 15:21:13 +0100 Subject: [PATCH 309/402] added lm6 library (+ transmesh tool) Signed-off-by: Etienne Schmitt --- thirdparty/CMakeLists.txt | 1 + thirdparty/lm6/CMakeLists.txt | 23 + thirdparty/lm6/LICENSE_lgpl.txt | 165 ++ thirdparty/lm6/copyright.txt | 10 + thirdparty/lm6/libmesh6.c | 1819 ++++++++++++++ thirdparty/lm6/libmesh6.h | 158 ++ thirdparty/lm6/lm6_en.pdf | Bin 0 -> 230876 bytes thirdparty/lm6/quad.mesh | 3973 +++++++++++++++++++++++++++++++ thirdparty/lm6/transmesh.c | 147 ++ 9 files changed, 6296 insertions(+) create mode 100644 thirdparty/lm6/CMakeLists.txt create mode 100644 thirdparty/lm6/LICENSE_lgpl.txt create mode 100644 thirdparty/lm6/copyright.txt create mode 100644 thirdparty/lm6/libmesh6.c create mode 100644 thirdparty/lm6/libmesh6.h create mode 100644 thirdparty/lm6/lm6_en.pdf create mode 100644 thirdparty/lm6/quad.mesh create mode 100644 thirdparty/lm6/transmesh.c diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index c4a92db5..c1ba8283 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -20,3 +20,4 @@ endif(CGOGN_BUILD_BENCHS) add_subdirectory(ply) add_subdirectory(OffBinConverter) +add_subdirectory(lm6) diff --git a/thirdparty/lm6/CMakeLists.txt b/thirdparty/lm6/CMakeLists.txt new file mode 100644 index 00000000..8dc9f8df --- /dev/null +++ b/thirdparty/lm6/CMakeLists.txt @@ -0,0 +1,23 @@ +set(CGOGN_THIRDPARTY_LM6_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE PATH "LM6 include directory") + +project(lm6 + LANGUAGES C + ) + +set(HEADER_FILES + libmesh6.h + ) + +set(SOURCE_FILES + libmesh6.c + ) + +add_library(${PROJECT_NAME} STATIC ${HEADER_FILES} ${SOURCE_FILES}) + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/tools) +add_executable(transmesh transmesh.c) +target_include_directories(transmesh PRIVATE + $ +) +target_link_libraries(transmesh ${PROJECT_NAME}) +set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "_d") diff --git a/thirdparty/lm6/LICENSE_lgpl.txt b/thirdparty/lm6/LICENSE_lgpl.txt new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/thirdparty/lm6/LICENSE_lgpl.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/thirdparty/lm6/copyright.txt b/thirdparty/lm6/copyright.txt new file mode 100644 index 00000000..5feae287 --- /dev/null +++ b/thirdparty/lm6/copyright.txt @@ -0,0 +1,10 @@ +All LM6 code is Copyright 2001 - by Loïc Maréchal, Inria. +This program is a free software. +You can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along with this program as the file LICENSE_lgpl.txt; if not, please see : +http://www.gnu.org/licenses/lgpl.txt diff --git a/thirdparty/lm6/libmesh6.c b/thirdparty/lm6/libmesh6.c new file mode 100644 index 00000000..7a21624e --- /dev/null +++ b/thirdparty/lm6/libmesh6.c @@ -0,0 +1,1819 @@ + + +/*----------------------------------------------------------*/ +/* */ +/* LIBMESH V 6.04 */ +/* */ +/*----------------------------------------------------------*/ +/* */ +/* Description: handle .meshb file format I/O */ +/* Author: Loic MARECHAL */ +/* Creation date: feb 16 2007 */ +/* Last modification: feb 18 2015 */ +/* */ +/*----------------------------------------------------------*/ + + +/*----------------------------------------------------------*/ +/* Includes */ +/*----------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "libmesh6.h" + + +/*----------------------------------------------------------*/ +/* Defines */ +/*----------------------------------------------------------*/ + +#define Asc 1 +#define Bin 2 +#define MshFil 4 +#define SolFil 8 +#define MaxMsh 100 +#define InfKwd 1 +#define RegKwd 2 +#define SolKwd 3 +#define CmtKwd 4 +#define WrdSiz 4 +#define FilStrSiz 64 +#define BufSiz 10000 + + +/*----------------------------------------------------------*/ +/* Structures */ +/*----------------------------------------------------------*/ + +typedef struct +{ + int typ, SolSiz, NmbWrd, NmbTyp, TypTab[ GmfMaxTyp ]; + long NmbLin; + long pos; + char fmt[ GmfMaxTyp*9 ]; +}KwdSct; + +typedef struct +{ + int dim, ver, mod, typ, cod; + long NexKwdPos, siz, pos; + KwdSct KwdTab[ GmfMaxKwd + 1 ]; + FILE *hdl; + int *IntBuf; + float *FltBuf; + char *buf; + char FilNam[ GmfStrSiz ]; + double DblBuf[1000/8]; + unsigned char blk[ BufSiz + 1000 ]; +}GmfMshSct; + + +/*----------------------------------------------------------*/ +/* Global variables */ +/*----------------------------------------------------------*/ + +static jmp_buf GmfEnv; +static int GmfIniFlg=0; +static GmfMshSct *GmfMshTab[ MaxMsh + 1 ]; +const char *GmfKwdFmt[ GmfMaxKwd + 1 ][4] = +{ {"Reserved", "", "", ""}, + {"MeshVersionFormatted", "", "", "i"}, + {"Reserved", "", "", ""}, + {"Dimension", "", "", "i"}, + {"Vertices", "Vertex", "i", "dri"}, + {"Edges", "Edge", "i", "iii"}, + {"Triangles", "Triangle", "i", "iiii"}, + {"Quadrilaterals", "Quadrilateral", "i", "iiiii"}, + {"Tetrahedra", "Tetrahedron", "i", "iiiii"}, + {"Prisms", "Prism", "i", "iiiiiii"}, + {"Hexahedra", "Hexahedron", "i", "iiiiiiiii"}, + {"IterationsAll", "IterationAll","","i"}, + {"TimesAll", "TimeAll","","r"}, + {"Corners", "Corner", "i", "i"}, + {"Ridges", "Ridge", "i", "i"}, + {"RequiredVertices", "RequiredVertex", "i", "i"}, + {"RequiredEdges", "RequiredEdge", "i", "i"}, + {"RequiredTriangles", "RequiredTriangle", "i", "i"}, + {"RequiredQuadrilaterals", "RequiredQuadrilateral", "i", "i"}, + {"TangentAtEdgeVertices", "TangentAtEdgeVertex", "i", "iii"}, + {"NormalAtVertices", "NormalAtVertex", "i", "ii"}, + {"NormalAtTriangleVertices", "NormalAtTriangleVertex", "i", "iii"}, + {"NormalAtQuadrilateralVertices", "NormalAtQuadrilateralVertex", "i", "iiii"}, + {"AngleOfCornerBound", "", "", "r"}, + {"TrianglesP2", "TriangleP2", "i", "iiiiiii"}, + {"EdgesP2", "EdgeP2", "i", "iiii"}, + {"SolAtPyramids", "SolAtPyramid", "i", "sr"}, + {"QuadrilateralsQ2", "QuadrilateralQ2", "i", "iiiiiiiiii"}, + {"ISolAtPyramids", "ISolAtPyramid", "i", "iiiii"}, + {"SubDomainFromGeom", "SubDomainFromGeom", "i", "iii"}, + {"TetrahedraP2", "TetrahedronP2", "i", "iiiiiiiiiii"}, + {"Fault_NearTri", "Fault_NearTri", "i", "i"}, + {"Fault_Inter", "Fault_Inter", "i", "i"}, + {"HexahedraQ2", "HexahedronQ2", "i", "iiiiiiiiiiiiiiiiiiiiiiiiiiii"}, + {"ExtraVerticesAtEdges", "ExtraVerticesAtEdge", "i", "in"}, + {"ExtraVerticesAtTriangles", "ExtraVerticesAtTriangle", "i", "in"}, + {"ExtraVerticesAtQuadrilaterals", "ExtraVerticesAtQuadrilateral", "i", "in"}, + {"ExtraVerticesAtTetrahedra", "ExtraVerticesAtTetrahedron", "i", "in"}, + {"ExtraVerticesAtPrisms", "ExtraVerticesAtPrism", "i", "in"}, + {"ExtraVerticesAtHexahedra", "ExtraVerticesAtHexahedron", "i", "in"}, + {"VerticesOnGeometricVertices", "VertexOnGeometricVertex", "i", "iir"}, + {"VerticesOnGeometricEdges", "VertexOnGeometricEdge", "i", "iirr"}, + {"VerticesOnGeometricTriangles", "VertexOnGeometricTriangle", "i", "iirrr"}, + {"VerticesOnGeometricQuadrilaterals", "VertexOnGeometricQuadrilateral", "i", "iirrr"}, + {"EdgesOnGeometricEdges", "EdgeOnGeometricEdge", "i", "iir"}, + {"Fault_FreeEdge", "Fault_FreeEdge", "i", "i"}, + {"Polyhedra", "Polyhedron", "i", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii"}, + {"Polygons", "Polygon", "", "iiiiiiiii"}, + {"Fault_Overlap", "Fault_Overlap", "i", "i"}, + {"Pyramids", "Pyramid", "i", "iiiiii"}, + {"BoundingBox", "", "", "drdr"}, + {"Body","i", "drdrdrdr"}, + {"PrivateTable", "PrivateTable", "i", "i"}, + {"Fault_BadShape", "Fault_BadShape", "i", "i"}, + {"End", "", "", ""}, + {"TrianglesOnGeometricTriangles", "TriangleOnGeometricTriangle", "i", "iir"}, + {"TrianglesOnGeometricQuadrilaterals", "TriangleOnGeometricQuadrilateral", "i", "iir"}, + {"QuadrilateralsOnGeometricTriangles", "QuadrilateralOnGeometricTriangle", "i", "iir"}, + {"QuadrilateralsOnGeometricQuadrilaterals", "QuadrilateralOnGeometricQuadrilateral", "i", "iir"}, + {"Tangents", "Tangent", "i", "dr"}, + {"Normals", "Normal", "i", "dr"}, + {"TangentAtVertices", "TangentAtVertex", "i", "ii"}, + {"SolAtVertices", "SolAtVertex", "i", "sr"}, + {"SolAtEdges", "SolAtEdge", "i", "sr"}, + {"SolAtTriangles", "SolAtTriangle", "i", "sr"}, + {"SolAtQuadrilaterals", "SolAtQuadrilateral", "i", "sr"}, + {"SolAtTetrahedra", "SolAtTetrahedron", "i", "sr"}, + {"SolAtPrisms", "SolAtPrism", "i", "sr"}, + {"SolAtHexahedra", "SolAtHexahedron", "i", "sr"}, + {"DSolAtVertices", "DSolAtVertex", "i", "sr"}, + {"ISolAtVertices", "ISolAtVertex", "i", "i"}, + {"ISolAtEdges", "ISolAtEdge", "i", "ii"}, + {"ISolAtTriangles", "ISolAtTriangle", "i", "iii"}, + {"ISolAtQuadrilaterals", "ISolAtQuadrilateral", "i", "iiii"}, + {"ISolAtTetrahedra", "ISolAtTetrahedron", "i", "iiii"}, + {"ISolAtPrisms", "ISolAtPrism", "i", "iiiiii"}, + {"ISolAtHexahedra", "ISolAtHexahedron", "i", "iiiiiiii"}, + {"Iterations", "","","i"}, + {"Time", "","","r"}, + {"Fault_SmallTri", "Fault_SmallTri","i","i"}, + {"CoarseHexahedra", "CoarseHexahedron", "i", "i"}, + {"Comments", "Comment", "i", "c"} + }; + + +/*----------------------------------------------------------*/ +/* Prototypes of local procedures */ +/*----------------------------------------------------------*/ + +static void ScaWrd(GmfMshSct *, void *); +static void ScaDblWrd(GmfMshSct *, void *); +static long GetPos(GmfMshSct *); +static void RecWrd(GmfMshSct *, const void *); +static void RecDblWrd(GmfMshSct *, const void *); +static void RecBlk(GmfMshSct *, const void *, int); +static void SetPos(GmfMshSct *, long); +static int ScaKwdTab(GmfMshSct *); +static void ExpFmt(GmfMshSct *, int); +static void ScaKwdHdr(GmfMshSct *, int); +static void SwpWrd(char *, int); + +#define safe_fscanf(hdl, format, ptr) \ + do { \ + if( fscanf(hdl, format, ptr) != 1 ) \ + longjmp(GmfEnv, -1); \ + } while(0) + + +#define safe_fgets(ptr, siz, hdl) \ + do { \ + if( fgets(ptr, siz, hdl) == NULL ) \ + longjmp(GmfEnv, -1); \ + } while(0) + + +/*----------------------------------------------------------*/ +/* Open a mesh file in read or write mod */ +/*----------------------------------------------------------*/ + +int GmfOpenMesh(const char *FilNam, int mod, ...) +{ + int i, KwdCod, res, *PtrVer, *PtrDim, MshIdx=0; + char str[ GmfStrSiz ]; + va_list VarArg; + GmfMshSct *msh; + + if(!GmfIniFlg) + { + for(i=0;i<=MaxMsh;i++) + GmfMshTab[i] = NULL; + + GmfIniFlg = 1; + } + + /*---------------------*/ + /* MESH STRUCTURE INIT */ + /*---------------------*/ + + for(i=1;i<=MaxMsh;i++) + if(!GmfMshTab[i]) + { + MshIdx = i; + break; + } + + if( !MshIdx || !(msh = calloc(1, sizeof(GmfMshSct))) ) + return(0); + + /* Save the current stack environment for longjmp */ + + if(setjmp(GmfEnv) != 0) + { + if(msh->hdl != NULL) + fclose(msh->hdl); + free(msh); + return(0); + } + + /* Copy the FilNam into the structure */ + + if(strlen(FilNam) + 7 >= GmfStrSiz) + longjmp(GmfEnv, -1); + + strcpy(msh->FilNam, FilNam); + + /* Store the opening mod (read or write) and guess the filetype (binary or ascii) depending on the extension */ + + msh->mod = mod; + msh->buf = (void *)msh->DblBuf; + msh->FltBuf = (void *)msh->DblBuf; + msh->IntBuf = (void *)msh->DblBuf; + + if(strstr(msh->FilNam, ".meshb")) + msh->typ |= (Bin | MshFil); + else if(strstr(msh->FilNam, ".mesh")) + msh->typ |= (Asc | MshFil); + else if(strstr(msh->FilNam, ".solb")) + msh->typ |= (Bin | SolFil); + else if(strstr(msh->FilNam, ".sol")) + msh->typ |= (Asc | SolFil); + else + longjmp(GmfEnv, -1); + + /* Open the file in the required mod and initialyse the mesh structure */ + + if(msh->mod == GmfRead) + { + + /*-----------------------*/ + /* OPEN FILE FOR READING */ + /*-----------------------*/ + + va_start(VarArg, mod); + PtrVer = va_arg(VarArg, int *); + PtrDim = va_arg(VarArg, int *); + va_end(VarArg); + + /* Create the name string and open the file */ + + if(!(msh->hdl = fopen(msh->FilNam, "rb"))) + longjmp(GmfEnv, -1); + + /* Read the endian coding tag, the mesh version and the mesh dimension (mandatory kwd) */ + + if(msh->typ & Bin) + { + if( fread(&msh->cod, WrdSiz, 1, msh->hdl) != 1 ) + longjmp(GmfEnv, -1); + + if( (msh->cod != 1) && (msh->cod != 16777216) ) + longjmp(GmfEnv, -1); + + ScaWrd(msh, (unsigned char *)&msh->ver); + + if( (msh->ver < 1) || (msh->ver > 4) ) + longjmp(GmfEnv, -1); + + if( (msh->ver >= 3) && (sizeof(long) == 4) ) + longjmp(GmfEnv, -1); + + ScaWrd(msh, (unsigned char *)&KwdCod); + + if(KwdCod != GmfDimension) + longjmp(GmfEnv, -1); + + GetPos(msh); + ScaWrd(msh, (unsigned char *)&msh->dim); + } + else + { + do + { + res = fscanf(msh->hdl, "%s", str); + }while( (res != EOF) && strcmp(str, "MeshVersionFormatted") ); + + if(res == EOF) + longjmp(GmfEnv, -1); + + safe_fscanf(msh->hdl, "%d", &msh->ver); + + if( (msh->ver < 1) || (msh->ver > 4) ) + longjmp(GmfEnv, -1); + + do + { + res = fscanf(msh->hdl, "%s", str); + }while( (res != EOF) && strcmp(str, "Dimension") ); + + if(res == EOF) + longjmp(GmfEnv, -1); + + safe_fscanf(msh->hdl, "%d", &msh->dim); + } + + if( (msh->dim != 2) && (msh->dim != 3) ) + longjmp(GmfEnv, -1); + + (*PtrVer) = msh->ver; + (*PtrDim) = msh->dim; + + /*------------*/ + /* KW READING */ + /*------------*/ + + /* Read the list of kw present in the file */ + + if(!ScaKwdTab(msh)) + return(0); + + GmfMshTab[ MshIdx ] = msh; + + return(MshIdx); + } + else if(msh->mod == GmfWrite) + { + + /*-----------------------*/ + /* OPEN FILE FOR WRITING */ + /*-----------------------*/ + + msh->cod = 1; + + /* Check if the user provided a valid version number and dimension */ + + va_start(VarArg, mod); + msh->ver = va_arg(VarArg, int); + msh->dim = va_arg(VarArg, int); + va_end(VarArg); + + if( (msh->ver < 1) || (msh->ver > 4) ) + longjmp(GmfEnv, -1); + + if( (msh->ver >= 3) && (sizeof(long) == 4) ) + longjmp(GmfEnv, -1); + + if( (msh->dim != 2) && (msh->dim != 3) ) + longjmp(GmfEnv, -1); + + /* Create the mesh file */ + + if(!(msh->hdl = fopen(msh->FilNam, "wb"))) + longjmp(GmfEnv, -1); + + GmfMshTab[ MshIdx ] = msh; + + + /*------------*/ + /* KW WRITING */ + /*------------*/ + + /* Write the mesh version and dimension */ + + if(msh->typ & Asc) + { + fprintf(msh->hdl, "%s %d\n\n", GmfKwdFmt[ GmfVersionFormatted ][0], msh->ver); + fprintf(msh->hdl, "%s %d\n", GmfKwdFmt[ GmfDimension ][0], msh->dim); + } + else + { + RecWrd(msh, (unsigned char *)&msh->cod); + RecWrd(msh, (unsigned char *)&msh->ver); + GmfSetKwd(MshIdx, GmfDimension, 0); + RecWrd(msh, (unsigned char *)&msh->dim); + } + + return(MshIdx); + } + else + { + free(msh); + return(0); + } +} + + +/*----------------------------------------------------------*/ +/* Close a meshfile in the right way */ +/*----------------------------------------------------------*/ + +int GmfCloseMesh(int MshIdx) +{ + int res = 1; + GmfMshSct *msh; + + if( (MshIdx < 1) || (MshIdx > MaxMsh) ) + return(0); + + msh = GmfMshTab[ MshIdx ]; + RecBlk(msh, msh->buf, 0); + + /* In write down the "End" kw in write mode */ + + if(msh->mod == GmfWrite) + { + if(msh->typ & Asc) + fprintf(msh->hdl, "\n%s\n", GmfKwdFmt[ GmfEnd ][0]); + else + GmfSetKwd(MshIdx, GmfEnd, 0); + } + + /* Close the file and free the mesh structure */ + + if(fclose(msh->hdl)) + res = 0; + + free(msh); + GmfMshTab[ MshIdx ] = NULL; + + return(res); +} + + +/*----------------------------------------------------------*/ +/* Read the number of lines and set the position to this kwd*/ +/*----------------------------------------------------------*/ + +long GmfStatKwd(int MshIdx, int KwdCod, ...) +{ + int i, *PtrNmbTyp, *PtrSolSiz, *TypTab; + GmfMshSct *msh; + KwdSct *kwd; + va_list VarArg; + + if( (MshIdx < 1) || (MshIdx > MaxMsh) ) + return(0); + + msh = GmfMshTab[ MshIdx ]; + + if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) ) + return(0); + + kwd = &msh->KwdTab[ KwdCod ]; + + if(!kwd->NmbLin) + return(0); + + /* Read further arguments if this kw is a sol */ + + if(kwd->typ == SolKwd) + { + va_start(VarArg, KwdCod); + + PtrNmbTyp = va_arg(VarArg, int *); + *PtrNmbTyp = kwd->NmbTyp; + + PtrSolSiz = va_arg(VarArg, int *); + *PtrSolSiz = kwd->SolSiz; + + TypTab = va_arg(VarArg, int *); + + for(i=0;iNmbTyp;i++) + TypTab[i] = kwd->TypTab[i]; + + va_end(VarArg); + } + + return(kwd->NmbLin); +} + + +/*----------------------------------------------------------*/ +/* Set the current file position to a given kwd */ +/*----------------------------------------------------------*/ + +int GmfGotoKwd(int MshIdx, int KwdCod) +{ + GmfMshSct *msh; + KwdSct *kwd; + + if( (MshIdx < 1) || (MshIdx > MaxMsh) ) + return(0); + + msh = GmfMshTab[ MshIdx ]; + + if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) ) + return(0); + + kwd = &msh->KwdTab[ KwdCod ]; + + if(!kwd->NmbLin) + return(0); + + return(fseek(msh->hdl, kwd->pos, SEEK_SET) == 0); +} + + +/*----------------------------------------------------------*/ +/* Write the kwd and set the number of lines */ +/*----------------------------------------------------------*/ + +long GmfSetKwd(int MshIdx, int KwdCod, ...) +{ + int i, *TypTab; + long NmbLin=0, CurPos; + va_list VarArg; + GmfMshSct *msh; + KwdSct *kwd; + + if( (MshIdx < 1) || (MshIdx > MaxMsh) ) + return(0); + + msh = GmfMshTab[ MshIdx ]; + RecBlk(msh, msh->buf, 0); + + if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) ) + return(0); + + kwd = &msh->KwdTab[ KwdCod ]; + + /* Read further arguments if this kw has a header */ + + if(strlen(GmfKwdFmt[ KwdCod ][2])) + { + va_start(VarArg, KwdCod); + NmbLin = va_arg(VarArg, long); + + if(!strcmp(GmfKwdFmt[ KwdCod ][3], "sr")) + { + kwd->NmbTyp = va_arg(VarArg, int); + TypTab = va_arg(VarArg, int *); + + for(i=0;iNmbTyp;i++) + kwd->TypTab[i] = TypTab[i]; + } + + va_end(VarArg); + } + + /* Setup the kwd info */ + + ExpFmt(msh, KwdCod); + + if(!kwd->typ) + return(0); + else if(kwd->typ == InfKwd) + kwd->NmbLin = 1; + else + kwd->NmbLin = NmbLin; + + /* Store the next kwd position in binary file */ + + if( (msh->typ & Bin) && msh->NexKwdPos ) + { + CurPos = ftell(msh->hdl); + + if(fseek(msh->hdl, msh->NexKwdPos, SEEK_SET) != 0) + return(0); + + SetPos(msh, CurPos); + + if(fseek(msh->hdl, CurPos, SEEK_SET) != 0) + return(0); + } + + /* Write the header */ + + if(msh->typ & Asc) + { + fprintf(msh->hdl, "\n%s\n", GmfKwdFmt[ KwdCod ][0]); + + if(kwd->typ != InfKwd) + fprintf(msh->hdl, "%ld\n", kwd->NmbLin); + + /* In case of solution field, write the extended header */ + + if(kwd->typ == SolKwd) + { + fprintf(msh->hdl, "%d ", kwd->NmbTyp); + + for(i=0;iNmbTyp;i++) + fprintf(msh->hdl, "%d ", kwd->TypTab[i]); + + fprintf(msh->hdl, "\n\n"); + } + } + else + { + RecWrd(msh, (unsigned char *)&KwdCod); + msh->NexKwdPos = ftell(msh->hdl); + SetPos(msh, 0); + + if(kwd->typ != InfKwd) + { + if(msh->ver < 4) + { + i = (int)kwd->NmbLin; + RecWrd(msh, (unsigned char *)&i); + } + else + RecDblWrd(msh, (unsigned char *)&kwd->NmbLin); + } + + /* In case of solution field, write the extended header at once */ + + if(kwd->typ == SolKwd) + { + RecWrd(msh, (unsigned char *)&kwd->NmbTyp); + + for(i=0;iNmbTyp;i++) + RecWrd(msh, (unsigned char *)&kwd->TypTab[i]); + } + } + + /* Reset write buffer position */ + msh->pos = 0; + + /* Estimate the total file size and check whether it crosses the 2GB threshold */ + + msh->siz += kwd->NmbLin * kwd->NmbWrd * WrdSiz; + return(kwd->NmbLin); +} + + +/*----------------------------------------------------------*/ +/* Read a full line from the current kwd */ +/*----------------------------------------------------------*/ + +int GmfGetLin(int MshIdx, int KwdCod, ...) +{ + int i, j; + float *FltSolTab; + double *DblSolTab; + va_list VarArg; + GmfMshSct *msh = GmfMshTab[ MshIdx ]; + KwdSct *kwd = &msh->KwdTab[ KwdCod ]; + + /* Save the current stack environment for longjmp */ + + if(setjmp(GmfEnv) != 0) + return(0); + + /* Start decoding the arguments */ + + va_start(VarArg, KwdCod); + + switch(kwd->typ) + { + case InfKwd : case RegKwd : case CmtKwd : + { + if(msh->typ & Asc) + { + for(i=0;iSolSiz;i++) + if(kwd->fmt[i] == 'r') + if(msh->ver <= 1) + safe_fscanf(msh->hdl, "%f", va_arg(VarArg, float *)); + else + safe_fscanf(msh->hdl, "%lf", va_arg(VarArg, double *)); + else if(kwd->fmt[i] == 'i') + if(msh->ver <= 3) + safe_fscanf(msh->hdl, "%d", va_arg(VarArg, int *)); + else + safe_fscanf(msh->hdl, "%ld", va_arg(VarArg, long *)); + else if(kwd->fmt[i] == 'c') + safe_fgets(va_arg(VarArg, char *), WrdSiz * FilStrSiz, msh->hdl); + } + else + { + for(i=0;iSolSiz;i++) + if(kwd->fmt[i] == 'r') + if(msh->ver <= 1) + ScaWrd(msh, (unsigned char *)va_arg(VarArg, float *)); + else + ScaDblWrd(msh, (unsigned char *)va_arg(VarArg, double *)); + else if(kwd->fmt[i] == 'i') + if(msh->ver <= 3) + ScaWrd(msh, (unsigned char *)va_arg(VarArg, int *)); + else + ScaDblWrd(msh, (unsigned char *)va_arg(VarArg, long *)); + else if(kwd->fmt[i] == 'c') + fread(va_arg(VarArg, char *), WrdSiz, FilStrSiz, msh->hdl); + } + }break; + + case SolKwd : + { + if(msh->ver == 1) + { + FltSolTab = va_arg(VarArg, float *); + + if(msh->typ & Asc) + for(j=0;jSolSiz;j++) + safe_fscanf(msh->hdl, "%f", &FltSolTab[j]); + else + for(j=0;jSolSiz;j++) + ScaWrd(msh, (unsigned char *)&FltSolTab[j]); + } + else + { + DblSolTab = va_arg(VarArg, double *); + + if(msh->typ & Asc) + for(j=0;jSolSiz;j++) + safe_fscanf(msh->hdl, "%lf", &DblSolTab[j]); + else + for(j=0;jSolSiz;j++) + ScaDblWrd(msh, (unsigned char *)&DblSolTab[j]); + } + }break; + } + + va_end(VarArg); + + return(1); +} + + +/*----------------------------------------------------------*/ +/* Write a full line from the current kwd */ +/*----------------------------------------------------------*/ + +void GmfSetLin(int MshIdx, int KwdCod, ...) +{ + int i, j, pos, *IntBuf; + long *LngBuf; + float *FltSolTab, *FltBuf; + double *DblSolTab, *DblBuf; + va_list VarArg; + GmfMshSct *msh = GmfMshTab[ MshIdx ]; + KwdSct *kwd = &msh->KwdTab[ KwdCod ]; + + /* Start decoding the arguments */ + + va_start(VarArg, KwdCod); + + if(kwd->typ != SolKwd) + { + if(msh->typ & Asc) + { + for(i=0;iSolSiz;i++) + { + if(kwd->fmt[i] == 'r') + { + if(msh->ver <= 1) + fprintf(msh->hdl, "%g ", va_arg(VarArg, double)); + else + fprintf(msh->hdl, "%.15g ", va_arg(VarArg, double)); + } + else if(kwd->fmt[i] == 'i') + { + if(msh->ver <= 3) + fprintf(msh->hdl, "%d ", va_arg(VarArg, int)); + else + fprintf(msh->hdl, "%ld ", va_arg(VarArg, long)); + } + else if(kwd->fmt[i] == 'c') + fprintf(msh->hdl, "%s", va_arg(VarArg, char *)); + } + } + else + { + pos = 0; + + for(i=0;iSolSiz;i++) + { + if(kwd->fmt[i] == 'r') + { + if(msh->ver <= 1) + { + FltBuf = (void *)&msh->buf[ pos ]; + *FltBuf = (float)va_arg(VarArg, double); + pos += 4; + } + else + { + DblBuf = (void *)&msh->buf[ pos ]; + *DblBuf = va_arg(VarArg, double); + pos += 8; + } + } + else if(kwd->fmt[i] == 'i') + { + if(msh->ver <= 3) + { + IntBuf = (void *)&msh->buf[ pos ]; + *IntBuf = va_arg(VarArg, int); + pos += 4; + } + else + { + LngBuf = (void *)&msh->buf[ pos ]; + *LngBuf = va_arg(VarArg, long); + pos += 8; + } + } + else if(kwd->fmt[i] == 'c') + { + memset(&msh->buf[ pos ], 0, FilStrSiz * WrdSiz); + strncpy(&msh->buf[ pos ], va_arg(VarArg, char *), FilStrSiz * WrdSiz); + pos += FilStrSiz; + } + } + + RecBlk(msh, msh->buf, kwd->NmbWrd); + } + } + else + { + if(msh->ver == 1) + { + FltSolTab = va_arg(VarArg, float *); + + if(msh->typ & Asc) + for(j=0;jSolSiz;j++) + fprintf(msh->hdl, "%g ", (double)FltSolTab[j]); + else + RecBlk(msh, (unsigned char *)FltSolTab, kwd->NmbWrd); + } + else + { + DblSolTab = va_arg(VarArg, double *); + + if(msh->typ & Asc) + for(j=0;jSolSiz;j++) + fprintf(msh->hdl, "%.15g ", DblSolTab[j]); + else + RecBlk(msh, (unsigned char *)DblSolTab, kwd->NmbWrd); + } + } + + va_end(VarArg); + + if(msh->typ & Asc) + fprintf(msh->hdl, "\n"); +} + + +/*----------------------------------------------------------*/ +/* Private procedure for transmesh : copy a whole line */ +/*----------------------------------------------------------*/ + +int GmfCpyLin(int InpIdx, int OutIdx, int KwdCod) +{ + char s[ WrdSiz * FilStrSiz ]; + double d; + float f; + int i, a; + long l; + GmfMshSct *InpMsh = GmfMshTab[ InpIdx ], *OutMsh = GmfMshTab[ OutIdx ]; + KwdSct *kwd = &InpMsh->KwdTab[ KwdCod ]; + + /* Save the current stack environment for longjmp */ + + if(setjmp(GmfEnv) != 0) + return(0); + + for(i=0;iSolSiz;i++) + { + if(kwd->fmt[i] == 'r') + { + if(InpMsh->ver == 1) + { + if(InpMsh->typ & Asc) + safe_fscanf(InpMsh->hdl, "%f", &f); + else + ScaWrd(InpMsh, (unsigned char *)&f); + + d = (double)f; + } + else + { + if(InpMsh->typ & Asc) + safe_fscanf(InpMsh->hdl, "%lf", &d); + else + ScaDblWrd(InpMsh, (unsigned char *)&d); + + f = (float)d; + } + + if(OutMsh->ver == 1) + if(OutMsh->typ & Asc) + fprintf(OutMsh->hdl, "%g ", (double)f); + else + RecWrd(OutMsh, (unsigned char *)&f); + else + if(OutMsh->typ & Asc) + fprintf(OutMsh->hdl, "%.15g ", d); + else + RecDblWrd(OutMsh, (unsigned char *)&d); + } + else if(kwd->fmt[i] == 'i') + { + if(InpMsh->ver <= 3) + { + if(InpMsh->typ & Asc) + safe_fscanf(InpMsh->hdl, "%d", &a); + else + ScaWrd(InpMsh, (unsigned char *)&a); + + l = (long)a; + } + else + { + if(InpMsh->typ & Asc) + safe_fscanf(InpMsh->hdl, "%ld", &l); + else + ScaDblWrd(InpMsh, (unsigned char *)&l); + + a = (int)l; + } + + if(OutMsh->ver <= 3) + { + if(OutMsh->typ & Asc) + fprintf(OutMsh->hdl, "%d ", a); + else + RecWrd(OutMsh, (unsigned char *)&a); + } + else + { + if(OutMsh->typ & Asc) + fprintf(OutMsh->hdl, "%ld ", l); + else + RecDblWrd(OutMsh, (unsigned char *)&l); + } + } + else if(kwd->fmt[i] == 'c') + { + memset(s, 0, FilStrSiz * WrdSiz); + + if(InpMsh->typ & Asc) + safe_fgets(s, WrdSiz * FilStrSiz, InpMsh->hdl); + else + fread(s, WrdSiz, FilStrSiz, InpMsh->hdl); + + if(OutMsh->typ & Asc) + fprintf(OutMsh->hdl, "%s", s); + else + fwrite(s, WrdSiz, FilStrSiz, OutMsh->hdl); + } + } + + if(OutMsh->typ & Asc) + fprintf(OutMsh->hdl, "\n"); + + return(1); +} + + +/*----------------------------------------------------------*/ +/* Bufferized reading of all keyword's lines */ +/*----------------------------------------------------------*/ + +extern int GmfGetBlock(int MshIdx, int KwdCod, ...) +{ + char *UsrDat[ GmfMaxTyp ], *FilBuf=NULL, *FilPos; + char *StrTab[5] = { "", "%f", "%lf", "%d", "%ld" }; + int b, i, j, LinSiz, *FilPtrI32, *UsrPtrI32, FilTyp[ GmfMaxTyp ], UsrTyp[ GmfMaxTyp ], SizTab[5] = {0,4,8,4,8}; + long NmbLin, *FilPtrI64, *UsrPtrI64; + float *FilPtrR32, *UsrPtrR32; + double *FilPtrR64, *UsrPtrR64; + size_t UsrLen[ GmfMaxTyp ]; + va_list VarArg; + GmfMshSct *msh = GmfMshTab[ MshIdx ]; + KwdSct *kwd = &msh->KwdTab[ KwdCod ]; + + /* Save the current stack environment for longjmp */ + + if(setjmp(GmfEnv) != 0) + { + if(FilBuf) + free(FilBuf); + + return(0); + } + + /* Check mesh and keyword */ + + if( (MshIdx < 1) || (MshIdx > MaxMsh) ) + return(0); + + if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) ) + return(0); + + if(!kwd->NmbLin) + return(0); + + /* Make shure it's not a simple information keyword */ + + if( (kwd->typ != RegKwd) && (kwd->typ != SolKwd) ) + return(0); + + /* Start decoding the arguments */ + + va_start(VarArg, KwdCod); + LinSiz = 0; + + if(kwd->typ == RegKwd) + { + for(i=0;iSolSiz;i++) + { + /* Get the user's data type */ + + UsrTyp[i] = va_arg(VarArg, int); + + if(kwd->fmt[i] == 'r') + { + /* Get the data pointer */ + + if(UsrTyp[i] == GmfFloat) + UsrDat[i] = (char *)va_arg(VarArg, float *); + else if(UsrTyp[i] == GmfDouble) + UsrDat[i] = (char *)va_arg(VarArg, double *); + else + return(0); + + /* Get the file's data type */ + + if(msh->ver <= 1) + FilTyp[i] = GmfFloat; + else + FilTyp[i] = GmfDouble; + } + else + { + /* Get the data pointer */ + + if(UsrTyp[i] == GmfInt) + UsrDat[i] = (char *)va_arg(VarArg, int *); + else if(UsrTyp[i] == GmfLong) + UsrDat[i] = (char *)va_arg(VarArg, long *); + else + return(0); + + /* Get the file's data type */ + + if(msh->ver <= 3) + FilTyp[i] = GmfInt; + else + FilTyp[i] = GmfLong; + } + + /* Then get the data second adress and compute the stride */ + + UsrLen[i] = (size_t)(va_arg(VarArg, char *) - UsrDat[i]); + LinSiz += SizTab[ FilTyp[i] ]; + } + } + else + { + /* Get the user's data type */ + + UsrTyp[0] = va_arg(VarArg, int); + + /* Get the data pointer */ + + if(UsrTyp[0] == GmfFloat) + UsrDat[0] = (char *)va_arg(VarArg, float *); + else if(UsrTyp[0] == GmfDouble) + UsrDat[0] = (char *)va_arg(VarArg, double *); + else + return(0); + + /* Get the file's data type */ + + if(msh->ver <= 1) + FilTyp[0] = GmfFloat; + else + FilTyp[0] = GmfDouble; + + /* Then get the data second adress and compute the stride */ + + UsrLen[0] = (size_t)(va_arg(VarArg, char *) - UsrDat[0]); + + for(i=1;iSolSiz;i++) + { + UsrTyp[i] = UsrTyp[0]; + UsrDat[i] = UsrDat[i-1] + SizTab[ UsrTyp[0] ]; + UsrLen[i] = UsrLen[0]; + FilTyp[i] = FilTyp[0]; + } + + LinSiz = kwd->SolSiz * SizTab[ FilTyp[0] ]; + } + + va_end(VarArg); + + /* Read the whole kwd data */ + + if(msh->typ & Asc) + { + for(i=0;iNmbLin;i++) + for(j=0;jSolSiz;j++) + { + safe_fscanf(msh->hdl, StrTab[ UsrTyp[j] ], UsrDat[j]); + UsrDat[j] += UsrLen[j]; + } + } + else + { + /* Allocate a small buffer and split the main loop into chunks */ + + if(!(FilBuf = malloc((size_t)(BufSiz * LinSiz)))) + return(0); + + for(b=0;b<=kwd->NmbLin/BufSiz;b++) + { + if(b == kwd->NmbLin/BufSiz) + NmbLin = kwd->NmbLin - b * BufSiz; + else + NmbLin = BufSiz; + + /* Read a chunk of data */ + + if(fread(FilBuf, (size_t)LinSiz, (size_t)NmbLin, msh->hdl) != NmbLin) + longjmp(GmfEnv, -1); + + FilPos = FilBuf; + + /* Then decode it and store it in the user's data structure */ + + for(i=0;iSolSiz;j++) + { + if(msh->cod != 1) + SwpWrd(FilPos, SizTab[ FilTyp[j] ]); + + if(FilTyp[j] == GmfInt) + { + FilPtrI32 = (int *)FilPos; + + if(UsrTyp[j] == GmfInt) + { + UsrPtrI32 = (int *)UsrDat[j]; + *UsrPtrI32 = *FilPtrI32; + } + else + { + UsrPtrI64 = (long *)UsrDat[j]; + *UsrPtrI64 = (long)*FilPtrI32; + } + } + else if(FilTyp[j] == GmfLong) + { + FilPtrI64 = (long *)FilPos; + + if(UsrTyp[j] == GmfLong) + { + UsrPtrI64 = (long *)UsrDat[j]; + *UsrPtrI64 = *FilPtrI64; + } + else + { + UsrPtrI32 = (int *)UsrDat[j]; + *UsrPtrI32 = (int)*FilPtrI64; + } + } + else if(FilTyp[j] == GmfFloat) + { + FilPtrR32 = (float *)FilPos; + + if(UsrTyp[j] == GmfFloat) + { + UsrPtrR32 = (float *)UsrDat[j]; + *UsrPtrR32 = *FilPtrR32; + } + else + { + UsrPtrR64 = (double *)UsrDat[j]; + *UsrPtrR64 = (double)*FilPtrR32; + } + } + else if(FilTyp[j] == GmfDouble) + { + FilPtrR64 = (double *)FilPos; + + if(UsrTyp[j] == GmfDouble) + { + UsrPtrR64 = (double *)UsrDat[j]; + *UsrPtrR64 = *FilPtrR64; + } + else + { + UsrPtrR32 = (float *)UsrDat[j]; + *UsrPtrR32 = (float)*FilPtrR64; + } + } + + FilPos += SizTab[ FilTyp[j] ]; + UsrDat[j] += UsrLen[j]; + } + } + + free(FilBuf); + } + + return(1); +} + + +/*----------------------------------------------------------*/ +/* Bufferized writing of all keyword's lines */ +/*----------------------------------------------------------*/ + +extern int GmfSetBlock(int MshIdx, int KwdCod, ...) +{ + char *UsrDat[ GmfMaxTyp ], *FilBuf, *FilPos; + char *StrTab[5] = { "", "%g", "%.15g", "%d", "%ld" }; + int i, j, LinSiz, *FilPtrI32, *UsrPtrI32, FilTyp[ GmfMaxTyp ], UsrTyp[ GmfMaxTyp ]; + int SizTab[5] = {0,4,8,4,8}; + long NmbLin, b, *FilPtrI64, *UsrPtrI64; + float *FilPtrR32, *UsrPtrR32; + double *FilPtrR64, *UsrPtrR64; + size_t UsrLen[ GmfMaxTyp ]; + va_list VarArg; + GmfMshSct *msh = GmfMshTab[ MshIdx ]; + KwdSct *kwd = &msh->KwdTab[ KwdCod ]; + + /* Check mesh and keyword */ + + if( (MshIdx < 1) || (MshIdx > MaxMsh) ) + return(0); + + if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) ) + return(0); + + if(!kwd->NmbLin) + return(0); + + if( (kwd->typ != RegKwd) && (kwd->typ != SolKwd) ) + return(0); + + /* Start decoding the arguments */ + + va_start(VarArg, KwdCod); + LinSiz = 0; + + if(kwd->typ == RegKwd) + { + for(i=0;iSolSiz;i++) + { + /* Get the user's data type */ + + UsrTyp[i] = va_arg(VarArg, int); + + if(kwd->fmt[i] == 'r') + { + /* Get the data pointer */ + + if(UsrTyp[i] == GmfFloat) + UsrDat[i] = (char *)va_arg(VarArg, float *); + else if(UsrTyp[i] == GmfDouble) + UsrDat[i] = (char *)va_arg(VarArg, double *); + else + return(0); + + /* Get the file's data type */ + + if(msh->ver <= 1) + FilTyp[i] = GmfFloat; + else + FilTyp[i] = GmfDouble; + } + else + { + /* Get the data pointer */ + + if(UsrTyp[i] == GmfInt) + UsrDat[i] = (char *)va_arg(VarArg, int *); + else if(UsrTyp[i] == GmfLong) + UsrDat[i] = (char *)va_arg(VarArg, long *); + else + return(0); + + /* Get the file's data type */ + + if(msh->ver <= 3) + FilTyp[i] = GmfInt; + else + FilTyp[i] = GmfLong; + } + + /* Then get the data second adress and compute the stride */ + + UsrLen[i] = (size_t)(va_arg(VarArg, char *) - UsrDat[i]); + LinSiz += SizTab[ FilTyp[i] ]; + } + } + else + { + /* Get the user's data type */ + + UsrTyp[0] = va_arg(VarArg, int); + + /* Get the data pointer */ + + if(UsrTyp[0] == GmfFloat) + UsrDat[0] = (char *)va_arg(VarArg, float *); + else if(UsrTyp[0] == GmfDouble) + UsrDat[0] = (char *)va_arg(VarArg, double *); + else + return(0); + + /* Get the file's data type */ + + if(msh->ver <= 1) + FilTyp[0] = GmfFloat; + else + FilTyp[0] = GmfDouble; + + /* Then get the data second adress and compute the stride */ + + UsrLen[0] = (size_t)(va_arg(VarArg, char *) - UsrDat[0]); + + for(i=1;iSolSiz;i++) + { + UsrTyp[i] = UsrTyp[0]; + UsrDat[i] = UsrDat[i-1] + SizTab[ UsrTyp[0] ]; + UsrLen[i] = UsrLen[0]; + FilTyp[i] = FilTyp[0]; + } + + LinSiz = kwd->SolSiz * SizTab[ FilTyp[0] ]; + } + + va_end(VarArg); + + /* Write the whole kwd data */ + + if(msh->typ & Asc) + { + for(i=0;iNmbLin;i++) + for(j=0;jSolSiz;j++) + { + if(UsrTyp[j] == GmfFloat) + { + UsrPtrR32 = (float *)UsrDat[j]; + fprintf(msh->hdl, StrTab[ UsrTyp[j] ], (double)*UsrPtrR32); + } + else if(UsrTyp[j] == GmfDouble) + { + UsrPtrR64 = (double *)UsrDat[j]; + fprintf(msh->hdl, StrTab[ UsrTyp[j] ], *UsrPtrR64); + } + else if(UsrTyp[j] == GmfInt) + { + UsrPtrI32 = (int *)UsrDat[j]; + fprintf(msh->hdl, StrTab[ UsrTyp[j] ], *UsrPtrI32); + } + else if(UsrTyp[j] == GmfLong) + { + UsrPtrI64 = (long *)UsrDat[j]; + fprintf(msh->hdl, StrTab[ UsrTyp[j] ], *UsrPtrI64); + } + + if(j < kwd->SolSiz -1) + fprintf(msh->hdl, " "); + else + fprintf(msh->hdl, "\n"); + + UsrDat[j] += UsrLen[j]; + } + } + else + { + if(!(FilBuf = malloc((size_t)BufSiz * (size_t)LinSiz))) + return(0); + + for(b=0;b<=kwd->NmbLin/BufSiz;b++) + { + if(b == kwd->NmbLin/BufSiz) + NmbLin = kwd->NmbLin - b * BufSiz; + else + NmbLin = BufSiz; + + FilPos = FilBuf; + + for(i=0;iSolSiz;j++) + { + if(FilTyp[j] == GmfInt) + { + FilPtrI32 = (int *)FilPos; + + if(UsrTyp[j] == GmfInt) + { + UsrPtrI32 = (int *)UsrDat[j]; + *FilPtrI32 = *UsrPtrI32; + } + else + { + UsrPtrI64 = (long *)UsrDat[j]; + *FilPtrI32 = (int)*UsrPtrI64; + } + } + else if(FilTyp[j] == GmfLong) + { + FilPtrI64 = (long *)FilPos; + + if(UsrTyp[j] == GmfLong) + { + UsrPtrI64 = (long *)UsrDat[j]; + *FilPtrI64 = *UsrPtrI64; + } + else + { + UsrPtrI32 = (int *)UsrDat[j]; + *FilPtrI64 = (long)*UsrPtrI32; + } + } + else if(FilTyp[j] == GmfFloat) + { + FilPtrR32 = (float *)FilPos; + + if(UsrTyp[j] == GmfFloat) + { + UsrPtrR32 = (float *)UsrDat[j]; + *FilPtrR32 = *UsrPtrR32; + } + else + { + UsrPtrR64 = (double *)UsrDat[j]; + *FilPtrR32 = (float)*UsrPtrR64; + } + } + else if(FilTyp[j] == GmfDouble) + { + FilPtrR64 = (double *)FilPos; + + if(UsrTyp[j] == GmfDouble) + { + UsrPtrR64 = (double *)UsrDat[j]; + *FilPtrR64 = *UsrPtrR64; + } + else + { + UsrPtrR32 = (float *)UsrDat[j]; + *FilPtrR64 = (double)*UsrPtrR32; + } + } + + FilPos += SizTab[ FilTyp[j] ]; + UsrDat[j] += UsrLen[j]; + } + + if(fwrite(FilBuf, (size_t)LinSiz, (size_t)NmbLin, msh->hdl) != NmbLin) + { + free(FilBuf); + return(0); + } + } + + free(FilBuf); + } + + return(1); +} + + +/*----------------------------------------------------------*/ +/* Find every kw present in a meshfile */ +/*----------------------------------------------------------*/ + +static int ScaKwdTab(GmfMshSct *msh) +{ + int KwdCod, c; + long NexPos, CurPos, EndPos; + char str[ GmfStrSiz ]; + + if(msh->typ & Asc) + { + /* Scan each string in the file until the end */ + + while(fscanf(msh->hdl, "%s", str) != EOF) + { + /* Fast test in order to reject quickly the numeric values */ + + if(isalpha(str[0])) + { + /* Search which kwd code this string is associated with, + then get its header and save the curent position in file (just before the data) */ + + for(KwdCod=1; KwdCod<= GmfMaxKwd; KwdCod++) + if(!strcmp(str, GmfKwdFmt[ KwdCod ][0])) + { + ScaKwdHdr(msh, KwdCod); + break; + } + } + else if(str[0] == '#') + while((c = fgetc(msh->hdl)) != '\n' && c != EOF); + } + } + else + { + /* Get file size */ + + CurPos = ftell(msh->hdl); + + if(fseek(msh->hdl, 0, SEEK_END) != 0) + longjmp(GmfEnv, -1); + + EndPos = ftell(msh->hdl); + + if(fseek(msh->hdl, CurPos, SEEK_SET) != 0) + longjmp(GmfEnv, -1); + + /* Jump through kwd positions in the file */ + + do + { + /* Get the kwd code and the next kwd position */ + + ScaWrd(msh, (unsigned char *)&KwdCod); + NexPos = GetPos(msh); + + if(NexPos > EndPos) + longjmp(GmfEnv, -1); + + /* Check if this kwd belongs to this mesh version */ + + if( (KwdCod >= 1) && (KwdCod <= GmfMaxKwd) ) + ScaKwdHdr(msh, KwdCod); + + /* Go to the next kwd */ + + if(NexPos && (fseek(msh->hdl, NexPos, SEEK_SET) != 0)) + longjmp(GmfEnv, -1); + }while(NexPos && (KwdCod != GmfEnd)); + } + + return(1); +} + + +/*----------------------------------------------------------*/ +/* Read and setup the keyword's header */ +/*----------------------------------------------------------*/ + +static void ScaKwdHdr(GmfMshSct *msh, int KwdCod) +{ + int i; + KwdSct *kwd = &msh->KwdTab[ KwdCod ]; + + if(!strcmp("i", GmfKwdFmt[ KwdCod ][2])) + if(msh->typ & Asc) + safe_fscanf(msh->hdl, "%ld", &kwd->NmbLin); + else + if(msh->ver <= 3) + { + ScaWrd(msh, (unsigned char *)&i); + kwd->NmbLin = i; + } + else + ScaDblWrd(msh, (unsigned char *)&kwd->NmbLin); + else + kwd->NmbLin = 1; + + if(!strcmp("sr", GmfKwdFmt[ KwdCod ][3])) + { + if(msh->typ & Asc) + { + safe_fscanf(msh->hdl, "%d", &kwd->NmbTyp); + + for(i=0;iNmbTyp;i++) + safe_fscanf(msh->hdl, "%d", &kwd->TypTab[i]); + } + else + { + ScaWrd(msh, (unsigned char *)&kwd->NmbTyp); + + for(i=0;iNmbTyp;i++) + ScaWrd(msh, (unsigned char *)&kwd->TypTab[i]); + } + } + + ExpFmt(msh, KwdCod); + kwd->pos = ftell(msh->hdl); +} + + +/*----------------------------------------------------------*/ +/* Expand the compacted format and compute the line size */ +/*----------------------------------------------------------*/ + +static void ExpFmt(GmfMshSct *msh, int KwdCod) +{ + int i, j, TmpSiz=0, IntWrd, FltWrd; + char chr; + const char *InpFmt = GmfKwdFmt[ KwdCod ][3]; + KwdSct *kwd = &msh->KwdTab[ KwdCod ]; + + /* Set the kwd's type */ + + if(!strlen(GmfKwdFmt[ KwdCod ][2])) + kwd->typ = InfKwd; + else if(!strcmp(InpFmt, "sr")) + kwd->typ = SolKwd; + else + kwd->typ = RegKwd; + + /* Get the solution-field's size */ + + if(kwd->typ == SolKwd) + for(i=0;iNmbTyp;i++) + switch(kwd->TypTab[i]) + { + case GmfSca : TmpSiz += 1; break; + case GmfVec : TmpSiz += msh->dim; break; + case GmfSymMat : TmpSiz += (msh->dim * (msh->dim+1)) / 2; break; + case GmfMat : TmpSiz += msh->dim * msh->dim; break; + } + + /* Scan each character from the format string */ + + i = kwd->SolSiz = kwd->NmbWrd = 0; + + while(i < (int)strlen(InpFmt)) + { + chr = InpFmt[ i++ ]; + + if(chr == 'd') + { + chr = InpFmt[i++]; + + for(j=0;jdim;j++) + kwd->fmt[ kwd->SolSiz++ ] = chr; + } + else if(chr == 's') + { + chr = InpFmt[i++]; + + for(j=0;jfmt[ kwd->SolSiz++ ] = chr; + } + else + kwd->fmt[ kwd->SolSiz++ ] = chr; + } + + if(msh->ver <= 1) + FltWrd = 1; + else + FltWrd = 2; + + if(msh->ver <= 3) + IntWrd = 1; + else + IntWrd = 2; + + for(i=0;iSolSiz;i++) + switch(kwd->fmt[i]) + { + case 'i' : kwd->NmbWrd += IntWrd; break; + case 'c' : kwd->NmbWrd += FilStrSiz; break; + case 'r' : kwd->NmbWrd += FltWrd;break; + } +} + + +/*----------------------------------------------------------*/ +/* Read a four bytes word from a mesh file */ +/*----------------------------------------------------------*/ + +static void ScaWrd(GmfMshSct *msh, void *ptr) +{ + if( fread(ptr, WrdSiz, 1, msh->hdl) != 1) + longjmp(GmfEnv, -1); + + if(msh->cod != 1) + SwpWrd((char *)ptr, WrdSiz); +} + + +/*----------------------------------------------------------*/ +/* Read an eight bytes word from a mesh file */ +/*----------------------------------------------------------*/ + +static void ScaDblWrd(GmfMshSct *msh, void *ptr) +{ + if( fread(ptr, WrdSiz, 2, msh->hdl) != 2 ) + longjmp(GmfEnv, -1); + + if(msh->cod != 1) + SwpWrd((char *)ptr, 2 * WrdSiz); +} + + +/*----------------------------------------------------------*/ +/* Read a 4 or 8 bytes position in mesh file */ +/*----------------------------------------------------------*/ + +static long GetPos(GmfMshSct *msh) +{ + int IntVal; + long pos; + + if(msh->ver >= 3) + ScaDblWrd(msh, (unsigned char*)&pos); + else + { + ScaWrd(msh, (unsigned char*)&IntVal); + pos = (long)IntVal; + } + + return(pos); +} + + +/*----------------------------------------------------------*/ +/* Write a four bytes word to a mesh file */ +/*----------------------------------------------------------*/ + +static void RecWrd(GmfMshSct *msh, const void *wrd) +{ + fwrite(wrd, WrdSiz, 1, msh->hdl); +} + + +/*----------------------------------------------------------*/ +/* Write an eight bytes word to a mesh file */ +/*----------------------------------------------------------*/ + +static void RecDblWrd(GmfMshSct *msh, const void *wrd) +{ + fwrite(wrd, WrdSiz, 2, msh->hdl); +} + + +/*----------------------------------------------------------*/ +/* Write a block of four bytes word to a mesh file */ +/*----------------------------------------------------------*/ + +static void RecBlk(GmfMshSct *msh, const void *blk, int siz) +{ + /* Copy this line-block into the main mesh buffer */ + + if(siz) + { + memcpy(&msh->blk[ msh->pos ], blk, (size_t)(siz * WrdSiz)); + msh->pos += siz * WrdSiz; + } + + /* When the buffer is full or this procedure is called with a 0 size, flush the cache on disk */ + + if( (msh->pos > BufSiz) || (!siz && msh->pos) ) + { + fwrite(msh->blk, 1, (size_t)msh->pos, msh->hdl); + msh->pos = 0; + } +} + + +/*----------------------------------------------------------*/ +/* Write a 4 or 8 bytes position in a mesh file */ +/*----------------------------------------------------------*/ + +static void SetPos(GmfMshSct *msh, long pos) +{ + int IntVal; + + if(msh->ver >= 3) + RecDblWrd(msh, (unsigned char*)&pos); + else + { + IntVal = (int)pos; + RecWrd(msh, (unsigned char*)&IntVal); + } +} + + +/*----------------------------------------------------------*/ +/* Endianness conversion */ +/*----------------------------------------------------------*/ + +static void SwpWrd(char *wrd, int siz) +{ + char swp; + int i; + + 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 <w6syw|CAgsy!u7PULKq3Cdl(c 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%0D-FCR2D*WTj*$N%tQqWM#65*X~vk#am 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 z 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 bLZ~jTCeE%u_dif%TwI)}w6v1SQmFqQ+)!Nj literal 0 HcmV?d00001 diff --git a/thirdparty/lm6/quad.mesh b/thirdparty/lm6/quad.mesh new file mode 100644 index 00000000..92e0b807 --- /dev/null +++ b/thirdparty/lm6/quad.mesh @@ -0,0 +1,3973 @@ +MeshVersionFormatted 2 + +Dimension 3 + +Vertices +1982 +0.491814 0.357873 0.793755 0 +-0.185247 0.576968 0.795482 0 +-0.605974 0.00211274 0.795482 0 +-0.189262 -0.575662 0.795483 0 +0.489311 -0.355541 0.796345 0 +0.18688 0.575248 -0.796345 0 +-0.492393 0.35579 -0.794332 0 +-0.490535 -0.358348 -0.794332 0 +0.189225 -0.577262 -0.794332 0 +0.608238 -0.000444233 -0.793755 0 +0.793286 0.579422 0.186998 0 +0.301117 0.934866 -0.188027 0 +-0.304976 0.933315 0.189508 0 +-0.795969 0.576124 -0.185778 0 +-0.981878 -0.00163909 0.189508 0 +-0.793895 -0.57898 -0.185778 0 +-0.301858 -0.934328 0.189508 0 +0.305315 -0.933953 -0.185778 0 +0.795319 -0.575807 0.189508 0 +0.98259 0.0017648 -0.185778 0 +0.000569249 0.000222193 1 0 +0.000590977 0.000154955 -1 0 +0.276627 0.850311 0.447715 0 +-0.723276 0.525844 0.447616 0 +-0.723612 -0.525382 0.447616 0 +0.276059 -0.850548 0.447616 0 +0.894253 -0.000431273 0.447562 0 +-0.276504 0.850312 -0.44779 0 +-0.894126 -0.000268137 -0.447815 0 +-0.276045 -0.850447 -0.447815 0 +0.723521 -0.525337 -0.447815 0 +0.723249 0.525857 -0.447643 0 +0.256714 -0.149484 0.954763 0 +0.524775 0.00459358 0.851228 0 +0.220485 0.200032 0.954566 0 +0.119822 0.271828 -0.954763 0 +0.427252 0.304739 -0.851228 0 +0.295951 -0.0322319 -0.954566 0 +0.0832626 0.750053 0.655992 0 +0.1675 0.499739 0.849826 0 +0.420045 0.656133 0.626804 0 +-0.687614 0.310969 0.655991 0 +-0.423351 0.313193 0.850108 0 +-0.493357 0.605724 0.624116 0 +-0.508233 -0.557865 0.655991 0 +-0.428687 -0.305849 0.850108 0 +-0.728533 -0.282031 0.624116 0 +0.373505 -0.655741 0.656 0 +0.158296 -0.502146 0.850172 0 +0.0430982 -0.780028 0.624116 0 +0.738017 0.145904 0.658679 0 +0.756916 -0.201853 0.621397 0 +-0.0832595 0.750045 -0.656002 0 +-0.167033 0.499277 -0.85019 0 +-0.420046 0.65614 -0.626795 0 +-0.739145 0.149499 -0.656608 0 +-0.526557 -0.00446402 -0.850128 0 +-0.753829 -0.196733 -0.626793 0 +-0.370591 -0.656771 -0.656608 0 +-0.15847 -0.502165 -0.850128 0 +-0.0458414 -0.777727 -0.626793 0 +0.510108 -0.555406 -0.656608 0 +0.429233 -0.305862 -0.849828 0 +0.725492 -0.283925 -0.626801 0 +0.682827 0.315755 -0.658681 0 +0.493713 0.608207 -0.621396 0 +-0.124845 0.269191 0.954857 0 +-0.294571 -0.0355551 0.954864 0 +-0.0571566 -0.29117 0.954859 0 +0.0572024 -0.29117 -0.954856 0 +-0.259226 -0.144362 -0.954863 0 +-0.217382 0.201984 -0.954856 0 +0.689546 0.502211 0.521833 0 +0.540126 0.777696 0.321378 0 +0.584161 0.811637 -0.0014475 0 +0.278426 0.946647 0.16177 0 +-0.0033168 0.999989 0.00336067 0 +-0.00345595 0.92949 0.368602 0 +-0.260374 0.807108 0.529888 0 +-0.575197 0.753058 0.319162 0 +-0.591381 0.806391 -0.00140495 0 +-0.814271 0.557336 0.161773 0 +-0.952064 0.30588 0.00335348 0 +-0.885066 0.283941 0.368602 0 +-0.848066 0.00177962 0.529888 0 +-0.893946 -0.314337 0.319162 0 +-0.94967 -0.313248 -0.00140496 0 +-0.781681 -0.602192 0.161773 0 +-0.585113 -0.810945 0.00335348 0 +-0.543545 -0.754005 0.368602 0 +-0.263759 -0.806009 0.529888 0 +0.0227073 -0.947329 0.319162 0 +0.00445275 -0.999989 -0.00140495 0 +0.331165 -0.929511 0.161773 0 +0.590445 -0.807071 0.00335348 0 +0.549137 -0.749942 0.368602 0 +0.685075 -0.499913 0.529867 0 +0.90798 -0.271149 0.319159 0 +0.952422 -0.304779 -0.00140495 0 +0.986353 0.0277227 0.161775 0 +0.950017 0.31218 0.00341563 0 +0.880937 0.291644 0.37245 0 +-0.689564 0.502267 -0.521757 0 +-0.539139 0.779923 -0.317607 0 +-0.270809 0.948542 -0.1635 0 +0.00359873 0.928207 -0.371794 0 +0.260381 0.807158 -0.52981 0 +-0.690771 -0.500605 -0.521757 0 +-0.908354 -0.271743 -0.317607 0 +-0.985802 0.0355612 -0.163502 0 +-0.879614 0.291205 -0.375873 0 +0.262644 -0.811658 -0.521757 0 +-0.0222541 -0.947869 -0.317607 0 +-0.33845 -0.926564 -0.163502 0 +-0.548768 -0.746576 -0.375873 0 +0.853076 -0.00102413 -0.521785 0 +0.8946 -0.314072 -0.317607 0 +0.776628 -0.608209 -0.163502 0 +0.540457 -0.752614 -0.375873 0 +0.577849 0.752638 -0.315326 0 +0.818421 0.550683 -0.163518 0 +0.882785 0.28144 -0.375877 0 +0.392326 -0.135659 0.909763 0 +0.391632 0.0898775 0.91572 0 +0.23644 -0.0163112 0.971459 0 +0.23766 0.340354 -0.909763 0 +0.369665 0.157483 -0.91572 0 +0.181697 0.152172 -0.971459 0 +0.0676954 0.648947 0.75781 0 +0.283868 0.58442 0.760177 0 +0.220029 0.730839 0.646037 0 +-0.596269 0.264935 0.757803 0 +-0.468053 0.451147 0.759862 0 +-0.627088 0.435162 0.645986 0 +-0.436225 -0.485216 0.757803 0 +-0.573703 -0.305733 0.759862 0 +-0.607644 -0.461923 0.645986 0 +0.326611 -0.564746 0.757878 0 +0.113479 -0.640094 0.759868 0 +0.251543 -0.720646 0.645986 0 +0.619602 0.108114 0.777438 0 +0.663381 -0.106778 0.740615 0 +0.764629 0.0136778 0.644258 0 +-0.0676997 0.648861 -0.757884 0 +-0.283854 0.584424 -0.760179 0 +-0.220028 0.73084 -0.646037 0 +-0.638177 0.13573 -0.757826 0 +-0.643547 -0.0893953 -0.760166 0 +-0.763115 0.0163528 -0.645981 0 +-0.326294 -0.564999 -0.757825 0 +-0.113847 -0.639674 -0.760166 0 +-0.251368 -0.720712 -0.645981 0 +0.436515 -0.484918 -0.757826 0 +0.573191 -0.305925 -0.76017 0 +0.607761 -0.461776 -0.645982 0 +0.564816 0.276726 -0.777438 0 +0.473924 0.476311 -0.740615 0 +0.626638 0.438372 -0.644258 0 +0.231373 0.364261 0.9021 0 +0.0112916 0.380517 0.924698 0 +0.0859406 0.218843 0.971923 0 +-0.275359 0.33222 0.902115 0 +-0.358427 0.128304 0.924692 0 +-0.181557 0.149318 0.971933 0 +-0.401049 -0.159221 0.902116 0 +-0.232777 -0.301239 0.924693 0 +-0.198001 -0.126573 0.97195 0 +0.0274316 -0.430611 0.902123 0 +0.213573 -0.315558 0.924552 0 +0.0593613 -0.227845 0.971842 0 +0.401284 -0.1587 -0.902103 0 +0.232735 -0.301249 -0.9247 0 +0.198155 -0.126536 -0.971923 0 +-0.0275814 -0.430636 -0.902107 0 +-0.214621 -0.314432 -0.924693 0 +-0.0591211 -0.227514 -0.971933 0 +-0.418081 -0.106841 -0.902107 0 +-0.36536 0.106959 -0.924694 0 +-0.234582 -0.0139765 -0.971951 0 +-0.230866 0.364549 -0.902114 0 +-0.0126935 0.380829 -0.924551 0 +-0.0858992 0.219223 -0.971842 0 +0.531718 0.565509 0.63045 0 +0.62895 0.639706 0.441809 0 +0.465511 0.720338 0.514117 0 +0.607491 0.770122 0.194572 0 +0.454521 0.887244 0.078775 0 +0.438916 0.856343 0.271902 0 +0.19133 0.980128 0.0522926 0 +0.00167376 0.984955 0.172796 0 +0.176842 0.950765 0.254313 0 +-0.141623 0.905416 0.400195 0 +-0.103573 0.79814 0.593499 0 +0.0411958 0.873057 0.485775 0 +-0.354729 0.708207 0.610421 0 +-0.44038 0.791302 0.42414 0 +-0.543473 0.665457 0.511582 0 +-0.545358 0.81538 0.194249 0 +-0.703348 0.706465 0.0787834 0 +-0.678625 0.682302 0.271725 0 +-0.873005 0.484889 0.0523097 0 +-0.93623 0.305961 0.172796 0 +-0.849584 0.46199 0.254312 0 +-0.904866 0.145097 0.400195 0 +-0.791082 0.148135 0.593499 0 +-0.817597 0.308969 0.485774 0 +-0.783162 -0.118519 0.610421 0 +-0.888658 -0.174301 0.42414 0 +-0.80083 -0.311236 0.511582 0 +-0.943997 -0.2667 0.194249 0 +-0.889234 -0.450614 0.0787834 0 +-0.858614 -0.434568 0.271725 0 +-0.730931 -0.680438 0.0523097 0 +-0.580297 -0.795861 0.172796 0 +-0.701914 -0.66524 0.254312 0 +-0.417615 -0.815741 0.400195 0 +-0.385343 -0.706588 0.593499 0 +-0.546498 -0.682104 0.485774 0 +-0.129292 -0.781456 0.610422 0 +-0.10884 -0.899025 0.42414 0 +0.0485329 -0.857811 0.511582 0 +-0.0380643 -0.980209 0.194249 0 +0.153771 -0.984959 0.0787834 0 +0.147972 -0.950879 0.271725 0 +0.421265 -0.905423 0.0523097 0 +0.577587 -0.79783 0.172796 0 +0.415777 -0.87313 0.254312 0 +0.646766 -0.649251 0.400198 0 +0.552925 -0.584794 0.593538 0 +0.479843 -0.730531 0.485777 0 +0.703707 -0.364686 0.609758 0 +0.821391 -0.381358 0.424111 0 +0.830864 -0.219 0.511484 0 +0.920472 -0.339103 0.194249 0 +0.98427 -0.158125 0.0787835 0 +0.950066 -0.153109 0.271724 0 +0.991285 0.120862 0.0523309 0 +0.937065 0.30302 0.173449 0 +0.958858 0.125619 0.254389 0 +0.794739 0.431007 0.427349 0 +0.731337 0.31417 0.605335 0 +0.842759 0.227723 0.487661 0 +-0.53174 0.565539 -0.630405 0 +-0.628906 0.640171 -0.441199 0 +-0.465484 0.720394 -0.514062 0 +-0.603965 0.781339 -0.15729 0 +-0.427216 0.899375 -0.0927217 0 +-0.435805 0.857792 -0.272355 0 +-0.153257 0.987186 -0.0445129 0 +-0.00109441 0.978917 -0.204227 0 +-0.175616 0.950149 -0.257465 0 +0.141372 0.905148 -0.40089 0 +0.103593 0.798097 -0.593554 0 +-0.0408741 0.873122 -0.485685 0 +-0.702176 -0.330954 -0.630405 0 +-0.803181 -0.400302 -0.441198 0 +-0.828977 -0.220088 -0.514062 0 +-0.929733 -0.332958 -0.15729 0 +-0.987374 -0.128385 -0.0927217 0 +-0.95048 -0.149403 -0.272355 0 +-0.986227 0.159305 -0.0445254 0 +-0.93117 0.301325 -0.205214 0 +-0.957889 0.126579 -0.257563 0 +-0.794588 0.430738 -0.4279 0 +-0.731349 0.315648 -0.604551 0 +-0.842689 0.227853 -0.487721 0 +0.0977715 -0.770079 -0.630405 0 +0.132513 -0.88757 -0.441198 0 +-0.0468515 -0.856416 -0.514062 0 +0.0293588 -0.987118 -0.15729 0 +-0.183014 -0.978722 -0.0927217 0 +-0.151623 -0.950128 -0.272355 0 +-0.456269 -0.888729 -0.0445254 0 +-0.574325 -0.792481 -0.205214 0 +-0.416388 -0.871891 -0.257563 0 +-0.655197 -0.622593 -0.4279 0 +-0.526198 -0.598014 -0.604551 0 +-0.477106 -0.731034 -0.487721 0 +0.762577 -0.144985 -0.630435 0 +0.885077 -0.148246 -0.441202 0 +0.800021 -0.309205 -0.514063 0 +0.947878 -0.277114 -0.15729 0 +0.874265 -0.476498 -0.0927217 0 +0.856772 -0.437808 -0.272355 0 +0.704237 -0.70857 -0.0445254 0 +0.576218 -0.791105 -0.205214 0 +0.700547 -0.665438 -0.257563 0 +0.389654 -0.815521 -0.4279 0 +0.406141 -0.685241 -0.604551 0 +0.547821 -0.679657 -0.487721 0 +0.354967 0.708677 -0.609737 0 +0.441138 0.791197 -0.423548 0 +0.543538 0.665526 -0.511423 0 +0.557024 0.815527 -0.156985 0 +0.723337 0.684219 -0.0928211 0 +0.681215 0.679509 -0.272261 0 +0.891464 0.450898 -0.0445717 0 +0.930445 0.303556 -0.205214 0 +0.84935 0.46063 -0.257561 0 +0.895991 0.118616 -0.427942 0 +0.776311 0.175686 -0.605362 0 +0.815603 0.311092 -0.487778 0 +0.140109 -0.105927 0.984464 0 +0.143999 0.100239 0.984498 0 +0.521606 -0.143864 0.840984 0 +0.372042 -0.274472 0.886702 0 +0.374802 0.274316 0.885589 0 +0.515327 0.184808 0.836827 0 +0.0510884 0.16805 -0.984464 0 +0.175416 0.00354539 -0.984498 0 +0.337427 0.422981 -0.840984 0 +0.139658 0.440734 -0.886702 0 +0.46446 -0.00162301 -0.885589 0 +0.525536 0.153389 -0.836827 0 +0.151099 0.810982 0.565241 0 +0.347313 0.744978 0.569563 0 +0.0234537 0.5377 0.842825 0 +-0.0694694 0.680007 0.729902 0 +0.450146 0.5091 0.733607 0 +0.335363 0.435093 0.835597 0 +-0.724603 0.394315 0.565232 0 +-0.601375 0.560811 0.569086 0 +-0.504126 0.188432 0.842838 0 +-0.668193 0.144066 0.729901 0 +-0.343675 0.589033 0.731383 0 +-0.309909 0.453323 0.835734 0 +-0.59893 -0.567289 0.565232 0 +-0.719199 -0.398642 0.569086 0 +-0.334992 -0.421224 0.842838 0 +-0.343498 -0.59097 0.729902 0 +-0.666405 -0.144833 0.731383 0 +-0.526903 -0.154657 0.835734 0 +0.354444 -0.744918 0.565233 0 +0.156886 -0.807186 0.569086 0 +0.296559 -0.448466 0.843182 0 +0.455879 -0.509003 0.730126 0 +-0.0681867 -0.678545 0.731383 0 +-0.0157373 -0.548905 0.835735 0 +0.817984 0.105392 0.56552 0 +0.816592 -0.100965 0.568333 0 +0.624177 0.269389 0.733365 0 +0.627109 -0.27435 0.729011 0 +-0.151078 0.81098 -0.565251 0 +-0.34731 0.744982 -0.56956 0 +-0.0236753 0.537128 -0.843183 0 +0.0696302 0.67975 -0.730126 0 +-0.45022 0.509081 -0.733574 0 +-0.335202 0.434972 -0.835725 0 +-0.817865 0.105929 -0.565593 0 +-0.815845 -0.100119 -0.569556 0 +-0.518618 0.144056 -0.842798 0 +-0.626363 0.274649 -0.72954 0 +-0.623291 -0.270871 -0.733573 0 +-0.517269 -0.18438 -0.835723 0 +-0.353478 -0.745102 -0.565593 0 +-0.156891 -0.806853 -0.569556 0 +-0.297267 -0.448719 -0.842798 0 +-0.454764 -0.510835 -0.72954 0 +0.065006 -0.676489 -0.733573 0 +0.0155109 -0.548928 -0.835723 0 +0.599403 -0.566427 -0.565593 0 +0.718881 -0.398543 -0.569557 0 +0.334936 -0.421377 -0.842784 0 +0.345304 -0.590363 -0.72954 0 +0.663418 -0.147281 -0.733606 0 +0.527056 -0.154876 -0.835597 0 +0.723704 0.395523 -0.565537 0 +0.601296 0.56166 -0.56833 0 +0.663312 0.148941 -0.733366 0 +0.346083 0.59056 -0.72901 0 +-0.0512894 0.167478 0.984551 0 +-0.146528 0.438123 0.886887 0 +-0.174867 0.00289383 0.984598 0 +-0.46196 -0.00396923 0.886887 0 +-0.0564016 -0.165708 0.98457 0 +-0.138879 -0.440529 0.886926 0 +0.056944 -0.16564 -0.984551 0 +0.138729 -0.44071 -0.886859 0 +-0.139772 -0.105123 -0.984598 0 +-0.376271 -0.268127 -0.886859 0 +-0.14303 0.100911 -0.98457 0 +-0.371279 0.274997 -0.886859 0 +0.439315 0.806606 0.395489 0 +0.621151 0.448796 0.642479 0 +0.684885 0.676736 0.270099 0 +0.753888 0.549761 0.35974 0 +0.300562 0.910724 0.283312 0 +0.681184 0.72835 0.0743004 0 +0.311169 0.950156 -0.0192143 0 +0.449914 0.887899 -0.0959622 0 +0.122414 0.913354 0.388356 0 +0.1213 0.989659 -0.0767251 0 +-0.154366 0.951594 0.265769 0 +-0.156449 0.982778 0.09832 0 +-0.28484 0.871958 0.398221 0 +-0.226643 0.703461 0.673626 0 +-0.632102 0.666905 0.394594 0 +-0.434166 0.859432 0.26994 0 +-0.773276 0.567288 0.283284 0 +-0.482081 0.872958 0.0746144 0 +-0.807303 0.589824 -0.0190137 0 +-0.705376 0.702354 -0.0956058 0 +-0.830828 0.398664 0.388347 0 +-0.90367 0.421323 -0.0767649 0 +-0.952721 0.147248 0.265769 0 +-0.983023 0.154903 0.0983197 0 +-0.917302 -0.0014487 0.398221 0 +-0.739068 0.00183061 0.673626 0 +-0.829595 -0.39508 0.394594 0 +-0.951533 -0.147338 0.26994 0 +-0.778479 -0.560127 0.283284 0 +-0.979204 -0.188727 0.0746144 0 +-0.810427 -0.585525 -0.0190137 0 +-0.885951 -0.453813 -0.0956058 0 +-0.635892 -0.66697 0.388347 0 +-0.679951 -0.729245 -0.0767649 0 +-0.434448 -0.86059 0.265769 0 +-0.451093 -0.887043 0.0983197 0 +-0.282084 -0.872854 0.398221 0 +-0.230125 -0.702329 0.673626 0 +0.119384 -0.911078 0.394594 0 +-0.153913 -0.950491 0.26994 0 +0.29215 -0.913466 0.283284 0 +-0.1231 -0.989598 0.0746144 0 +0.306432 -0.951699 -0.0190137 0 +0.157828 -0.982826 -0.0956058 0 +0.437825 -0.810874 0.388347 0 +0.483437 -0.872021 -0.0767649 0 +0.684218 -0.679121 0.265769 0 +0.704232 -0.703126 0.0983197 0 +0.742966 -0.538004 0.398219 0 +0.597282 -0.435382 0.673568 0 +0.903384 -0.168017 0.394574 0 +0.856409 -0.440098 0.26994 0 +0.959037 -0.00443457 0.283284 0 +0.903123 -0.422878 0.0746144 0 +0.999812 -0.00265669 -0.0190132 0 +0.983494 -0.153607 -0.0956058 0 +0.906319 0.16559 0.388827 0 +0.978732 0.190308 -0.0767594 0 +0.855132 0.443026 0.269205 0 +0.886223 0.452784 0.0979399 0 +-0.438923 0.806934 -0.395252 0 +-0.621265 0.448822 -0.64235 0 +-0.684883 0.678568 -0.265471 0 +-0.754424 0.549225 -0.359433 0 +-0.299064 0.911024 -0.283929 0 +-0.305041 0.952177 0.0173019 0 +-0.122116 0.912952 -0.389392 0 +0.152747 0.951339 -0.267608 0 +0.284657 0.872198 -0.397826 0 +0.2273 0.703306 -0.673567 0 +-0.903074 -0.168086 -0.395253 0 +-0.618836 -0.452165 -0.64235 0 +-0.856997 -0.441673 -0.265471 0 +-0.755474 -0.54778 -0.359433 0 +-0.958849 -0.00290817 -0.283936 0 +-0.999837 0.00412821 0.0173016 0 +-0.905848 0.165709 -0.389871 0 +-0.855335 0.44089 -0.272045 0 +-0.119206 -0.910816 -0.395253 0 +0.238803 -0.728275 -0.64235 0 +0.15523 -0.951537 -0.265471 0 +0.287516 -0.887772 -0.359433 0 +-0.293535 -0.912818 -0.283936 0 +-0.312893 -0.949626 0.0173016 0 +-0.437521 -0.810305 -0.389871 0 +-0.683625 -0.677229 -0.272045 0 +0.829401 -0.394829 -0.395253 0 +0.766319 0.00201622 -0.642477 0 +0.952934 -0.146409 -0.265471 0 +0.933168 -0.000891708 -0.359434 0 +0.777435 -0.561245 -0.283936 0 +0.806459 -0.591029 0.0173016 0 +0.635445 -0.666505 -0.389871 0 +0.432832 -0.859441 -0.272045 0 +0.632534 0.666606 -0.394406 0 +0.436791 0.859609 -0.265096 0 +0.774026 0.56595 -0.283908 0 +0.811162 0.584567 0.0169739 0 +0.830245 0.398401 -0.389857 0 +0.951129 0.146067 -0.272046 0 +0.324949 -0.0586432 0.943907 0 +0.396508 -0.038851 0.917199 0 +0.303846 0.0277655 0.952312 0 +0.22842 0.238444 -0.943907 0 +0.297945 0.264492 -0.917199 0 +0.262137 0.156134 -0.952312 0 +0.159881 0.68286 0.712833 0 +0.161573 0.623564 0.764881 0 +0.247406 0.672226 0.697778 0 +-0.600035 0.363087 0.712823 0 +-0.543121 0.346418 0.76485 0 +-0.56288 0.443163 0.697684 0 +-0.530737 -0.458468 0.712823 0 +-0.497297 -0.40949 0.76485 0 +-0.595413 -0.398386 0.697684 0 +0.272021 -0.646433 0.712826 0 +0.235764 -0.599483 0.764864 0 +0.194894 -0.689378 0.697686 0 +0.699023 0.0468839 0.713557 0 +0.6436 0.00226604 0.765351 0 +0.722287 -0.0357177 0.690663 0 +-0.159881 0.682859 -0.712834 0 +-0.161573 0.623551 -0.764892 0 +-0.247403 0.672229 -0.697776 0 +-0.698921 0.058656 -0.712783 0 +-0.642993 0.0389067 -0.764871 0 +-0.7158 -0.0276624 -0.697751 0 +-0.271764 -0.646588 -0.712783 0 +-0.235698 -0.5995 -0.764871 0 +-0.194886 -0.689314 -0.697751 0 +0.530961 -0.458268 -0.712785 0 +0.497321 -0.409414 -0.764874 0 +0.595353 -0.398353 -0.697755 0 +0.593079 0.372945 -0.713557 0 +0.522015 0.376465 -0.765351 0 +0.563348 0.453446 -0.690663 0 +0.145232 0.295338 0.944287 0 +0.124656 0.376607 0.917941 0 +0.0572624 0.291411 0.954877 0 +-0.23632 0.229636 0.944148 0 +-0.319774 0.234883 0.917912 0 +-0.259517 0.144557 0.954853 0 +-0.291421 -0.153793 0.944148 0 +-0.322201 -0.231541 0.917913 0 +-0.217631 -0.202165 0.954859 0 +0.0561815 -0.324684 0.94415 0 +0.120369 -0.377981 0.917949 0 +0.124781 -0.270072 0.954715 0 +0.291086 -0.153571 -0.944288 0 +0.322188 -0.231424 -0.917946 0 +0.217594 -0.202111 -0.954879 0 +-0.0562187 -0.324683 -0.944148 0 +-0.12068 -0.377966 -0.917914 0 +-0.125006 -0.269475 -0.954854 0 +-0.326162 -0.0468629 -0.944149 0 +-0.396758 -0.00202375 -0.917914 0 +-0.294889 0.0356579 -0.95486 0 +-0.145389 0.295701 -0.944149 0 +-0.124779 0.376554 -0.917946 0 +-0.0577931 0.291839 -0.954715 0 +0.515984 0.646574 0.561867 0 +0.578655 0.599641 0.552783 0 +0.536991 0.689172 0.486492 0 +0.519263 0.826381 0.217835 0 +0.546124 0.825267 0.143752 0 +0.448252 0.873183 0.191344 0 +0.16548 0.973771 0.156135 0 +0.109229 0.988658 0.102979 0 +0.103778 0.969891 0.220304 0 +-0.0564479 0.88507 0.462013 0 +-0.128181 0.864106 0.486695 0 +-0.0204851 0.845669 0.533306 0 +-0.457127 0.697205 0.552209 0 +-0.39763 0.754535 0.522068 0 +-0.498611 0.722804 0.478467 0 +-0.625567 0.749182 0.217681 0 +-0.616206 0.774355 0.143686 0 +-0.691922 0.696158 0.191309 0 +-0.874975 0.458293 0.156135 0 +-0.906516 0.409397 0.102979 0 +-0.890352 0.398411 0.220304 0 +-0.859195 0.219817 0.462013 0 +-0.861424 0.145116 0.486695 0 +-0.810609 0.241844 0.533306 0 +-0.804342 -0.219305 0.552209 0 +-0.84048 -0.145004 0.522068 0 +-0.841507 -0.250848 0.478467 0 +-0.905825 -0.363439 0.217681 0 +-0.926874 -0.346758 0.143686 0 +-0.875901 -0.442933 0.191309 0 +-0.706244 -0.69053 0.156135 0 +-0.669488 -0.735637 0.102979 0 +-0.654046 -0.723659 0.220304 0 +-0.474564 -0.749216 0.462013 0 +-0.404208 -0.774419 0.486695 0 +-0.480499 -0.696202 0.533306 0 +-0.0399837 -0.832743 0.552209 0 +-0.121816 -0.844153 0.522068 0 +-0.021469 -0.877837 0.478467 0 +0.0657361 -0.973799 0.217681 0 +0.0433666 -0.988663 0.143686 0 +0.150586 -0.969905 0.191309 0 +0.438492 -0.885064 0.156135 0 +0.492749 -0.864045 0.102979 0 +0.486129 -0.845657 0.220304 0 +0.565899 -0.682856 0.462015 0 +0.61161 -0.623726 0.486703 0 +0.513645 -0.672111 0.533316 0 +0.779449 -0.295765 0.552248 0 +0.765221 -0.37681 0.521958 0 +0.828207 -0.291806 0.478448 0 +0.946452 -0.238402 0.217681 0 +0.953676 -0.26427 0.143686 0 +0.968968 -0.156502 0.191309 0 +0.977244 0.143534 0.156154 0 +0.974012 0.201648 0.103054 0 +0.954443 0.201049 0.220473 0 +0.819481 0.324482 0.472395 0 +0.76724 0.377827 0.518244 0 +0.798131 0.269577 0.538799 0 +-0.515981 0.646592 -0.561849 0 +-0.578652 0.599708 -0.552715 0 +-0.536956 0.689294 -0.486357 0 +-0.511974 0.832656 -0.211093 0 +-0.521375 0.844189 -0.124506 0 +-0.43729 0.877937 -0.194918 0 +-0.154957 0.974619 -0.161554 0 +-0.0780013 0.989432 -0.122182 0 +-0.101703 0.967386 -0.231971 0 +0.0565057 0.884987 -0.462166 0 +0.128163 0.864039 -0.486818 0 +0.0205263 0.845653 -0.533329 0 +-0.774392 -0.290919 -0.561849 0 +-0.749169 -0.365011 -0.552715 0 +-0.821486 -0.297672 -0.486357 0 +-0.950112 -0.229612 -0.211093 0 +-0.963985 -0.234988 -0.124506 0 +-0.970098 -0.14459 -0.194918 0 +-0.974801 0.153802 -0.161565 0 +-0.965099 0.231582 -0.122235 0 +-0.951383 0.202192 -0.232334 0 +-0.819342 0.324698 -0.472487 0 +-0.767171 0.378049 -0.518186 0 +-0.798097 0.270103 -0.538587 0 +0.0373803 -0.82639 -0.561849 0 +0.11564 -0.825297 -0.552715 0 +0.0292497 -0.873265 -0.486357 0 +-0.0752271 -0.974564 -0.211093 0 +-0.0744004 -0.989419 -0.124506 0 +-0.162264 -0.967299 -0.194918 0 +-0.447505 -0.879563 -0.161565 0 +-0.518479 -0.846301 -0.122235 0 +-0.48629 -0.842338 -0.232334 0 +-0.561997 -0.678904 -0.472487 0 +-0.596614 -0.612799 -0.518186 0 +-0.503508 -0.675569 -0.538587 0 +0.797492 -0.219816 -0.561854 0 +0.820631 -0.145047 -0.552727 0 +0.839563 -0.242035 -0.486359 0 +0.903619 -0.372702 -0.211093 0 +0.918003 -0.376506 -0.124506 0 +0.869814 -0.453234 -0.194918 0 +0.698227 -0.697402 -0.161565 0 +0.644661 -0.754625 -0.122235 0 +0.650839 -0.722786 -0.232334 0 +0.472009 -0.744284 -0.472487 0 +0.398443 -0.756779 -0.518186 0 +0.486911 -0.687627 -0.538587 0 +0.45675 0.69743 -0.552236 0 +0.397643 0.754657 -0.521883 0 +0.498797 0.722842 -0.478216 0 +0.63371 0.744277 -0.21085 0 +0.641804 0.756701 -0.124417 0 +0.699853 0.687186 -0.194864 0 +0.87903 0.448551 -0.161565 0 +0.916893 0.379938 -0.122236 0 +0.888529 0.395635 -0.232334 0 +0.853687 0.21895 -0.472518 0 +0.842735 0.145269 -0.518346 0 +0.804134 0.250974 -0.538861 0 +0.133834 -0.0025591 0.990964 0 +0.181759 -0.0545586 0.981836 0 +0.262833 -0.0833502 0.961219 0 +0.213695 -0.0926866 0.971282 0 +0.191914 0.0440153 0.980424 0 +0.248485 0.0928201 0.964153 0 +0.443367 -0.228734 0.86666 0 +0.457244 -0.14178 0.877974 0 +0.465983 -0.0529018 0.883211 0 +0.382662 -0.216383 0.898175 0 +0.324234 -0.142831 0.935135 0 +0.448114 0.229703 0.863957 0 +0.383301 0.208124 0.899854 0 +0.295039 0.155256 0.942787 0 +0.471167 0.150057 0.869193 0 +0.47813 0.0335719 0.877645 0 +0.10677 0.0807363 -0.990964 0 +0.114978 0.150974 -0.981836 0 +0.163644 0.221921 -0.961219 0 +0.118403 0.200592 -0.971282 0 +0.181133 0.0771953 -0.980424 0 +0.255587 0.0709626 -0.964153 0 +0.224245 0.445654 -0.86666 0 +0.286582 0.383464 -0.877974 0 +0.345893 0.316696 -0.883211 0 +0.182393 0.399981 -0.898175 0 +0.178357 0.306132 -0.935135 0 +0.497548 0.0775617 -0.863957 0 +0.432429 0.0569227 -0.899854 0 +0.329949 0.0478144 -0.942787 0 +0.469384 0.155546 -0.869193 0 +0.406549 0.253878 -0.877645 0 +0.252905 0.786844 0.562889 0 +0.193999 0.774859 0.601642 0 +0.149355 0.731617 0.665132 0 +0.149944 0.764219 0.625404 0 +0.286134 0.738699 0.610288 0 +0.319947 0.685627 0.653836 0 +-0.039811 0.618626 0.784671 0 +0.044375 0.595971 0.801786 0 +0.12929 0.569392 0.811835 0 +-0.011931 0.667944 0.744095 0 +0.0763214 0.702042 0.70804 0 +0.394549 0.472779 0.78791 0 +0.391923 0.537647 0.746529 0 +0.365504 0.628153 0.686898 0 +0.317454 0.492316 0.810469 0 +0.208361 0.53281 0.82018 0 +-0.670189 0.483686 0.562871 0 +-0.676991 0.423965 0.601625 0 +-0.649656 0.36813 0.665129 0 +-0.680482 0.378766 0.625399 0 +-0.614162 0.500547 0.610129 0 +-0.553214 0.516634 0.653448 0 +-0.600651 0.153304 0.784671 0 +-0.553091 0.226375 0.801784 0 +-0.501574 0.298933 0.811827 0 +-0.63894 0.195064 0.744093 0 +-0.644098 0.289537 0.708035 0 +-0.327351 0.522034 0.7876 0 +-0.389912 0.54071 0.745369 0 +-0.484171 0.543703 0.68554 0 +-0.36996 0.45424 0.810437 0 +-0.442303 0.362785 0.820214 0 +-0.667112 -0.487921 0.562871 0 +-0.612416 -0.512844 0.601626 0 +-0.550868 -0.504101 0.665129 0 +-0.570509 -0.530132 0.625399 0 +-0.665835 -0.429425 0.610129 0 +-0.662301 -0.366489 0.653448 0 +-0.331412 -0.52388 0.784671 0 +-0.38621 -0.456067 0.801784 0 +-0.439297 -0.38465 0.811827 0 +-0.38296 -0.54739 0.744093 0 +-0.474403 -0.523102 0.708035 0 +-0.59764 -0.150012 0.7876 0 +-0.634735 -0.20374 0.745369 0 +-0.666709 -0.292461 0.68554 0 +-0.546332 -0.211485 0.810437 0 +-0.481709 -0.308549 0.820214 0 +0.257891 -0.785237 0.562871 0 +0.298497 -0.74092 0.601626 0 +0.309201 -0.679682 0.66513 0 +0.327888 -0.706405 0.6254 0 +0.202653 -0.765947 0.610129 0 +0.143889 -0.743137 0.653448 0 +0.395534 -0.476658 0.785075 0 +0.314184 -0.508019 0.802008 0 +0.229987 -0.536575 0.811907 0 +0.402171 -0.533195 0.744265 0 +0.350886 -0.612808 0.708063 0 +-0.0420116 -0.614746 0.787601 0 +-0.00237692 -0.666627 0.74537 0 +0.0721205 -0.724452 0.685541 0 +0.0323013 -0.58494 0.810441 0 +0.144549 -0.553442 0.820246 0 +0.826713 0.00214713 0.562556 0 +0.797317 0.0535421 0.601192 0 +0.741624 0.0825084 0.665701 0 +0.773119 0.0917811 0.625704 0 +0.792105 -0.0455753 0.608681 0 +0.754007 -0.0963845 0.649715 0 +0.569223 0.230541 0.789195 0 +0.507844 0.251467 0.823906 0 +0.558317 0.154666 0.81509 0 +0.520732 0.0945109 0.848485 0 +0.56735 0.039608 0.822522 0 +0.62529 0.207689 0.752235 0 +0.686783 0.13133 0.714898 0 +0.578946 -0.2225 0.784414 0 +0.510003 -0.2401 0.825958 0 +0.639455 -0.210619 0.739395 0 +0.717431 -0.160968 0.677772 0 +0.588164 -0.128639 0.798454 0 +0.582979 -0.0372631 0.811631 0 +0.525255 -0.0585771 0.848931 0 +-0.252904 0.786844 -0.56289 0 +-0.193996 0.774859 -0.601644 0 +-0.149355 0.731616 -0.665133 0 +-0.149941 0.764219 -0.625405 0 +-0.286133 0.7387 -0.610287 0 +-0.319947 0.68563 -0.653833 0 +0.0398214 0.618113 -0.785075 0 +-0.0444174 0.595666 -0.802011 0 +-0.129297 0.569271 -0.811919 0 +0.0119632 0.667753 -0.744267 0 +-0.0763195 0.702015 -0.708067 0 +-0.394583 0.47283 -0.787863 0 +-0.391945 0.537691 -0.746486 0 +-0.365504 0.628164 -0.686889 0 +-0.317327 0.492259 -0.810553 0 +-0.208203 0.532671 -0.82031 0 +-0.82648 0.00256302 -0.562897 0 +-0.796881 0.0545695 -0.601679 0 +-0.742195 0.0833536 -0.664959 0 +-0.773167 0.0926916 -0.625512 0 +-0.790974 -0.04392 -0.610272 0 +-0.750946 -0.092449 -0.653823 0 +-0.576387 0.229035 -0.784419 0 +-0.580591 0.141934 -0.801736 0 +-0.581483 0.0529859 -0.811831 0 +-0.631985 0.216528 -0.744096 0 +-0.691373 0.142863 -0.708237 0 +-0.571622 -0.229158 -0.787862 0 +-0.632494 -0.206611 -0.746483 0 +-0.710369 -0.153515 -0.686883 0 +-0.566233 -0.149682 -0.810548 0 +-0.570989 -0.0333845 -0.820276 0 +-0.257834 -0.785237 -0.562897 0 +-0.298148 -0.741016 -0.601679 0 +-0.308625 -0.680111 -0.664959 0 +-0.327077 -0.706682 -0.625512 0 +-0.202654 -0.765833 -0.610272 0 +-0.144131 -0.742761 -0.653823 0 +-0.395939 -0.477401 -0.784419 0 +-0.3144 -0.508315 -0.801736 0 +-0.230081 -0.536649 -0.811831 0 +-0.401225 -0.534143 -0.744096 0 +-0.349517 -0.613388 -0.708237 0 +0.0413015 -0.614458 -0.787862 0 +0.00104775 -0.665384 -0.746483 0 +-0.0735144 -0.723039 -0.686883 0 +-0.0326201 -0.584774 -0.810548 0 +-0.144695 -0.553359 -0.820276 0 +0.66713 -0.487866 -0.562897 0 +0.612615 -0.512542 -0.60168 0 +0.551454 -0.503685 -0.664959 0 +0.571022 -0.529445 -0.625512 0 +0.665726 -0.42939 -0.610273 0 +0.661867 -0.366599 -0.653826 0 +0.331683 -0.524085 -0.784419 0 +0.386283 -0.456089 -0.801736 0 +0.439297 -0.384647 -0.811828 0 +0.384015 -0.546647 -0.744097 0 +0.475359 -0.521957 -0.708238 0 +0.597089 -0.150576 -0.78791 0 +0.633097 -0.204594 -0.746528 0 +0.664927 -0.293338 -0.686894 0 +0.546205 -0.211692 -0.810468 0 +0.48175 -0.308578 -0.820179 0 +0.670087 0.484192 -0.562556 0 +0.676513 0.425333 -0.601195 0 +0.648483 0.369165 -0.665701 0 +0.679413 0.380174 -0.625706 0 +0.614039 0.502459 -0.608681 0 +0.553351 0.521171 -0.649715 0 +0.596019 0.148069 -0.789195 0 +0.558663 0.095062 -0.823906 0 +0.542598 0.203043 -0.81509 0 +0.476833 0.229618 -0.848485 0 +0.482277 0.301436 -0.822522 0 +0.627946 0.199512 -0.752235 0 +0.632813 0.297433 -0.714898 0 +0.337595 0.520302 -0.784414 0 +0.271474 0.494017 -0.825958 0 +0.393531 0.546256 -0.739395 0 +0.4858 0.551921 -0.677772 0 +0.400223 0.449785 -0.798454 0 +0.449737 0.372813 -0.811631 0 +0.390509 0.356127 -0.84893 0 +0.0443054 0.126599 0.990928 0 +0.0810037 0.0565706 0.995076 0 +0.107533 0.155947 0.981901 0 +0.193026 0.142619 0.970777 0 +0.160545 0.225474 0.960915 0 +0.153981 0.174996 0.971237 0 +0.016033 0.195236 0.980625 0 +-0.0160632 0.261941 0.964923 0 +0.357546 0.357457 0.862773 0 +0.419479 0.305783 0.854725 0 +0.395963 0.406776 0.823231 0 +0.294737 0.407873 0.864165 0 +0.252512 0.471141 0.845154 0 +0.187709 0.446941 0.874647 0 +0.318068 0.307832 0.896689 0 +0.227486 0.274838 0.93419 0 +0.30735 0.236958 0.921633 0 +-0.0750626 0.488975 0.869057 0 +-0.0706657 0.559056 0.826087 0 +-0.0846986 0.42169 0.902757 0 +-0.0649824 0.321257 0.944757 0 +0.0170373 0.468563 0.883273 0 +0.108633 0.454177 0.884263 0 +0.106421 0.516844 0.849443 0 +-0.106279 0.0812016 0.990979 0 +-0.0281915 0.0943865 0.995105 0 +-0.11507 0.15027 0.981932 0 +-0.0775936 0.226699 0.970872 0 +-0.164989 0.222219 0.960921 0 +-0.119336 0.200134 0.971256 0 +-0.180539 0.0755483 0.980662 0 +-0.254035 0.0656711 0.964935 0 +-0.2292 0.449959 0.863131 0 +-0.159553 0.490725 0.856594 0 +-0.263696 0.502251 0.823511 0 +-0.296665 0.40596 0.864406 0 +-0.369865 0.385319 0.845429 0 +-0.366628 0.3152 0.875346 0 +-0.196561 0.396935 0.896541 0 +-0.192824 0.300002 0.934245 0 +-0.134541 0.361722 0.922537 0 +-0.488239 0.0797144 0.869056 0 +-0.553531 0.105552 0.826087 0 +-0.427228 0.0497544 0.902756 0 +-0.325604 0.0374669 0.944761 0 +-0.440339 0.160899 0.883304 0 +-0.398261 0.243212 0.88444 0 +-0.458613 0.260754 0.849522 0 +-0.109569 -0.0761981 0.991018 0 +-0.0979271 0.00213327 0.99516 0 +-0.17824 -0.0630843 0.981969 0 +-0.239489 -0.00376007 0.970895 0 +-0.26232 -0.0882456 0.960923 0 +-0.227116 -0.0516783 0.971279 0 +-0.127377 -0.148489 0.980676 0 +-0.140857 -0.221358 0.964939 0 +-0.498763 -0.0789367 0.863131 0 +-0.516012 -0.000100958 0.856594 0 +-0.559155 -0.0955854 0.823511 0 +-0.477765 -0.156697 0.864406 0 +-0.480755 -0.232693 0.845429 0 +-0.413067 -0.251282 0.875346 0 +-0.438248 -0.0642807 0.896542 0 +-0.344898 -0.0906821 0.934247 0 +-0.385591 -0.0161799 0.922539 0 +-0.226687 -0.43971 0.869056 0 +-0.271436 -0.493822 0.826087 0 +-0.179043 -0.390739 0.902903 0 +-0.136203 -0.298098 0.944765 0 +-0.289095 -0.369067 0.883304 0 +-0.354378 -0.303612 0.88444 0 +-0.389711 -0.35559 0.849522 0 +0.0392692 -0.128581 0.990886 0 +0.0789166 -0.0594678 0.995075 0 +-0.0316348 -0.0929685 0.995135 0 +0.00532359 -0.189488 0.981874 0 +-0.070253 -0.229047 0.97088 0 +0.0028993 -0.276783 0.960913 0 +-0.02081 -0.232186 0.971228 0 +0.102053 -0.167866 0.980514 0 +0.166708 -0.203683 0.964712 0 +0.195501 -0.139672 0.97071 0 +-0.0790512 -0.498757 0.863124 0 +-0.159342 -0.490782 0.856601 0 +-0.0818812 -0.561328 0.82351 0 +0.00137 -0.502799 0.864409 0 +0.0727127 -0.529111 0.845444 0 +0.111271 -0.470465 0.875374 0 +-0.0742657 -0.436652 0.896549 0 +-0.0203286 -0.356032 0.93425 0 +-0.103677 -0.37167 0.922568 0 +0.346279 -0.352586 0.869347 0 +0.385049 -0.410098 0.82675 0 +0.414961 -0.304464 0.857397 0 +0.3149 -0.29973 0.900541 0 +0.31647 -0.222084 0.922251 0 +0.23958 -0.224839 0.94448 0 +0.260748 -0.389218 0.883478 0 +0.178869 -0.430772 0.884556 0 +0.21751 -0.480372 0.84967 0 +0.110256 -0.0763786 -0.990928 0 +0.0987846 0.00184614 -0.995076 0 +0.178658 -0.0629586 -0.981901 0 +0.23999 -0.00192375 -0.970777 0 +0.262414 -0.0880466 -0.960915 0 +0.227432 -0.0510675 -0.971237 0 +0.127724 -0.148527 -0.980626 0 +0.140957 -0.221363 -0.964923 0 +0.499368 -0.0790284 -0.862773 0 +0.519101 -0.000820062 -0.854726 0 +0.559437 -0.0963473 -0.823231 0 +0.478186 -0.156736 -0.864166 0 +0.481214 -0.232739 -0.845155 0 +0.414552 -0.251259 -0.87465 0 +0.438261 -0.0620863 -0.896689 0 +0.345583 -0.0886372 -0.934191 0 +0.387931 -0.0110474 -0.921633 0 +0.226428 -0.439927 -0.869014 0 +0.271198 -0.494258 -0.825905 0 +0.179183 -0.391021 -0.902753 0 +0.136217 -0.298119 -0.944756 0 +0.28908 -0.369169 -0.883267 0 +0.354795 -0.303624 -0.884269 0 +0.389851 -0.355632 -0.84944 0 +-0.0382528 -0.128162 -0.990979 0 +0.032671 -0.0929309 -0.995105 0 +-0.00476919 -0.189207 -0.981932 0 +0.0704685 -0.229015 -0.970872 0 +-0.0028629 -0.276757 -0.960921 0 +0.0210883 -0.232056 -0.971256 0 +-0.101657 -0.167235 -0.980662 0 +-0.166929 -0.202437 -0.964936 0 +0.0787629 -0.498876 -0.863082 0 +0.159038 -0.491147 -0.856448 0 +0.0814691 -0.561505 -0.82343 0 +-0.00156452 -0.502826 -0.864392 0 +-0.0728853 -0.529061 -0.84546 0 +-0.111369 -0.470486 -0.87535 0 +0.0741188 -0.436737 -0.89652 0 +0.0202909 -0.356059 -0.934241 0 +0.10367 -0.371765 -0.922531 0 +-0.348425 -0.351292 -0.869013 0 +-0.386262 -0.410659 -0.825905 0 +-0.316517 -0.291246 -0.902751 0 +-0.24143 -0.221663 -0.94476 0 +-0.26181 -0.388915 -0.883297 0 +-0.179306 -0.430818 -0.884445 0 +-0.217827 -0.480487 -0.849524 0 +-0.133432 -0.00275708 -0.991018 0 +-0.0779711 -0.0592855 -0.99516 0 +-0.181279 -0.0537281 -0.981969 0 +-0.195966 -0.13772 -0.970895 0 +-0.264091 -0.0827947 -0.960923 0 +-0.214118 -0.0916838 -0.971279 0 +-0.190328 0.0452643 -0.980677 0 +-0.24406 0.0963018 -0.964939 0 +-0.45012 -0.229069 -0.863082 0 +-0.417963 -0.303028 -0.856448 0 +-0.508847 -0.250996 -0.82343 0 +-0.4787 -0.153894 -0.864392 0 +-0.52569 -0.0941708 -0.84546 0 +-0.481873 -0.0394697 -0.87535 0 +-0.392457 -0.20545 -0.89652 0 +-0.332357 -0.129321 -0.934243 0 +-0.321533 -0.213475 -0.922532 0 +-0.441768 0.222817 -0.869013 0 +-0.509922 0.240457 -0.825905 0 +-0.3748 0.211027 -0.902751 0 +-0.285404 0.161149 -0.944759 0 +-0.450783 0.128815 -0.883297 0 +-0.46514 0.0374003 -0.884445 0 +-0.524282 0.0586871 -0.849524 0 +-0.0438084 0.127106 -0.990886 0 +0.0288906 0.0944965 -0.995075 0 +-0.0802385 0.056619 -0.995135 0 +-0.107071 0.156429 -0.981874 0 +-0.191464 0.144016 -0.97088 0 +-0.160343 0.225627 -0.960913 0 +-0.15331 0.175613 -0.971228 0 +-0.0161068 0.195792 -0.980513 0 +0.0151481 0.262771 -0.964712 0 +0.0760668 0.22791 -0.97071 0 +-0.356955 0.357298 -0.863083 0 +-0.417355 0.303864 -0.856448 0 +-0.395955 0.406379 -0.823431 0 +-0.294302 0.407693 -0.864398 0 +-0.252022 0.470826 -0.845475 0 +-0.186494 0.446023 -0.875374 0 +-0.316682 0.309748 -0.89652 0 +-0.225711 0.276123 -0.934241 0 +-0.302386 0.239832 -0.922531 0 +0.0729003 0.488786 -0.869347 0 +0.0704618 0.558102 -0.82675 0 +0.156751 0.490225 -0.857397 0 +0.0785825 0.42758 -0.900541 0 +0.125492 0.365686 -0.922251 0 +0.0616684 0.322721 -0.94448 0 +-0.017824 0.468149 -0.883478 0 +-0.108484 0.453641 -0.884556 0 +-0.106372 0.516475 -0.849674 0 +0.388312 0.784628 0.483221 0 +0.317637 0.794428 0.517618 0 +0.404875 0.740627 0.536249 0 +0.376302 0.699235 0.607844 0 +0.456772 0.679759 0.57381 0 +0.412984 0.706372 0.572819 0 +0.455367 0.765442 0.454685 0 +0.520423 0.742581 0.421526 0 +0.524913 0.477658 0.704487 0 +0.467086 0.455193 0.758058 0 +0.576626 0.508556 0.639442 0 +0.623236 0.536791 0.568711 0 +0.486206 0.534002 0.691678 0 +0.476581 0.613519 0.62966 0 +0.431674 0.579806 0.691016 0 +0.722768 0.614816 0.315595 0 +0.667973 0.665519 0.332972 0 +0.581487 0.723006 0.373008 0 +0.710137 0.585073 0.391672 0 +0.668948 0.553428 0.496207 0 +0.366396 0.862841 0.348122 0 +0.368977 0.829064 0.420056 0 +0.431455 0.83703 0.336515 0 +0.49606 0.786762 0.367337 0 +0.49981 0.818412 0.283483 0 +0.476109 0.814137 0.328851 0 +0.370203 0.886852 0.276481 0 +0.370109 0.906644 0.202406 0 +0.694023 0.695306 0.186744 0 +0.726853 0.643282 0.240617 0 +0.64665 0.750512 0.136335 0 +0.592964 0.80066 0.0856586 0 +0.653955 0.717978 0.238374 0 +0.574283 0.776505 0.259318 0 +0.621711 0.722888 0.301545 0 +0.38187 0.92234 -0.0587877 0 +0.364396 0.931104 0.0153504 0 +0.353939 0.926719 0.126169 0 +0.453354 0.89079 -0.0312295 0 +0.540326 0.840959 0.0288418 0 +0.216864 0.913297 0.344654 0 +0.291019 0.887466 0.357282 0 +0.236967 0.93073 0.278575 0 +0.301195 0.928064 0.219054 0 +0.219251 0.955888 0.195391 0 +0.252349 0.938485 0.230674 0 +0.147953 0.935019 0.322256 0 +0.076559 0.95101 0.299449 0 +0.235088 0.970513 -0.053202 0 +0.308534 0.947814 -0.0804783 0 +0.158513 0.987285 -0.0123907 0 +0.0806559 0.996285 0.0301698 0 +0.260917 0.965286 0.0107881 0 +0.235574 0.965768 0.108644 0 +0.304545 0.950289 0.0649901 0 +-0.156871 0.970646 0.182289 0 +-0.0991866 0.967465 0.232697 0 +-0.00271868 0.957762 0.287547 0 +-0.0980675 0.987139 0.126302 0 +0.000217854 0.997946 0.0640371 0 +0.145746 0.866202 0.477893 0 +0.207386 0.831375 0.515505 0 +0.191012 0.888874 0.416361 0 +0.08974 0.892133 0.442787 0 +0.0608021 0.927805 0.368086 0 +0.00276044 0.902183 0.43131 0 +0.0506769 0.907494 0.414152 0 +0.0953823 0.843363 0.52881 0 +0.0450687 0.814427 0.578472 0 +0.106646 0.786452 0.60838 0 +-0.217642 0.923344 0.316322 0 +-0.209501 0.94815 0.239047 0 +-0.213238 0.891913 0.398789 0 +-0.205656 0.85346 0.478864 0 +-0.149686 0.934299 0.323498 0 +-0.0714649 0.919789 0.385858 0 +-0.0814883 0.947805 0.308296 0 +-0.148485 0.693853 0.704636 0 +-0.111704 0.644219 0.756655 0 +-0.0823977 0.725289 0.683477 0 +-0.00399377 0.719246 0.694758 0 +0.00412267 0.773515 0.633764 0 +-0.181547 0.741376 0.646077 0 +-0.20465 0.807597 0.553084 0 +-0.626584 0.611745 0.482793 0 +-0.657493 0.547606 0.517463 0 +-0.579919 0.61412 0.535316 0 +-0.548791 0.575004 0.606799 0 +-0.504707 0.645395 0.573331 0 +-0.544217 0.611708 0.57208 0 +-0.588853 0.669353 0.453011 0 +-0.549592 0.723525 0.417623 0 +-0.284102 0.648887 0.705849 0 +-0.286049 0.586319 0.75791 0 +-0.212162 0.657993 0.722492 0 +-0.27839 0.706999 0.650125 0 +-0.242876 0.759309 0.603724 0 +-0.302138 0.772126 0.559045 0 +-0.352538 0.636911 0.685594 0 +-0.432051 0.653711 0.621282 0 +-0.416278 0.595469 0.687131 0 +-0.367167 0.872523 0.322308 0 +-0.294048 0.905226 0.30669 0 +-0.431132 0.839896 0.329651 0 +-0.516558 0.773875 0.366442 0 +-0.356947 0.839066 0.410573 0 +-0.333364 0.803803 0.492713 0 +-0.272076 0.836759 0.475201 0 +-0.707465 0.615102 0.347954 0 +-0.674666 0.607074 0.419791 0 +-0.6629 0.669081 0.336019 0 +-0.596438 0.71449 0.365748 0 +-0.623254 0.728902 0.283244 0 +-0.627279 0.704634 0.32807 0 +-0.729044 0.626165 0.276426 0 +-0.747894 0.632174 0.202393 0 +-0.447212 0.874572 0.187399 0 +-0.388765 0.888744 0.242937 0 +-0.514106 0.846801 0.13651 0 +-0.578267 0.811334 0.0857058 0 +-0.482328 0.843076 0.237812 0 +-0.562568 0.78544 0.25808 0 +-0.499233 0.813355 0.298732 0 +-0.758997 0.648442 -0.0586322 0 +-0.772823 0.634413 0.0154448 0 +-0.771978 0.623001 0.126173 0 +-0.707027 0.706511 -0.0310994 0 +-0.632823 0.773755 0.0288733 0 +-0.801589 0.488474 0.34464 0 +-0.75413 0.551018 0.357218 0 +-0.811952 0.512982 0.278566 0 +-0.789566 0.573246 0.219048 0 +-0.841351 0.503906 0.195391 0 +-0.814572 0.530007 0.23067 0 +-0.843538 0.429648 0.322252 0 +-0.880807 0.36669 0.299449 0 +-0.850225 0.523724 -0.0531409 0 +-0.805762 0.586809 -0.0801549 0 +-0.889932 0.455938 -0.0123812 0 +-0.922588 0.384605 0.0301679 0 +-0.837322 0.546577 0.0108632 0 +-0.845688 0.522506 0.108656 0 +-0.809619 0.58336 0.0650321 0 +-0.971615 0.150753 0.182289 0 +-0.950764 0.204631 0.232697 0 +-0.911726 0.293379 0.287547 0 +-0.969129 0.211776 0.126302 0 +-0.949032 0.308599 0.0640355 0 +-0.778775 0.406284 0.477883 0 +-0.726614 0.454148 0.51548 0 +-0.78636 0.456339 0.416331 0 +-0.82074 0.361032 0.442783 0 +-0.863607 0.344534 0.368085 0 +-0.857174 0.281415 0.43131 0 +-0.847419 0.328628 0.414151 0 +-0.772613 0.351328 0.528807 0 +-0.760639 0.294535 0.578472 0 +-0.715006 0.344454 0.608378 0 +-0.945408 0.0783391 0.316322 0 +-0.966483 0.0937475 0.239047 0 +-0.914154 0.0728154 0.398789 0 +-0.87524 0.0681429 0.478864 0 +-0.934826 0.146355 0.323498 0 +-0.896855 0.216263 0.385858 0 +-0.926597 0.215388 0.308296 0 +-0.705778 0.0731946 0.704636 0 +-0.647207 0.0928381 0.756654 0 +-0.715254 0.145763 0.683477 0 +-0.685278 0.218464 0.694757 0 +-0.734383 0.242951 0.633763 0 +-0.761191 0.0564363 0.646077 0 +-0.831311 0.0549276 0.553083 0 +-0.775429 -0.406877 0.482793 0 +-0.723981 -0.456094 0.517463 0 +-0.763268 -0.361762 0.535316 0 +-0.716447 -0.344245 0.606799 0 +-0.76977 -0.280567 0.573331 0 +-0.749941 -0.328553 0.57208 0 +-0.818558 -0.353191 0.453011 0 +-0.857946 -0.299111 0.417623 0 +-0.704921 -0.0696802 0.705849 0 +-0.646017 -0.090866 0.75791 0 +-0.69135 0.0015533 0.722492 0 +-0.758423 -0.0462899 0.650125 0 +-0.797198 0.00365093 0.603724 0 +-0.827701 -0.0487508 0.559045 0 +-0.714679 -0.138467 0.685594 0 +-0.755227 -0.208897 0.621282 0 +-0.694962 -0.211893 0.687131 0 +-0.943279 -0.0795726 0.322308 0 +-0.951788 7.378e-05 0.30669 0 +-0.932016 -0.150489 0.329651 0 +-0.895624 -0.252135 0.366442 0 +-0.908302 -0.080191 0.410573 0 +-0.867478 -0.0686593 0.492713 0 +-0.879881 -0.000186698 0.475201 0 +-0.803616 -0.482762 0.347954 0 +-0.785845 -0.454049 0.419791 0 +-0.841181 -0.423698 0.336019 0 +-0.86383 -0.346456 0.365748 0 +-0.885823 -0.367507 0.283244 0 +-0.863987 -0.378834 0.32807 0 +-0.820805 -0.499866 0.276426 0 +-0.832345 -0.515937 0.202393 0 +-0.969963 -0.155066 0.187399 0 +-0.96538 -0.0951006 0.242937 0 +-0.964223 -0.227268 0.13651 0 +-0.950318 -0.299248 0.0857058 0 +-0.95086 -0.198196 0.237812 0 +-0.920841 -0.29232 0.25808 0 +-0.927818 -0.223459 0.298732 0 +-0.851248 -0.52147 -0.0586322 0 +-0.842178 -0.538954 0.0154448 0 +-0.831063 -0.541677 0.126173 0 +-0.890415 -0.454098 -0.0310994 0 +-0.931438 -0.362747 0.0288733 0 +-0.712271 -0.61141 0.34464 0 +-0.757089 -0.546946 0.357218 0 +-0.738782 -0.613692 0.278566 0 +-0.789178 -0.573779 0.219048 0 +-0.739235 -0.644457 0.195391 0 +-0.755784 -0.610923 0.23067 0 +-0.669287 -0.669483 0.322252 0 +-0.620927 -0.724384 0.299449 0 +-0.760825 -0.646772 -0.0531409 0 +-0.807083 -0.584991 -0.0801549 0 +-0.708627 -0.705483 -0.0123812 0 +-0.650876 -0.758584 0.0301679 0 +-0.778572 -0.627439 0.0108632 0 +-0.758264 -0.642834 0.108656 0 +-0.804994 -0.589725 0.0650321 0 +-0.44362 -0.877476 0.182289 0 +-0.488418 -0.840996 0.232697 0 +-0.560759 -0.776444 0.287547 0 +-0.500888 -0.856254 0.126302 0 +-0.586762 -0.807221 0.0640356 0 +-0.627054 -0.615111 0.477883 0 +-0.656456 -0.550712 0.51548 0 +-0.677002 -0.606856 0.416331 0 +-0.596985 -0.669005 0.442783 0 +-0.59454 -0.714872 0.368085 0 +-0.532523 -0.728259 0.43131 0 +-0.57441 -0.704392 0.414151 0 +-0.572883 -0.626233 0.528807 0 +-0.51517 -0.632395 0.578472 0 +-0.548545 -0.573569 0.608378 0 +-0.366652 -0.874928 0.316322 0 +-0.387819 -0.890211 0.239047 0 +-0.351741 -0.846911 0.398789 0 +-0.335272 -0.811346 0.478864 0 +-0.428069 -0.843847 0.323498 0 +-0.482822 -0.786131 0.385858 0 +-0.49118 -0.814688 0.308296 0 +-0.287709 -0.648616 0.704636 0 +-0.288292 -0.586842 0.756655 0 +-0.359654 -0.635203 0.683477 0 +-0.419534 -0.584229 0.694757 0 +-0.457997 -0.623363 0.633763 0 +-0.288895 -0.706496 0.646077 0 +-0.309128 -0.77365 0.553084 0 +0.147343 -0.863209 0.482793 0 +0.210049 -0.829488 0.517463 0 +0.108194 -0.837702 0.535316 0 +0.106002 -0.787759 0.6068 0 +0.028963 -0.818794 0.573331 0 +0.0807278 -0.814765 0.57208 0 +0.0829561 -0.887637 0.453011 0 +0.0193518 -0.908385 0.417623 0 +-0.151563 -0.691952 0.705849 0 +-0.113211 -0.642477 0.75791 0 +-0.215115 -0.657033 0.722492 0 +-0.190341 -0.735608 0.650125 0 +-0.24982 -0.757052 0.603724 0 +-0.209409 -0.802256 0.559045 0 +-0.0891576 -0.722489 0.685595 0 +-0.034705 -0.782816 0.621282 0 +-0.0132332 -0.726426 0.687131 0 +-0.215811 -0.921701 0.322308 0 +-0.294189 -0.905181 0.30669 0 +-0.144885 -0.932903 0.329651 0 +-0.036968 -0.929703 0.366442 0 +-0.204415 -0.888627 0.410573 0 +-0.202766 -0.846237 0.492713 0 +-0.271721 -0.836874 0.475201 0 +0.210803 -0.913465 0.347954 0 +0.188987 -0.887692 0.419791 0 +0.143021 -0.930941 0.336019 0 +0.0625613 -0.928612 0.365748 0 +0.0757854 -0.956034 0.283244 0 +0.0933063 -0.938766 0.32807 0 +0.221758 -0.9351 0.276426 0 +0.233477 -0.95104 0.202393 0 +-0.152258 -0.970408 0.187399 0 +-0.207873 -0.947519 0.242937 0 +-0.0818168 -0.98726 0.13651 0 +-0.00906227 -0.996279 0.0857058 0 +-0.105336 -0.965568 0.237812 0 +-0.00654298 -0.966104 0.25808 0 +-0.0741899 -0.95146 0.298732 0 +0.232897 -0.970728 -0.0586322 0 +0.252328 -0.967505 0.0154448 0 +0.258353 -0.957775 0.126173 0 +0.15672 -0.987159 -0.0310994 0 +0.0571628 -0.997945 0.0288733 0 +0.361381 -0.866346 0.34464 0 +0.286223 -0.88905 0.357218 0 +0.355359 -0.892264 0.278566 0 +0.301827 -0.927861 0.219048 0 +0.384479 -0.902202 0.195391 0 +0.347472 -0.907578 0.23067 0 +0.429895 -0.843412 0.322252 0 +0.497053 -0.814384 0.299449 0 +0.380009 -0.923451 -0.0531409 0 +0.306957 -0.948354 -0.0801549 0 +0.451977 -0.89195 -0.0123812 0 +0.520325 -0.853436 0.0301679 0 +0.356138 -0.934355 0.0108632 0 +0.377055 -0.919799 0.108656 0 +0.312105 -0.94783 0.0650321 0 +0.697443 -0.693063 0.182289 0 +0.648905 -0.724395 0.232697 0 +0.565158 -0.773248 0.287547 0 +0.659563 -0.74097 0.126302 0 +0.586393 -0.807489 0.0640355 0 +0.391234 -0.786444 0.477883 0 +0.320902 -0.794506 0.51548 0 +0.367949 -0.831396 0.416331 0 +0.451783 -0.7745 0.442783 0 +0.496161 -0.786349 0.368085 0 +0.528057 -0.731504 0.43131 0 +0.492414 -0.763965 0.414151 0 +0.418552 -0.73836 0.528809 0 +0.442247 -0.685371 0.578478 0 +0.375986 -0.698938 0.60838 0 +0.718804 -0.619074 0.316322 0 +0.726798 -0.643928 0.239047 0 +0.696767 -0.596234 0.39879 0 +0.668032 -0.569577 0.478869 0 +0.670265 -0.66788 0.323499 0 +0.598455 -0.702119 0.38586 0 +0.623031 -0.718892 0.308296 0 +0.527991 -0.473706 0.704854 0 +0.469048 -0.45478 0.757094 0 +0.492922 -0.538292 0.683553 0 +0.425967 -0.579458 0.694838 0 +0.45132 -0.628186 0.633791 0 +0.58272 -0.49289 0.646149 0 +0.640271 -0.533045 0.553093 0 +0.86653 -0.126695 0.482705 0 +0.853909 -0.0567902 0.517254 0 +0.830294 -0.156176 0.535007 0 +0.78278 -0.143983 0.605418 0 +0.787782 -0.225571 0.57314 0 +0.800138 -0.175464 0.571508 0 +0.869842 -0.195437 0.452967 0 +0.869903 -0.26233 0.417612 0 +0.612183 -0.357087 0.705487 0 +0.578682 -0.303559 0.756968 0 +0.558749 -0.406704 0.72274 0 +0.641216 -0.408046 0.649886 0 +0.64291 -0.471425 0.603693 0 +0.698338 -0.447074 0.558969 0 +0.660717 -0.308709 0.684202 0 +0.734864 -0.27588 0.619565 0 +0.690119 -0.239254 0.683018 0 +0.809901 -0.49007 0.322308 0 +0.769969 -0.559506 0.306689 0 +0.842472 -0.426079 0.329649 0 +0.872776 -0.322466 0.366432 0 +0.781971 -0.469016 0.410559 0 +0.742177 -0.454365 0.492669 0 +0.711954 -0.51703 0.475192 0 +0.933902 -0.0818012 0.347946 0 +0.902659 -0.0946161 0.419754 0 +0.929574 -0.151661 0.336014 0 +0.902495 -0.227466 0.365743 0 +0.932661 -0.223355 0.283244 0 +0.921653 -0.201358 0.328068 0 +0.95786 -0.0780606 0.276423 0 +0.976641 -0.0718385 0.202393 0 +0.875862 -0.444679 0.187399 0 +0.836908 -0.490498 0.242937 0 +0.913658 -0.382893 0.13651 0 +0.944717 -0.316486 0.0857058 0 +0.885759 -0.398558 0.237811 0 +0.916797 -0.304766 0.258079 0 +0.881966 -0.364579 0.298729 0 +0.995186 -0.078473 -0.0586322 0 +0.998126 -0.0589969 0.015445 0 +0.990734 -0.0502609 0.126173 0 +0.987274 -0.156 -0.0310994 0 +0.966767 -0.254017 0.0288733 0 +0.935614 0.0759611 0.344653 0 +0.933989 -0.00254736 0.357205 0 +0.958401 0.0622371 0.278586 0 +0.975717 0.000328091 0.219049 0 +0.976855 0.0868654 0.195395 0 +0.970532 0.0500069 0.230676 0 +0.934912 0.148208 0.322448 0 +0.927918 0.221164 0.300009 0 +0.995683 0.0760483 -0.05314 0 +0.996793 -0.00112396 -0.0801547 0 +0.987963 0.154231 -0.0123706 0 +0.97245 0.231144 0.0302067 0 +0.998677 0.0499766 0.0108676 0 +0.991296 0.0743687 0.108666 0 +0.997886 0.00393461 0.0650347 0 +0.874168 0.449819 0.182991 0 +0.888597 0.394091 0.234648 0 +0.909127 0.299281 0.289687 0 +0.908352 0.398618 0.126538 0 +0.949135 0.308244 0.0642128 0 +0.868805 0.128496 0.478117 0 +0.854836 0.0592524 0.515444 0 +0.904385 0.0928441 0.416419 0 +0.876038 0.189426 0.443495 0 +0.900636 0.228889 0.36942 0 +0.858269 0.276809 0.432114 0 +0.878359 0.232146 0.415001 0 +0.831403 0.167615 0.529788 0 +0.788229 0.203023 0.580882 0 +0.780672 0.138612 0.60938 0 +0.80654 0.500226 0.315053 0 +0.835302 0.494855 0.239608 0 +0.772033 0.56261 0.295629 0 +0.772172 0.503438 0.387699 0 +0.723497 0.529267 0.443225 0 +0.733166 0.470516 0.490998 0 +0.835276 0.437934 0.332427 0 +0.845485 0.356565 0.39751 0 +0.872941 0.373205 0.314184 0 +0.621699 0.351914 0.699741 0 +0.56637 0.410827 0.714426 0 +0.578263 0.304363 0.756966 0 +0.665522 0.292841 0.686508 0 +0.680635 0.215484 0.70023 0 +0.736842 0.222209 0.638499 0 +0.673241 0.388969 0.628858 0 +0.711075 0.430755 0.555716 0 +0.662538 0.480533 0.574576 0 +-0.388297 0.78464 -0.483213 0 +-0.317631 0.794432 -0.517617 0 +-0.404865 0.740643 -0.536235 0 +-0.376301 0.699238 -0.607841 0 +-0.456771 0.679763 -0.573806 0 +-0.412982 0.706377 -0.572814 0 +-0.455271 0.765577 -0.454554 0 +-0.520261 0.742952 -0.421073 0 +-0.525021 0.477601 -0.704445 0 +-0.467286 0.454854 -0.758138 0 +-0.576677 0.508562 -0.639391 0 +-0.623253 0.536827 -0.568659 0 +-0.486256 0.534008 -0.691637 0 +-0.476588 0.613538 -0.629636 0 +-0.431691 0.579829 -0.690986 0 +-0.723002 0.615238 -0.314234 0 +-0.667775 0.666763 -0.330872 0 +-0.581114 0.724348 -0.37098 0 +-0.710346 0.585179 -0.391135 0 +-0.668967 0.553562 -0.496033 0 +-0.365867 0.863027 -0.348215 0 +-0.36881 0.82914 -0.420052 0 +-0.430435 0.837569 -0.336478 0 +-0.495459 0.787607 -0.366335 0 +-0.499863 0.818782 -0.282318 0 +-0.475642 0.814672 -0.328193 0 +-0.367878 0.88762 -0.277121 0 +-0.364276 0.908576 -0.204303 0 +-0.699137 0.692023 -0.179731 0 +-0.728281 0.642967 -0.237112 0 +-0.74214 0.657358 -0.130655 0 +-0.666428 0.735748 -0.120664 0 +-0.651288 0.757387 -0.0470183 0 +-0.592425 0.803118 -0.0634949 0 +-0.654205 0.721907 -0.225492 0 +-0.571579 0.782628 -0.246552 0 +-0.621032 0.726183 -0.294952 0 +-0.383414 0.922269 0.0490425 0 +-0.405335 0.905253 0.127196 0 +-0.35594 0.934255 -0.0210268 0 +-0.341771 0.930582 -0.131163 0 +-0.458074 0.888921 -0.000707395 0 +-0.530865 0.84655 -0.0391559 0 +-0.546313 0.837029 0.0305256 0 +-0.21658 0.913164 -0.345185 0 +-0.29063 0.887506 -0.357498 0 +-0.236044 0.930624 -0.279703 0 +-0.297872 0.928917 -0.21998 0 +-0.217917 0.956251 -0.195108 0 +-0.250692 0.938789 -0.231221 0 +-0.147417 0.934352 -0.32443 0 +-0.07575 0.949336 -0.304911 0 +-0.232101 0.97078 0.0608806 0 +-0.307672 0.948143 0.0799002 0 +-0.213499 0.967826 0.133014 0 +-0.155725 0.986947 0.0411914 0 +-0.0786776 0.995552 0.0520327 0 +-0.060021 0.997955 -0.0219418 0 +-0.247086 0.968946 -0.00849674 0 +-0.219613 0.969454 -0.109195 0 +-0.292863 0.953787 -0.0673956 0 +0.146788 0.971849 -0.184263 0 +0.203766 0.970876 -0.125849 0 +0.099157 0.966128 -0.238192 0 +0.00283148 0.954501 -0.298185 0 +0.0669554 0.988483 -0.135762 0 +-0.00466162 0.996915 -0.078342 0 +0.0495046 0.998294 -0.0310657 0 +-0.145648 0.866148 -0.478021 0 +-0.20735 0.831366 -0.515534 0 +-0.190866 0.888766 -0.416658 0 +-0.0894461 0.892009 -0.443095 0 +-0.0604288 0.927028 -0.370101 0 +-0.00198093 0.902419 -0.430822 0 +-0.0500512 0.907331 -0.414559 0 +-0.0953249 0.843359 -0.528828 0 +-0.0450488 0.814422 -0.578481 0 +-0.106639 0.786451 -0.608383 0 +0.216652 0.923623 -0.316188 0 +0.205942 0.948922 -0.239076 0 +0.212935 0.891995 -0.398767 0 +0.205591 0.853482 -0.478854 0 +0.148952 0.933878 -0.32505 0 +0.0713798 0.918993 -0.387765 0 +0.0812901 0.946299 -0.312939 0 +0.148716 0.693582 -0.704854 0 +0.112155 0.643624 -0.757094 0 +0.0823834 0.725217 -0.683556 0 +0.00402131 0.719167 -0.694841 0 +-0.00410781 0.77349 -0.633794 0 +0.181717 0.74127 -0.64615 0 +0.204658 0.807598 -0.55308 0 +-0.866227 -0.126829 -0.483213 0 +-0.8537 -0.0566122 -0.517618 0 +-0.829503 -0.156183 -0.536234 0 +-0.781299 -0.141817 -0.607838 0 +-0.787643 -0.224357 -0.573806 0 +-0.799423 -0.17449 -0.572813 0 +-0.868793 -0.196413 -0.454554 0 +-0.867359 -0.265213 -0.421073 0 +-0.616466 -0.351738 -0.704445 0 +-0.576991 -0.303858 -0.758138 0 +-0.661875 -0.391298 -0.639391 0 +-0.703149 -0.42686 -0.568659 0 +-0.658133 -0.297441 -0.691637 0 +-0.730783 -0.26367 -0.629635 0 +-0.684851 -0.23139 -0.690983 0 +-0.808546 -0.497497 -0.314234 0 +-0.840483 -0.429051 -0.330872 0 +-0.86847 -0.328836 -0.37098 0 +-0.776047 -0.494749 -0.391135 0 +-0.733191 -0.465165 -0.496033 0 +-0.933847 -0.0812723 -0.348215 0 +-0.902526 -0.0945477 -0.420053 0 +-0.929587 -0.150545 -0.336478 0 +-0.902164 -0.227826 -0.366335 0 +-0.933175 -0.22238 -0.282318 0 +-0.921781 -0.200615 -0.328193 0 +-0.957857 -0.0755837 -0.277122 0 +-0.976674 -0.0656814 -0.204303 0 +-0.874198 -0.451072 -0.179731 0 +-0.836549 -0.493949 -0.237112 0 +-0.854519 -0.502682 -0.130655 0 +-0.905675 -0.406452 -0.120664 0 +-0.921576 -0.385366 -0.0470183 0 +-0.94688 -0.315253 -0.0634949 0 +-0.888735 -0.399104 -0.225492 0 +-0.920951 -0.301759 -0.246552 0 +-0.88255 -0.366234 -0.294952 0 +-0.995611 -0.0796512 0.0490425 0 +-0.986202 -0.105758 0.127196 0 +-0.99852 -0.0498181 -0.0210269 0 +-0.990649 -0.0374778 -0.131163 0 +-0.986967 -0.160962 -0.000707397 0 +-0.969163 -0.243284 -0.0391559 0 +-0.964882 -0.260918 0.0305256 0 +-0.935391 0.0761922 -0.345205 0 +-0.933876 -0.00216074 -0.357505 0 +-0.95801 0.0630821 -0.27973 0 +-0.9755 0.00375795 -0.219982 0 +-0.976789 0.0882467 -0.195109 0 +-0.970308 0.0516777 -0.231228 0 +-0.934109 0.148493 -0.32464 0 +-0.926063 0.221374 -0.305529 0 +-0.99499 0.0792462 0.06088 0 +-0.996814 0.00037892 0.0799 0 +-0.986432 0.0960248 0.133014 0 +-0.986764 0.156882 0.0411886 0 +-0.971138 0.23282 0.0520307 0 +-0.967657 0.251307 -0.0219477 0 +-0.997876 0.0644295 -0.00849958 0 +-0.98987 0.0907145 -0.109201 0 +-0.997604 0.0162079 -0.0673972 0 +-0.878593 0.440092 -0.18543 0 +-0.860213 0.49413 -0.125808 0 +-0.887615 0.391154 -0.243115 0 +-0.905937 0.298164 -0.300616 0 +-0.919323 0.36922 -0.136146 0 +-0.949545 0.303669 -0.0784061 0 +-0.934117 0.355622 -0.0310824 0 +-0.868708 0.128578 -0.478271 0 +-0.854715 0.0594602 -0.51562 0 +-0.904213 0.0929562 -0.41677 0 +-0.875832 0.18949 -0.443873 0 +-0.899801 0.229057 -0.371346 0 +-0.85817 0.276785 -0.432326 0 +-0.877999 0.23219 -0.415732 0 +-0.831353 0.167871 -0.529785 0 +-0.788299 0.203698 -0.580551 0 +-0.780793 0.139678 -0.608982 0 +-0.807257 0.49912 -0.314972 0 +-0.837318 0.491222 -0.240045 0 +-0.773043 0.56178 -0.294568 0 +-0.772472 0.503034 -0.387626 0 +-0.723621 0.529266 -0.443025 0 +-0.733169 0.470521 -0.49099 0 +-0.835072 0.436895 -0.334302 0 +-0.844706 0.356114 -0.399563 0 +-0.871529 0.37186 -0.31965 0 +-0.622268 0.352864 -0.698756 0 +-0.566679 0.410543 -0.714344 0 +-0.580673 0.304741 -0.754965 0 +-0.664492 0.29983 -0.684489 0 +-0.68325 0.222162 -0.695582 0 +-0.737581 0.224883 -0.636707 0 +-0.673383 0.38943 -0.628421 0 +-0.711084 0.430898 -0.555594 0 +-0.66257 0.480574 -0.574505 0 +-0.147057 -0.863023 -0.483213 0 +-0.209966 -0.829411 -0.517618 0 +-0.107791 -0.837168 -0.536234 0 +-0.106558 -0.786883 -0.607838 0 +-0.0300187 -0.818423 -0.573806 0 +-0.0810856 -0.814217 -0.572813 0 +-0.0816717 -0.886967 -0.454554 0 +-0.0157956 -0.906863 -0.421073 0 +0.144024 -0.694987 -0.704445 0 +0.110686 -0.642649 -0.758138 0 +0.167616 -0.750398 -0.639391 0 +0.188683 -0.800641 -0.568659 0 +0.0795085 -0.717836 -0.691637 0 +0.0249405 -0.776495 -0.629635 0 +0.00843468 -0.722836 -0.690983 0 +0.223293 -0.922708 -0.314234 0 +0.148328 -0.931931 -0.330872 0 +0.04437 -0.92758 -0.37098 0 +0.230722 -0.890951 -0.391135 0 +0.21583 -0.84105 -0.496033 0 +-0.21128 -0.913255 -0.348215 0 +-0.188976 -0.88757 -0.420053 0 +-0.144081 -0.930611 -0.336478 0 +-0.0621087 -0.928412 -0.366335 0 +-0.0768706 -0.956221 -0.282318 0 +-0.0940501 -0.938659 -0.328193 0 +-0.22411 -0.934333 -0.277122 0 +-0.239342 -0.949169 -0.204303 0 +0.158853 -0.970801 -0.179731 0 +0.211266 -0.948244 -0.237112 0 +0.214018 -0.968033 -0.130655 0 +0.10669 -0.986949 -0.120664 0 +0.081722 -0.995556 -0.0470183 0 +0.00722113 -0.997955 -0.0634949 0 +0.104936 -0.968567 -0.225492 0 +0.0024002 -0.969125 -0.246552 0 +0.0755859 -0.952528 -0.294952 0 +-0.231908 -0.971496 0.0490425 0 +-0.204172 -0.970615 0.127196 0 +-0.26118 -0.965044 -0.0210269 0 +-0.270484 -0.953745 -0.131163 0 +-0.151906 -0.988402 -0.00070739 0 +-0.0681112 -0.996908 -0.0391559 0 +-0.0500171 -0.998285 0.0305256 0 +-0.361515 -0.866065 -0.345205 0 +-0.286528 -0.888836 -0.357505 0 +-0.356036 -0.891628 -0.27973 0 +-0.30502 -0.926594 -0.219982 0 +-0.385772 -0.901712 -0.195109 0 +-0.34899 -0.906849 -0.231228 0 +-0.42988 -0.842503 -0.32464 0 +-0.496709 -0.81233 -0.305529 0 +-0.382836 -0.921803 0.06088 0 +-0.308393 -0.947909 0.0799 0 +-0.396149 -0.90848 0.133014 0 +-0.45413 -0.889989 0.0411886 0 +-0.521523 -0.851662 0.0520308 0 +-0.53803 -0.842638 -0.0219477 0 +-0.369637 -0.929127 -0.00849958 0 +-0.392161 -0.91339 -0.109201 0 +-0.323691 -0.94377 -0.0673972 0 +-0.690053 -0.699595 -0.18543 0 +-0.735766 -0.665416 -0.125808 0 +-0.646298 -0.723299 -0.243115 0 +-0.563521 -0.76946 -0.300616 0 +-0.635235 -0.760233 -0.136146 0 +-0.582232 -0.809232 -0.0784061 0 +-0.626874 -0.778504 -0.0310824 0 +-0.390731 -0.786458 -0.478271 0 +-0.320672 -0.794508 -0.51562 0 +-0.367824 -0.831232 -0.41677 0 +-0.450863 -0.77441 -0.443873 0 +-0.4959 -0.784979 -0.371346 0 +-0.528427 -0.730637 -0.432326 0 +-0.492143 -0.763276 -0.415732 0 +-0.416557 -0.738789 -0.529785 0 +-0.437326 -0.686771 -0.580551 0 +-0.37412 -0.699415 -0.608982 0 +-0.724147 -0.613511 -0.314972 0 +-0.725926 -0.64454 -0.240045 0 +-0.773168 -0.561608 -0.294568 0 +-0.717121 -0.579219 -0.387626 0 +-0.726973 -0.524652 -0.443025 0 +-0.674053 -0.551886 -0.49099 0 +-0.673563 -0.659192 -0.334302 0 +-0.599713 -0.693317 -0.399563 0 +-0.622978 -0.713962 -0.31965 0 +-0.527885 -0.482771 -0.698756 0 +-0.565563 -0.412078 -0.714344 0 +-0.469264 -0.458083 -0.754965 0 +-0.490495 -0.539317 -0.684489 0 +-0.422425 -0.581158 -0.695582 0 +-0.441801 -0.631989 -0.636707 0 +-0.578457 -0.520085 -0.628421 0 +-0.629545 -0.543126 -0.555594 0 +-0.661798 -0.481636 -0.574505 0 +0.77534 -0.406548 -0.483213 0 +0.723934 -0.455992 -0.517618 0 +0.762884 -0.361214 -0.536234 0 +0.715441 -0.344502 -0.60784 0 +0.76909 -0.281456 -0.573807 0 +0.749309 -0.328723 -0.572814 0 +0.818317 -0.351762 -0.454554 0 +0.857596 -0.295258 -0.421073 0 +0.705424 -0.0778977 -0.704487 0 +0.645436 -0.0937125 -0.758058 0 +0.765427 -0.0725051 -0.639435 0 +0.819745 -0.0679689 -0.568681 0 +0.707229 -0.146234 -0.691674 0 +0.746184 -0.216226 -0.629653 0 +0.690037 -0.215339 -0.691013 0 +0.946548 -0.0727678 -0.314234 0 +0.932154 -0.146914 -0.330873 0 +0.895892 -0.244439 -0.370981 0 +0.91864 -0.0558881 -0.391137 0 +0.866575 -0.0546335 -0.496044 0 +0.803268 -0.483151 -0.348215 0 +0.785733 -0.454001 -0.420054 0 +0.84054 -0.424604 -0.336478 0 +0.863779 -0.345964 -0.366335 0 +0.885666 -0.368597 -0.282318 0 +0.863655 -0.379509 -0.328193 0 +0.81935 -0.501866 -0.277122 0 +0.828753 -0.520937 -0.204303 0 +0.972374 -0.148916 -0.179731 0 +0.967118 -0.0920978 -0.237112 0 +0.986789 -0.0955952 -0.130655 0 +0.971613 -0.203516 -0.120664 0 +0.972084 -0.229921 -0.0470183 0 +0.951343 -0.301517 -0.0634949 0 +0.953589 -0.199503 -0.225492 0 +0.922435 -0.297193 -0.246553 0 +0.929265 -0.222461 -0.294953 0 +0.852284 -0.520766 0.0490425 0 +0.860017 -0.494115 0.127196 0 +0.837102 -0.546612 -0.0210269 0 +0.823481 -0.551969 -0.131163 0 +0.893084 -0.449904 -0.000707404 0 +0.927068 -0.372839 -0.0391559 0 +0.933969 -0.356056 0.0305256 0 +0.711962 -0.61145 -0.345205 0 +0.756791 -0.54717 -0.357505 0 +0.737968 -0.614139 -0.27973 0 +0.786987 -0.576425 -0.219982 0 +0.738369 -0.645535 -0.195109 0 +0.75462 -0.612141 -0.231228 0 +0.668428 -0.669188 -0.32464 0 +0.61908 -0.723422 -0.305529 0 +0.758384 -0.648952 0.06088 0 +0.806217 -0.586219 0.0799 0 +0.741599 -0.657496 0.133014 0 +0.706096 -0.706925 0.0411886 0 +0.648819 -0.759175 0.0520307 0 +0.635136 -0.772086 -0.0219477 0 +0.769428 -0.638661 -0.00849958 0 +0.747501 -0.65522 -0.109201 0 +0.797552 -0.59949 -0.0673972 0 +0.452116 -0.872466 -0.18543 0 +0.405484 -0.90538 -0.125808 0 +0.488181 -0.838178 -0.243115 0 +0.557662 -0.773716 -0.300616 0 +0.526726 -0.83907 -0.136146 0 +0.589706 -0.803802 -0.0784061 0 +0.546687 -0.836764 -0.0310824 0 +0.627223 -0.614636 -0.478271 0 +0.656529 -0.550493 -0.51562 0 +0.676885 -0.606686 -0.41677 0 +0.597183 -0.668102 -0.443873 0 +0.593317 -0.714201 -0.371346 0 +0.531584 -0.728344 -0.432326 0 +0.573838 -0.703921 -0.415732 0 +0.573907 -0.624468 -0.529785 0 +0.518017 -0.628146 -0.580551 0 +0.549574 -0.57194 -0.608982 0 +0.35971 -0.87829 -0.314972 0 +0.388671 -0.88957 -0.240045 0 +0.295199 -0.908873 -0.294568 0 +0.329267 -0.861011 -0.387626 0 +0.274326 -0.853519 -0.443025 0 +0.316581 -0.811605 -0.49099 0 +0.418787 -0.844299 -0.334302 0 +0.474063 -0.784608 -0.399563 0 +0.486508 -0.813113 -0.31965 0 +0.296017 -0.651233 -0.698756 0 +0.217141 -0.665222 -0.714344 0 +0.290652 -0.587852 -0.754965 0 +0.36135 -0.633146 -0.684489 0 +0.422177 -0.581337 -0.695582 0 +0.464533 -0.615473 -0.636707 0 +0.315877 -0.71086 -0.628421 0 +0.322004 -0.766568 -0.555594 0 +0.253556 -0.778241 -0.574505 0 +0.626586 0.61182 -0.482696 0 +0.657452 0.547855 -0.517253 0 +0.579947 0.614376 -0.534991 0 +0.548652 0.576591 -0.605417 0 +0.504742 0.645537 -0.573139 0 +0.544196 0.612262 -0.571504 0 +0.589014 0.669327 -0.452841 0 +0.550028 0.723474 -0.417134 0 +0.285377 0.648722 -0.705486 0 +0.289737 0.585725 -0.756968 0 +0.212983 0.657456 -0.72274 0 +0.278914 0.707019 -0.649879 0 +0.243027 0.759293 -0.603683 0 +0.30219 0.772182 -0.558939 0 +0.353079 0.638112 -0.684199 0 +0.432364 0.655137 -0.619558 0 +0.417689 0.599203 -0.683016 0 +0.367889 0.872701 -0.321 0 +0.293402 0.905785 -0.305657 0 +0.435573 0.838343 -0.327757 0 +0.518215 0.773767 -0.364324 0 +0.357178 0.839216 -0.410065 0 +0.333404 0.803904 -0.492521 0 +0.272035 0.836856 -0.475053 0 +0.707799 0.614629 -0.34811 0 +0.674776 0.606966 -0.41977 0 +0.663835 0.66806 -0.336202 0 +0.597337 0.714239 -0.36477 0 +0.624405 0.728336 -0.282165 0 +0.628342 0.703909 -0.327614 0 +0.730525 0.624149 -0.277076 0 +0.75154 0.627215 -0.204293 0 +0.442582 0.878396 -0.180371 0 +0.388172 0.889947 -0.239457 0 +0.395379 0.909039 -0.131474 0 +0.493967 0.861045 -0.120863 0 +0.519058 0.853453 -0.0470988 0 +0.580751 0.8116 -0.0634945 0 +0.486285 0.844377 -0.224798 0 +0.569387 0.784629 -0.245259 0 +0.503424 0.813188 -0.292076 0 +0.758467 0.649889 0.0486013 0 +0.735514 0.665599 0.126312 0 +0.778514 0.627239 -0.0213189 0 +0.779406 0.612622 -0.131206 0 +0.70376 0.710447 -0.000903493 0 +0.641033 0.766511 -0.0391954 0 +0.627203 0.778266 0.030426 0 +0.801537 0.488173 -0.345187 0 +0.754275 0.550676 -0.357439 0 +0.812128 0.512071 -0.27972 0 +0.791403 0.570348 -0.219979 0 +0.842108 0.50275 -0.195109 0 +0.815371 0.528527 -0.231225 0 +0.842992 0.428926 -0.324633 0 +0.879321 0.365232 -0.305528 0 +0.851337 0.521099 0.0605989 0 +0.806409 0.586065 0.0790791 0 +0.854213 0.502725 0.132481 0 +0.890419 0.453299 0.0410576 0 +0.92245 0.382612 0.0521165 0 +0.930558 0.365484 -0.0219365 0 +0.845056 0.534589 -0.00866481 0 +0.854115 0.508479 -0.109236 0 +0.816557 0.57332 -0.0675143 0 +0.969476 0.160382 -0.18543 0 +0.986369 0.105861 -0.125808 0 +0.94801 0.205278 -0.243115 0 +0.908174 0.29128 -0.300617 0 +0.960769 0.241662 -0.136144 0 +0.946687 0.312465 -0.0784007 0 +0.964744 0.261364 -0.031065 0 +0.778365 0.406664 -0.478228 0 +0.726402 0.454494 -0.515474 0 +0.786169 0.456316 -0.416716 0 +0.819923 0.361544 -0.443873 0 +0.862589 0.343583 -0.371344 0 +0.856963 0.280498 -0.432328 0 +0.84679 0.328241 -0.415732 0 +0.771117 0.353061 -0.529838 0 +0.757016 0.299045 -0.580901 0 +0.713049 0.346724 -0.609385 0 +0.946459 0.0707 -0.314974 0 +0.966137 0.0947563 -0.240045 0 +0.955611 -0.000105984 -0.294569 0 +0.920614 0.0470944 -0.387637 0 +0.896512 -0.00284881 -0.443033 0 +0.8697 0.0502961 -0.491008 0 +0.932383 0.137398 -0.334312 0 +0.892687 0.208424 -0.399582 0 +0.923653 0.211437 -0.319656 0 +0.709815 0.0807207 -0.699741 0 +0.699681 0.000537471 -0.714426 0 +0.646724 0.0936593 -0.756966 0 +0.710543 0.15427 -0.686511 0 +0.677301 0.225736 -0.700233 0 +0.726722 0.253328 -0.638509 0 +0.773289 0.0810355 -0.628864 0 +0.82845 0.0694624 -0.555737 0 +0.818461 0.000659717 -0.574567 0 + +Quadrilaterals +1980 +124 485 483 484 0 +485 125 665 483 0 +484 483 673 123 0 +483 665 33 673 0 +127 488 486 487 0 +488 128 681 486 0 +487 486 689 126 0 +486 681 36 689 0 +130 491 489 490 0 +491 131 697 489 0 +490 489 705 129 0 +489 697 39 705 0 +133 494 492 493 0 +494 134 713 492 0 +493 492 721 132 0 +492 713 42 721 0 +136 497 495 496 0 +497 137 729 495 0 +496 495 737 135 0 +495 729 45 737 0 +139 500 498 499 0 +500 140 745 498 0 +499 498 753 138 0 +498 745 48 753 0 +142 503 501 502 0 +503 143 761 501 0 +502 501 771 141 0 +501 761 51 771 0 +145 506 504 505 0 +506 146 781 504 0 +505 504 789 144 0 +504 781 53 789 0 +148 509 507 508 0 +509 149 797 507 0 +508 507 805 147 0 +507 797 56 805 0 +151 512 510 511 0 +512 152 813 510 0 +511 510 821 150 0 +510 813 59 821 0 +154 515 513 514 0 +515 155 829 513 0 +514 513 837 153 0 +513 829 62 837 0 +157 518 516 517 0 +518 158 845 516 0 +517 516 855 156 0 +516 845 65 855 0 +160 521 519 520 0 +521 161 867 519 0 +520 519 878 159 0 +519 867 35 878 0 +163 524 522 523 0 +524 164 891 522 0 +523 522 902 162 0 +522 891 67 902 0 +166 527 525 526 0 +527 167 915 525 0 +526 525 926 165 0 +525 915 68 926 0 +169 530 528 529 0 +530 170 940 528 0 +529 528 952 168 0 +528 940 69 952 0 +172 533 531 532 0 +533 173 967 531 0 +532 531 978 171 0 +531 967 38 978 0 +175 536 534 535 0 +536 176 991 534 0 +535 534 1002 174 0 +534 991 70 1002 0 +178 539 537 538 0 +539 179 1015 537 0 +538 537 1026 177 0 +537 1015 71 1026 0 +181 542 540 541 0 +542 182 1040 540 0 +541 540 1052 180 0 +540 1040 72 1052 0 +184 545 543 544 0 +545 185 1067 543 0 +544 543 1076 183 0 +543 1067 41 1076 0 +187 548 546 547 0 +548 188 1087 546 0 +547 546 1096 186 0 +546 1087 74 1096 0 +190 551 549 550 0 +551 191 1107 549 0 +550 549 1116 189 0 +549 1107 76 1116 0 +193 554 552 553 0 +554 194 1128 552 0 +553 552 1138 192 0 +552 1128 78 1138 0 +196 557 555 556 0 +557 197 1151 555 0 +556 555 1162 195 0 +555 1151 44 1162 0 +199 560 558 559 0 +560 200 1175 558 0 +559 558 1184 198 0 +558 1175 80 1184 0 +202 563 561 562 0 +563 203 1195 561 0 +562 561 1204 201 0 +561 1195 82 1204 0 +205 566 564 565 0 +566 206 1216 564 0 +565 564 1226 204 0 +564 1216 84 1226 0 +208 569 567 568 0 +569 209 1239 567 0 +568 567 1250 207 0 +567 1239 47 1250 0 +211 572 570 571 0 +572 212 1263 570 0 +571 570 1272 210 0 +570 1263 86 1272 0 +214 575 573 574 0 +575 215 1283 573 0 +574 573 1292 213 0 +573 1283 88 1292 0 +217 578 576 577 0 +578 218 1304 576 0 +577 576 1314 216 0 +576 1304 90 1314 0 +220 581 579 580 0 +581 221 1327 579 0 +580 579 1338 219 0 +579 1327 50 1338 0 +223 584 582 583 0 +584 224 1351 582 0 +583 582 1360 222 0 +582 1351 92 1360 0 +226 587 585 586 0 +587 227 1371 585 0 +586 585 1380 225 0 +585 1371 94 1380 0 +229 590 588 589 0 +590 230 1392 588 0 +589 588 1402 228 0 +588 1392 96 1402 0 +232 593 591 592 0 +593 233 1415 591 0 +592 591 1426 231 0 +591 1415 52 1426 0 +235 596 594 595 0 +596 236 1439 594 0 +595 594 1448 234 0 +594 1439 98 1448 0 +238 599 597 598 0 +599 239 1459 597 0 +598 597 1468 237 0 +597 1459 100 1468 0 +241 602 600 601 0 +602 242 1480 600 0 +601 600 1492 240 0 +600 1480 102 1492 0 +244 605 603 604 0 +605 245 1507 603 0 +604 603 1516 243 0 +603 1507 55 1516 0 +247 608 606 607 0 +608 248 1527 606 0 +607 606 1538 246 0 +606 1527 104 1538 0 +250 611 609 610 0 +611 251 1551 609 0 +610 609 1562 249 0 +609 1551 105 1562 0 +253 614 612 613 0 +614 254 1576 612 0 +613 612 1586 252 0 +612 1576 106 1586 0 +256 617 615 616 0 +617 257 1599 615 0 +616 615 1608 255 0 +615 1599 58 1608 0 +259 620 618 619 0 +620 260 1619 618 0 +619 618 1630 258 0 +618 1619 109 1630 0 +262 623 621 622 0 +623 263 1643 621 0 +622 621 1654 261 0 +621 1643 110 1654 0 +265 626 624 625 0 +626 266 1668 624 0 +625 624 1680 264 0 +624 1668 111 1680 0 +268 629 627 628 0 +629 269 1695 627 0 +628 627 1704 267 0 +627 1695 61 1704 0 +271 632 630 631 0 +632 272 1715 630 0 +631 630 1726 270 0 +630 1715 113 1726 0 +274 635 633 634 0 +635 275 1739 633 0 +634 633 1750 273 0 +633 1739 114 1750 0 +277 638 636 637 0 +638 278 1764 636 0 +637 636 1776 276 0 +636 1764 115 1776 0 +280 641 639 640 0 +641 281 1791 639 0 +640 639 1800 279 0 +639 1791 64 1800 0 +283 644 642 643 0 +644 284 1811 642 0 +643 642 1822 282 0 +642 1811 117 1822 0 +286 647 645 646 0 +647 287 1835 645 0 +646 645 1846 285 0 +645 1835 118 1846 0 +289 650 648 649 0 +650 290 1860 648 0 +649 648 1872 288 0 +648 1860 119 1872 0 +292 653 651 652 0 +653 293 1887 651 0 +652 651 1898 291 0 +651 1887 66 1898 0 +295 656 654 655 0 +656 296 1911 654 0 +655 654 1922 294 0 +654 1911 120 1922 0 +298 659 657 658 0 +659 299 1935 657 0 +658 657 1946 297 0 +657 1935 121 1946 0 +301 662 660 661 0 +662 302 1960 660 0 +661 660 1972 300 0 +660 1960 122 1972 0 +125 667 663 664 0 +667 304 864 663 0 +664 663 936 303 0 +663 864 21 936 0 +123 672 669 670 0 +672 306 956 669 0 +670 669 773 305 0 +669 956 5 773 0 +124 677 674 675 0 +677 308 766 674 0 +675 674 872 307 0 +674 766 1 872 0 +128 683 679 680 0 +683 310 964 679 0 +680 679 1036 309 0 +679 964 22 1036 0 +126 688 685 686 0 +688 312 1056 685 0 +686 685 857 311 0 +685 1056 6 857 0 +127 693 690 691 0 +693 314 850 690 0 +691 690 972 313 0 +690 850 10 972 0 +131 699 695 696 0 +699 316 1064 695 0 +696 695 1124 315 0 +695 1064 23 1124 0 +129 704 701 702 0 +704 318 1141 701 0 +702 701 881 317 0 +701 1141 2 881 0 +130 709 706 707 0 +709 320 873 706 0 +707 706 1072 319 0 +706 873 1 1072 0 +134 715 711 712 0 +715 322 1148 711 0 +712 711 1212 321 0 +711 1148 24 1212 0 +132 720 717 718 0 +720 324 1229 717 0 +718 717 905 323 0 +717 1229 3 905 0 +133 725 722 723 0 +725 326 897 722 0 +723 722 1156 325 0 +722 897 2 1156 0 +137 731 727 728 0 +731 328 1236 727 0 +728 727 1300 327 0 +727 1236 25 1300 0 +135 736 733 734 0 +736 330 1317 733 0 +734 733 929 329 0 +733 1317 4 929 0 +136 741 738 739 0 +741 332 921 738 0 +739 738 1244 331 0 +738 921 3 1244 0 +140 747 743 744 0 +747 334 1324 743 0 +744 743 1388 333 0 +743 1324 26 1388 0 +138 752 749 750 0 +752 336 1405 749 0 +750 749 955 335 0 +749 1405 5 955 0 +139 757 754 755 0 +757 338 947 754 0 +755 754 1332 337 0 +754 947 4 1332 0 +143 763 759 760 0 +763 340 1412 759 0 +760 759 1476 339 0 +759 1412 27 1476 0 +141 770 765 767 0 +770 341 1496 765 0 +767 765 766 308 0 +765 1496 1 766 0 +142 776 772 774 0 +776 305 773 772 0 +774 772 1420 342 0 +772 773 5 1420 0 +146 783 779 780 0 +783 344 1504 779 0 +780 779 1572 343 0 +779 1504 28 1572 0 +144 788 785 786 0 +788 346 1589 785 0 +786 785 1055 345 0 +785 1589 6 1055 0 +145 793 790 791 0 +793 348 1047 790 0 +791 790 1512 347 0 +790 1047 7 1512 0 +149 799 795 796 0 +799 350 1596 795 0 +796 795 1664 349 0 +795 1596 29 1664 0 +147 804 801 802 0 +804 352 1684 801 0 +802 801 1029 351 0 +801 1684 7 1029 0 +148 809 806 807 0 +809 354 1021 806 0 +807 806 1604 353 0 +806 1021 8 1604 0 +152 815 811 812 0 +815 356 1692 811 0 +812 811 1760 355 0 +811 1692 30 1760 0 +150 820 817 818 0 +820 358 1780 817 0 +818 817 1005 357 0 +817 1780 8 1005 0 +151 825 822 823 0 +825 360 997 822 0 +823 822 1700 359 0 +822 997 9 1700 0 +155 831 827 828 0 +831 362 1788 827 0 +828 827 1856 361 0 +827 1788 31 1856 0 +153 836 833 834 0 +836 364 1876 833 0 +834 833 981 363 0 +833 1876 9 981 0 +154 841 838 839 0 +841 366 973 838 0 +839 838 1796 365 0 +838 973 10 1796 0 +158 847 843 844 0 +847 368 1884 843 0 +844 843 1956 367 0 +843 1884 32 1956 0 +156 854 849 851 0 +854 369 1976 849 0 +851 849 850 314 0 +849 1976 10 850 0 +157 860 856 858 0 +860 311 857 856 0 +858 856 1892 370 0 +856 857 6 1892 0 +161 869 863 865 0 +869 371 888 863 0 +865 863 864 304 0 +863 888 21 864 0 +159 877 871 874 0 +877 307 872 871 0 +874 871 873 320 0 +871 872 1 873 0 +160 884 880 882 0 +884 317 881 880 0 +882 880 896 372 0 +880 881 2 896 0 +164 893 887 889 0 +893 373 912 887 0 +889 887 888 371 0 +887 912 21 888 0 +162 901 895 898 0 +901 372 896 895 0 +898 895 897 326 0 +895 896 2 897 0 +163 908 904 906 0 +908 323 905 904 0 +906 904 920 374 0 +904 905 3 920 0 +167 917 911 913 0 +917 375 937 911 0 +913 911 912 373 0 +911 937 21 912 0 +165 925 919 922 0 +925 374 920 919 0 +922 919 921 332 0 +919 920 3 921 0 +166 932 928 930 0 +932 329 929 928 0 +930 928 946 376 0 +928 929 4 946 0 +170 942 935 938 0 +942 303 936 935 0 +938 935 937 375 0 +935 936 21 937 0 +168 951 945 948 0 +951 376 946 945 0 +948 945 947 338 0 +945 946 4 947 0 +169 960 954 957 0 +960 335 955 954 0 +957 954 956 306 0 +954 955 5 956 0 +173 969 963 965 0 +969 377 988 963 0 +965 963 964 310 0 +963 988 22 964 0 +171 977 971 974 0 +977 313 972 971 0 +974 971 973 366 0 +971 972 10 973 0 +172 984 980 982 0 +984 363 981 980 0 +982 980 996 378 0 +980 981 9 996 0 +176 993 987 989 0 +993 379 1012 987 0 +989 987 988 377 0 +987 1012 22 988 0 +174 1001 995 998 0 +1001 378 996 995 0 +998 995 997 360 0 +995 996 9 997 0 +175 1008 1004 1006 0 +1008 357 1005 1004 0 +1006 1004 1020 380 0 +1004 1005 8 1020 0 +179 1017 1011 1013 0 +1017 381 1037 1011 0 +1013 1011 1012 379 0 +1011 1037 22 1012 0 +177 1025 1019 1022 0 +1025 380 1020 1019 0 +1022 1019 1021 354 0 +1019 1020 8 1021 0 +178 1032 1028 1030 0 +1032 351 1029 1028 0 +1030 1028 1046 382 0 +1028 1029 7 1046 0 +182 1042 1035 1038 0 +1042 309 1036 1035 0 +1038 1035 1037 381 0 +1035 1036 22 1037 0 +180 1051 1045 1048 0 +1051 382 1046 1045 0 +1048 1045 1047 348 0 +1045 1046 7 1047 0 +181 1060 1054 1057 0 +1060 345 1055 1054 0 +1057 1054 1056 312 0 +1054 1055 6 1056 0 +185 1069 1063 1065 0 +1069 383 1084 1063 0 +1065 1063 1064 316 0 +1063 1084 23 1064 0 +183 1075 1071 1073 0 +1075 319 1072 1071 0 +1073 1071 1495 384 0 +1071 1072 1 1495 0 +184 1081 1078 1079 0 +1081 386 1487 1078 0 +1079 1078 1092 385 0 +1078 1487 11 1092 0 +188 1089 1083 1085 0 +1089 387 1104 1083 0 +1085 1083 1084 383 0 +1083 1104 23 1084 0 +186 1095 1091 1093 0 +1095 385 1092 1091 0 +1093 1091 1925 388 0 +1091 1092 11 1925 0 +187 1101 1098 1099 0 +1101 390 1917 1098 0 +1099 1098 1112 389 0 +1098 1917 12 1112 0 +191 1109 1103 1105 0 +1109 391 1125 1103 0 +1105 1103 1104 387 0 +1103 1125 23 1104 0 +189 1115 1111 1113 0 +1115 389 1112 1111 0 +1113 1111 1565 392 0 +1111 1112 12 1565 0 +190 1121 1118 1119 0 +1121 394 1557 1118 0 +1119 1118 1134 393 0 +1118 1557 13 1134 0 +194 1130 1123 1126 0 +1130 315 1124 1123 0 +1126 1123 1125 391 0 +1123 1124 23 1125 0 +192 1137 1133 1135 0 +1137 393 1134 1133 0 +1135 1133 1165 395 0 +1133 1134 13 1165 0 +193 1145 1140 1142 0 +1145 396 1157 1140 0 +1142 1140 1141 318 0 +1140 1157 2 1141 0 +197 1153 1147 1149 0 +1153 397 1172 1147 0 +1149 1147 1148 322 0 +1147 1172 24 1148 0 +195 1161 1155 1158 0 +1161 325 1156 1155 0 +1158 1155 1157 396 0 +1155 1156 2 1157 0 +196 1168 1164 1166 0 +1168 395 1165 1164 0 +1166 1164 1180 398 0 +1164 1165 13 1180 0 +200 1177 1171 1173 0 +1177 399 1192 1171 0 +1173 1171 1172 397 0 +1171 1192 24 1172 0 +198 1183 1179 1181 0 +1183 398 1180 1179 0 +1181 1179 1541 400 0 +1179 1180 13 1541 0 +199 1189 1186 1187 0 +1189 402 1533 1186 0 +1187 1186 1200 401 0 +1186 1533 14 1200 0 +203 1197 1191 1193 0 +1197 403 1213 1191 0 +1193 1191 1192 399 0 +1191 1213 24 1192 0 +201 1203 1199 1201 0 +1203 401 1200 1199 0 +1201 1199 1657 404 0 +1199 1200 14 1657 0 +202 1209 1206 1207 0 +1209 406 1649 1206 0 +1207 1206 1222 405 0 +1206 1649 15 1222 0 +206 1218 1211 1214 0 +1218 321 1212 1211 0 +1214 1211 1213 403 0 +1211 1212 24 1213 0 +204 1225 1221 1223 0 +1225 405 1222 1221 0 +1223 1221 1253 407 0 +1221 1222 15 1253 0 +205 1233 1228 1230 0 +1233 408 1245 1228 0 +1230 1228 1229 324 0 +1228 1245 3 1229 0 +209 1241 1235 1237 0 +1241 409 1260 1235 0 +1237 1235 1236 328 0 +1235 1260 25 1236 0 +207 1249 1243 1246 0 +1249 331 1244 1243 0 +1246 1243 1245 408 0 +1243 1244 3 1245 0 +208 1256 1252 1254 0 +1256 407 1253 1252 0 +1254 1252 1268 410 0 +1252 1253 15 1268 0 +212 1265 1259 1261 0 +1265 411 1280 1259 0 +1261 1259 1260 409 0 +1259 1280 25 1260 0 +210 1271 1267 1269 0 +1271 410 1268 1267 0 +1269 1267 1633 412 0 +1267 1268 15 1633 0 +211 1277 1274 1275 0 +1277 414 1625 1274 0 +1275 1274 1288 413 0 +1274 1625 16 1288 0 +215 1285 1279 1281 0 +1285 415 1301 1279 0 +1281 1279 1280 411 0 +1279 1301 25 1280 0 +213 1291 1287 1289 0 +1291 413 1288 1287 0 +1289 1287 1753 416 0 +1287 1288 16 1753 0 +214 1297 1294 1295 0 +1297 418 1745 1294 0 +1295 1294 1310 417 0 +1294 1745 17 1310 0 +218 1306 1299 1302 0 +1306 327 1300 1299 0 +1302 1299 1301 415 0 +1299 1300 25 1301 0 +216 1313 1309 1311 0 +1313 417 1310 1309 0 +1311 1309 1341 419 0 +1309 1310 17 1341 0 +217 1321 1316 1318 0 +1321 420 1333 1316 0 +1318 1316 1317 330 0 +1316 1333 4 1317 0 +221 1329 1323 1325 0 +1329 421 1348 1323 0 +1325 1323 1324 334 0 +1323 1348 26 1324 0 +219 1337 1331 1334 0 +1337 337 1332 1331 0 +1334 1331 1333 420 0 +1331 1332 4 1333 0 +220 1344 1340 1342 0 +1344 419 1341 1340 0 +1342 1340 1356 422 0 +1340 1341 17 1356 0 +224 1353 1347 1349 0 +1353 423 1368 1347 0 +1349 1347 1348 421 0 +1347 1368 26 1348 0 +222 1359 1355 1357 0 +1359 422 1356 1355 0 +1357 1355 1729 424 0 +1355 1356 17 1729 0 +223 1365 1362 1363 0 +1365 426 1721 1362 0 +1363 1362 1376 425 0 +1362 1721 18 1376 0 +227 1373 1367 1369 0 +1373 427 1389 1367 0 +1369 1367 1368 423 0 +1367 1389 26 1368 0 +225 1379 1375 1377 0 +1379 425 1376 1375 0 +1377 1375 1849 428 0 +1375 1376 18 1849 0 +226 1385 1382 1383 0 +1385 430 1841 1382 0 +1383 1382 1398 429 0 +1382 1841 19 1398 0 +230 1394 1387 1390 0 +1394 333 1388 1387 0 +1390 1387 1389 427 0 +1387 1388 26 1389 0 +228 1401 1397 1399 0 +1401 429 1398 1397 0 +1399 1397 1429 431 0 +1397 1398 19 1429 0 +229 1409 1404 1406 0 +1409 432 1421 1404 0 +1406 1404 1405 336 0 +1404 1421 5 1405 0 +233 1417 1411 1413 0 +1417 433 1436 1411 0 +1413 1411 1412 340 0 +1411 1436 27 1412 0 +231 1425 1419 1422 0 +1425 342 1420 1419 0 +1422 1419 1421 432 0 +1419 1420 5 1421 0 +232 1432 1428 1430 0 +1432 431 1429 1428 0 +1430 1428 1444 434 0 +1428 1429 19 1444 0 +236 1441 1435 1437 0 +1441 435 1456 1435 0 +1437 1435 1436 433 0 +1435 1456 27 1436 0 +234 1447 1443 1445 0 +1447 434 1444 1443 0 +1445 1443 1825 436 0 +1443 1444 19 1825 0 +235 1453 1450 1451 0 +1453 438 1817 1450 0 +1451 1450 1464 437 0 +1450 1817 20 1464 0 +239 1461 1455 1457 0 +1461 439 1477 1455 0 +1457 1455 1456 435 0 +1455 1477 27 1456 0 +237 1467 1463 1465 0 +1467 437 1464 1463 0 +1465 1463 1949 440 0 +1463 1464 20 1949 0 +238 1473 1470 1471 0 +1473 442 1941 1470 0 +1471 1470 1486 441 0 +1470 1941 11 1486 0 +242 1482 1475 1478 0 +1482 339 1476 1475 0 +1478 1475 1477 439 0 +1475 1476 27 1477 0 +240 1491 1485 1488 0 +1491 441 1486 1485 0 +1488 1485 1487 386 0 +1485 1486 11 1487 0 +241 1500 1494 1497 0 +1500 384 1495 1494 0 +1497 1494 1496 341 0 +1494 1495 1 1496 0 +245 1509 1503 1505 0 +1509 443 1524 1503 0 +1505 1503 1504 344 0 +1503 1524 28 1504 0 +243 1515 1511 1513 0 +1515 347 1512 1511 0 +1513 1511 1683 444 0 +1511 1512 7 1683 0 +244 1521 1518 1519 0 +1521 446 1675 1518 0 +1519 1518 1532 445 0 +1518 1675 14 1532 0 +248 1529 1523 1525 0 +1529 447 1548 1523 0 +1525 1523 1524 443 0 +1523 1548 28 1524 0 +246 1537 1531 1534 0 +1537 445 1532 1531 0 +1534 1531 1533 402 0 +1531 1532 14 1533 0 +247 1544 1540 1542 0 +1544 400 1541 1540 0 +1542 1540 1556 448 0 +1540 1541 13 1556 0 +251 1553 1547 1549 0 +1553 449 1573 1547 0 +1549 1547 1548 447 0 +1547 1573 28 1548 0 +249 1561 1555 1558 0 +1561 448 1556 1555 0 +1558 1555 1557 394 0 +1555 1556 13 1557 0 +250 1568 1564 1566 0 +1568 392 1565 1564 0 +1566 1564 1582 450 0 +1564 1565 12 1582 0 +254 1578 1571 1574 0 +1578 343 1572 1571 0 +1574 1571 1573 449 0 +1571 1572 28 1573 0 +252 1585 1581 1583 0 +1585 450 1582 1581 0 +1583 1581 1901 451 0 +1581 1582 12 1901 0 +253 1593 1588 1590 0 +1593 452 1893 1588 0 +1590 1588 1589 346 0 +1588 1893 6 1589 0 +257 1601 1595 1597 0 +1601 453 1616 1595 0 +1597 1595 1596 350 0 +1595 1616 29 1596 0 +255 1607 1603 1605 0 +1607 353 1604 1603 0 +1605 1603 1779 454 0 +1603 1604 8 1779 0 +256 1613 1610 1611 0 +1613 456 1771 1610 0 +1611 1610 1624 455 0 +1610 1771 16 1624 0 +260 1621 1615 1617 0 +1621 457 1640 1615 0 +1617 1615 1616 453 0 +1615 1640 29 1616 0 +258 1629 1623 1626 0 +1629 455 1624 1623 0 +1626 1623 1625 414 0 +1623 1624 16 1625 0 +259 1636 1632 1634 0 +1636 412 1633 1632 0 +1634 1632 1648 458 0 +1632 1633 15 1648 0 +263 1645 1639 1641 0 +1645 459 1665 1639 0 +1641 1639 1640 457 0 +1639 1665 29 1640 0 +261 1653 1647 1650 0 +1653 458 1648 1647 0 +1650 1647 1649 406 0 +1647 1648 15 1649 0 +262 1660 1656 1658 0 +1660 404 1657 1656 0 +1658 1656 1674 460 0 +1656 1657 14 1674 0 +266 1670 1663 1666 0 +1670 349 1664 1663 0 +1666 1663 1665 459 0 +1663 1664 29 1665 0 +264 1679 1673 1676 0 +1679 460 1674 1673 0 +1676 1673 1675 446 0 +1673 1674 14 1675 0 +265 1688 1682 1685 0 +1688 444 1683 1682 0 +1685 1682 1684 352 0 +1682 1683 7 1684 0 +269 1697 1691 1693 0 +1697 461 1712 1691 0 +1693 1691 1692 356 0 +1691 1712 30 1692 0 +267 1703 1699 1701 0 +1703 359 1700 1699 0 +1701 1699 1875 462 0 +1699 1700 9 1875 0 +268 1709 1706 1707 0 +1709 464 1867 1706 0 +1707 1706 1720 463 0 +1706 1867 18 1720 0 +272 1717 1711 1713 0 +1717 465 1736 1711 0 +1713 1711 1712 461 0 +1711 1736 30 1712 0 +270 1725 1719 1722 0 +1725 463 1720 1719 0 +1722 1719 1721 426 0 +1719 1720 18 1721 0 +271 1732 1728 1730 0 +1732 424 1729 1728 0 +1730 1728 1744 466 0 +1728 1729 17 1744 0 +275 1741 1735 1737 0 +1741 467 1761 1735 0 +1737 1735 1736 465 0 +1735 1761 30 1736 0 +273 1749 1743 1746 0 +1749 466 1744 1743 0 +1746 1743 1745 418 0 +1743 1744 17 1745 0 +274 1756 1752 1754 0 +1756 416 1753 1752 0 +1754 1752 1770 468 0 +1752 1753 16 1770 0 +278 1766 1759 1762 0 +1766 355 1760 1759 0 +1762 1759 1761 467 0 +1759 1760 30 1761 0 +276 1775 1769 1772 0 +1775 468 1770 1769 0 +1772 1769 1771 456 0 +1769 1770 16 1771 0 +277 1784 1778 1781 0 +1784 454 1779 1778 0 +1781 1778 1780 358 0 +1778 1779 8 1780 0 +281 1793 1787 1789 0 +1793 469 1808 1787 0 +1789 1787 1788 362 0 +1787 1808 31 1788 0 +279 1799 1795 1797 0 +1799 365 1796 1795 0 +1797 1795 1975 470 0 +1795 1796 10 1975 0 +280 1805 1802 1803 0 +1805 472 1967 1802 0 +1803 1802 1816 471 0 +1802 1967 20 1816 0 +284 1813 1807 1809 0 +1813 473 1832 1807 0 +1809 1807 1808 469 0 +1807 1832 31 1808 0 +282 1821 1815 1818 0 +1821 471 1816 1815 0 +1818 1815 1817 438 0 +1815 1816 20 1817 0 +283 1828 1824 1826 0 +1828 436 1825 1824 0 +1826 1824 1840 474 0 +1824 1825 19 1840 0 +287 1837 1831 1833 0 +1837 475 1857 1831 0 +1833 1831 1832 473 0 +1831 1857 31 1832 0 +285 1845 1839 1842 0 +1845 474 1840 1839 0 +1842 1839 1841 430 0 +1839 1840 19 1841 0 +286 1852 1848 1850 0 +1852 428 1849 1848 0 +1850 1848 1866 476 0 +1848 1849 18 1866 0 +290 1862 1855 1858 0 +1862 361 1856 1855 0 +1858 1855 1857 475 0 +1855 1856 31 1857 0 +288 1871 1865 1868 0 +1871 476 1866 1865 0 +1868 1865 1867 464 0 +1865 1866 18 1867 0 +289 1880 1874 1877 0 +1880 462 1875 1874 0 +1877 1874 1876 364 0 +1874 1875 9 1876 0 +293 1889 1883 1885 0 +1889 477 1908 1883 0 +1885 1883 1884 368 0 +1883 1908 32 1884 0 +291 1897 1891 1894 0 +1897 370 1892 1891 0 +1894 1891 1893 452 0 +1891 1892 6 1893 0 +292 1904 1900 1902 0 +1904 451 1901 1900 0 +1902 1900 1916 478 0 +1900 1901 12 1916 0 +296 1913 1907 1909 0 +1913 479 1932 1907 0 +1909 1907 1908 477 0 +1907 1932 32 1908 0 +294 1921 1915 1918 0 +1921 478 1916 1915 0 +1918 1915 1917 390 0 +1915 1916 12 1917 0 +295 1928 1924 1926 0 +1928 388 1925 1924 0 +1926 1924 1940 480 0 +1924 1925 11 1940 0 +299 1937 1931 1933 0 +1937 481 1957 1931 0 +1933 1931 1932 479 0 +1931 1957 32 1932 0 +297 1945 1939 1942 0 +1945 480 1940 1939 0 +1942 1939 1941 442 0 +1939 1940 11 1941 0 +298 1952 1948 1950 0 +1952 440 1949 1948 0 +1950 1948 1966 482 0 +1948 1949 20 1966 0 +302 1962 1955 1958 0 +1962 367 1956 1955 0 +1958 1955 1957 481 0 +1955 1956 32 1957 0 +300 1971 1965 1968 0 +1971 482 1966 1965 0 +1968 1965 1967 472 0 +1965 1966 20 1967 0 +301 1980 1974 1977 0 +1980 470 1975 1974 0 +1977 1974 1976 369 0 +1974 1975 10 1976 0 +124 484 671 678 0 +484 123 670 671 0 +678 671 778 34 0 +671 670 305 778 0 +124 676 668 485 0 +676 35 866 668 0 +485 668 667 125 0 +668 866 304 667 0 +127 487 687 694 0 +487 126 686 687 0 +694 687 862 37 0 +687 686 311 862 0 +127 692 684 488 0 +692 38 966 684 0 +488 684 683 128 0 +684 966 310 683 0 +130 490 703 710 0 +490 129 702 703 0 +710 703 886 40 0 +703 702 317 886 0 +130 708 700 491 0 +708 41 1066 700 0 +491 700 699 131 0 +700 1066 316 699 0 +133 493 719 726 0 +493 132 718 719 0 +726 719 910 43 0 +719 718 323 910 0 +133 724 716 494 0 +724 44 1150 716 0 +494 716 715 134 0 +716 1150 322 715 0 +136 496 735 742 0 +496 135 734 735 0 +742 735 934 46 0 +735 734 329 934 0 +136 740 732 497 0 +740 47 1238 732 0 +497 732 731 137 0 +732 1238 328 731 0 +139 499 751 758 0 +499 138 750 751 0 +758 751 962 49 0 +751 750 335 962 0 +139 756 748 500 0 +756 50 1326 748 0 +500 748 747 140 0 +748 1326 334 747 0 +141 769 777 502 0 +769 34 778 777 0 +502 777 776 142 0 +777 778 305 776 0 +142 775 764 503 0 +775 52 1414 764 0 +503 764 763 143 0 +764 1414 340 763 0 +145 505 787 794 0 +505 144 786 787 0 +794 787 1062 54 0 +787 786 345 1062 0 +145 792 784 506 0 +792 55 1506 784 0 +506 784 783 146 0 +784 1506 344 783 0 +148 508 803 810 0 +508 147 802 803 0 +810 803 1034 57 0 +803 802 351 1034 0 +148 808 800 509 0 +808 58 1598 800 0 +509 800 799 149 0 +800 1598 350 799 0 +151 511 819 826 0 +511 150 818 819 0 +826 819 1010 60 0 +819 818 357 1010 0 +151 824 816 512 0 +824 61 1694 816 0 +512 816 815 152 0 +816 1694 356 815 0 +154 514 835 842 0 +514 153 834 835 0 +842 835 986 63 0 +835 834 363 986 0 +154 840 832 515 0 +840 64 1790 832 0 +515 832 831 155 0 +832 1790 362 831 0 +156 853 861 517 0 +853 37 862 861 0 +517 861 860 157 0 +861 862 311 860 0 +157 859 848 518 0 +859 66 1886 848 0 +518 848 847 158 0 +848 1886 368 847 0 +159 876 885 520 0 +876 40 886 885 0 +520 885 884 160 0 +885 886 317 884 0 +160 883 870 521 0 +883 67 890 870 0 +521 870 869 161 0 +870 890 371 869 0 +162 900 909 523 0 +900 43 910 909 0 +523 909 908 163 0 +909 910 323 908 0 +163 907 894 524 0 +907 68 914 894 0 +524 894 893 164 0 +894 914 373 893 0 +165 924 933 526 0 +924 46 934 933 0 +526 933 932 166 0 +933 934 329 932 0 +166 931 918 527 0 +931 69 939 918 0 +527 918 917 167 0 +918 939 375 917 0 +168 950 961 529 0 +950 49 962 961 0 +529 961 960 169 0 +961 962 335 960 0 +169 959 943 530 0 +959 33 944 943 0 +530 943 942 170 0 +943 944 303 942 0 +171 976 985 532 0 +976 63 986 985 0 +532 985 984 172 0 +985 986 363 984 0 +172 983 970 533 0 +983 70 990 970 0 +533 970 969 173 0 +970 990 377 969 0 +174 1000 1009 535 0 +1000 60 1010 1009 0 +535 1009 1008 175 0 +1009 1010 357 1008 0 +175 1007 994 536 0 +1007 71 1014 994 0 +536 994 993 176 0 +994 1014 379 993 0 +177 1024 1033 538 0 +1024 57 1034 1033 0 +538 1033 1032 178 0 +1033 1034 351 1032 0 +178 1031 1018 539 0 +1031 72 1039 1018 0 +539 1018 1017 179 0 +1018 1039 381 1017 0 +180 1050 1061 541 0 +1050 54 1062 1061 0 +541 1061 1060 181 0 +1061 1062 345 1060 0 +181 1059 1043 542 0 +1059 36 1044 1043 0 +542 1043 1042 182 0 +1043 1044 309 1042 0 +184 544 1074 1082 0 +544 183 1073 1074 0 +1082 1074 1502 73 0 +1074 1073 384 1502 0 +184 1080 1070 545 0 +1080 74 1086 1070 0 +545 1070 1069 185 0 +1070 1086 383 1069 0 +187 547 1094 1102 0 +547 186 1093 1094 0 +1102 1094 1930 75 0 +1094 1093 388 1930 0 +187 1100 1090 548 0 +1100 76 1106 1090 0 +548 1090 1089 188 0 +1090 1106 387 1089 0 +190 550 1114 1122 0 +550 189 1113 1114 0 +1122 1114 1570 77 0 +1114 1113 392 1570 0 +190 1120 1110 551 0 +1120 78 1127 1110 0 +551 1110 1109 191 0 +1110 1127 391 1109 0 +193 553 1136 1146 0 +553 192 1135 1136 0 +1146 1136 1170 79 0 +1136 1135 395 1170 0 +193 1144 1131 554 0 +1144 39 1132 1131 0 +554 1131 1130 194 0 +1131 1132 315 1130 0 +195 1160 1169 556 0 +1160 79 1170 1169 0 +556 1169 1168 196 0 +1169 1170 395 1168 0 +196 1167 1154 557 0 +1167 80 1174 1154 0 +557 1154 1153 197 0 +1154 1174 397 1153 0 +199 559 1182 1190 0 +559 198 1181 1182 0 +1190 1182 1546 81 0 +1182 1181 400 1546 0 +199 1188 1178 560 0 +1188 82 1194 1178 0 +560 1178 1177 200 0 +1178 1194 399 1177 0 +202 562 1202 1210 0 +562 201 1201 1202 0 +1210 1202 1662 83 0 +1202 1201 404 1662 0 +202 1208 1198 563 0 +1208 84 1215 1198 0 +563 1198 1197 203 0 +1198 1215 403 1197 0 +205 565 1224 1234 0 +565 204 1223 1224 0 +1234 1224 1258 85 0 +1224 1223 407 1258 0 +205 1232 1219 566 0 +1232 42 1220 1219 0 +566 1219 1218 206 0 +1219 1220 321 1218 0 +207 1248 1257 568 0 +1248 85 1258 1257 0 +568 1257 1256 208 0 +1257 1258 407 1256 0 +208 1255 1242 569 0 +1255 86 1262 1242 0 +569 1242 1241 209 0 +1242 1262 409 1241 0 +211 571 1270 1278 0 +571 210 1269 1270 0 +1278 1270 1638 87 0 +1270 1269 412 1638 0 +211 1276 1266 572 0 +1276 88 1282 1266 0 +572 1266 1265 212 0 +1266 1282 411 1265 0 +214 574 1290 1298 0 +574 213 1289 1290 0 +1298 1290 1758 89 0 +1290 1289 416 1758 0 +214 1296 1286 575 0 +1296 90 1303 1286 0 +575 1286 1285 215 0 +1286 1303 415 1285 0 +217 577 1312 1322 0 +577 216 1311 1312 0 +1322 1312 1346 91 0 +1312 1311 419 1346 0 +217 1320 1307 578 0 +1320 45 1308 1307 0 +578 1307 1306 218 0 +1307 1308 327 1306 0 +219 1336 1345 580 0 +1336 91 1346 1345 0 +580 1345 1344 220 0 +1345 1346 419 1344 0 +220 1343 1330 581 0 +1343 92 1350 1330 0 +581 1330 1329 221 0 +1330 1350 421 1329 0 +223 583 1358 1366 0 +583 222 1357 1358 0 +1366 1358 1734 93 0 +1358 1357 424 1734 0 +223 1364 1354 584 0 +1364 94 1370 1354 0 +584 1354 1353 224 0 +1354 1370 423 1353 0 +226 586 1378 1386 0 +586 225 1377 1378 0 +1386 1378 1854 95 0 +1378 1377 428 1854 0 +226 1384 1374 587 0 +1384 96 1391 1374 0 +587 1374 1373 227 0 +1374 1391 427 1373 0 +229 589 1400 1410 0 +589 228 1399 1400 0 +1410 1400 1434 97 0 +1400 1399 431 1434 0 +229 1408 1395 590 0 +1408 48 1396 1395 0 +590 1395 1394 230 0 +1395 1396 333 1394 0 +231 1424 1433 592 0 +1424 97 1434 1433 0 +592 1433 1432 232 0 +1433 1434 431 1432 0 +232 1431 1418 593 0 +1431 98 1438 1418 0 +593 1418 1417 233 0 +1418 1438 433 1417 0 +235 595 1446 1454 0 +595 234 1445 1446 0 +1454 1446 1830 99 0 +1446 1445 436 1830 0 +235 1452 1442 596 0 +1452 100 1458 1442 0 +596 1442 1441 236 0 +1442 1458 435 1441 0 +238 598 1466 1474 0 +598 237 1465 1466 0 +1474 1466 1954 101 0 +1466 1465 440 1954 0 +238 1472 1462 599 0 +1472 102 1479 1462 0 +599 1462 1461 239 0 +1462 1479 439 1461 0 +240 1490 1501 601 0 +1490 73 1502 1501 0 +601 1501 1500 241 0 +1501 1502 384 1500 0 +241 1499 1483 602 0 +1499 51 1484 1483 0 +602 1483 1482 242 0 +1483 1484 339 1482 0 +244 604 1514 1522 0 +604 243 1513 1514 0 +1522 1514 1690 103 0 +1514 1513 444 1690 0 +244 1520 1510 605 0 +1520 104 1526 1510 0 +605 1510 1509 245 0 +1510 1526 443 1509 0 +246 1536 1545 607 0 +1536 81 1546 1545 0 +607 1545 1544 247 0 +1545 1546 400 1544 0 +247 1543 1530 608 0 +1543 105 1550 1530 0 +608 1530 1529 248 0 +1530 1550 447 1529 0 +249 1560 1569 610 0 +1560 77 1570 1569 0 +610 1569 1568 250 0 +1569 1570 392 1568 0 +250 1567 1554 611 0 +1567 106 1575 1554 0 +611 1554 1553 251 0 +1554 1575 449 1553 0 +253 613 1584 1594 0 +613 252 1583 1584 0 +1594 1584 1906 107 0 +1584 1583 451 1906 0 +253 1592 1579 614 0 +1592 53 1580 1579 0 +614 1579 1578 254 0 +1579 1580 343 1578 0 +256 616 1606 1614 0 +616 255 1605 1606 0 +1614 1606 1786 108 0 +1606 1605 454 1786 0 +256 1612 1602 617 0 +1612 109 1618 1602 0 +617 1602 1601 257 0 +1602 1618 453 1601 0 +258 1628 1637 619 0 +1628 87 1638 1637 0 +619 1637 1636 259 0 +1637 1638 412 1636 0 +259 1635 1622 620 0 +1635 110 1642 1622 0 +620 1622 1621 260 0 +1622 1642 457 1621 0 +261 1652 1661 622 0 +1652 83 1662 1661 0 +622 1661 1660 262 0 +1661 1662 404 1660 0 +262 1659 1646 623 0 +1659 111 1667 1646 0 +623 1646 1645 263 0 +1646 1667 459 1645 0 +264 1678 1689 625 0 +1678 103 1690 1689 0 +625 1689 1688 265 0 +1689 1690 444 1688 0 +265 1687 1671 626 0 +1687 56 1672 1671 0 +626 1671 1670 266 0 +1671 1672 349 1670 0 +268 628 1702 1710 0 +628 267 1701 1702 0 +1710 1702 1882 112 0 +1702 1701 462 1882 0 +268 1708 1698 629 0 +1708 113 1714 1698 0 +629 1698 1697 269 0 +1698 1714 461 1697 0 +270 1724 1733 631 0 +1724 93 1734 1733 0 +631 1733 1732 271 0 +1733 1734 424 1732 0 +271 1731 1718 632 0 +1731 114 1738 1718 0 +632 1718 1717 272 0 +1718 1738 465 1717 0 +273 1748 1757 634 0 +1748 89 1758 1757 0 +634 1757 1756 274 0 +1757 1758 416 1756 0 +274 1755 1742 635 0 +1755 115 1763 1742 0 +635 1742 1741 275 0 +1742 1763 467 1741 0 +276 1774 1785 637 0 +1774 108 1786 1785 0 +637 1785 1784 277 0 +1785 1786 454 1784 0 +277 1783 1767 638 0 +1783 59 1768 1767 0 +638 1767 1766 278 0 +1767 1768 355 1766 0 +280 640 1798 1806 0 +640 279 1797 1798 0 +1806 1798 1982 116 0 +1798 1797 470 1982 0 +280 1804 1794 641 0 +1804 117 1810 1794 0 +641 1794 1793 281 0 +1794 1810 469 1793 0 +282 1820 1829 643 0 +1820 99 1830 1829 0 +643 1829 1828 283 0 +1829 1830 436 1828 0 +283 1827 1814 644 0 +1827 118 1834 1814 0 +644 1814 1813 284 0 +1814 1834 473 1813 0 +285 1844 1853 646 0 +1844 95 1854 1853 0 +646 1853 1852 286 0 +1853 1854 428 1852 0 +286 1851 1838 647 0 +1851 119 1859 1838 0 +647 1838 1837 287 0 +1838 1859 475 1837 0 +288 1870 1881 649 0 +1870 112 1882 1881 0 +649 1881 1880 289 0 +1881 1882 462 1880 0 +289 1879 1863 650 0 +1879 62 1864 1863 0 +650 1863 1862 290 0 +1863 1864 361 1862 0 +291 1896 1905 652 0 +1896 107 1906 1905 0 +652 1905 1904 292 0 +1905 1906 451 1904 0 +292 1903 1890 653 0 +1903 120 1910 1890 0 +653 1890 1889 293 0 +1890 1910 477 1889 0 +294 1920 1929 655 0 +1920 75 1930 1929 0 +655 1929 1928 295 0 +1929 1930 388 1928 0 +295 1927 1914 656 0 +1927 121 1934 1914 0 +656 1914 1913 296 0 +1914 1934 479 1913 0 +297 1944 1953 658 0 +1944 101 1954 1953 0 +658 1953 1952 298 0 +1953 1954 440 1952 0 +298 1951 1938 659 0 +1951 122 1959 1938 0 +659 1938 1937 299 0 +1938 1959 481 1937 0 +300 1970 1981 661 0 +1970 116 1982 1981 0 +661 1981 1980 301 0 +1981 1982 470 1980 0 +301 1979 1963 662 0 +1979 65 1964 1963 0 +662 1963 1962 302 0 +1963 1964 367 1962 0 +33 665 666 944 0 +665 125 664 666 0 +944 666 664 303 0 +123 673 958 672 0 +673 33 959 958 0 +672 958 957 306 0 +958 959 169 957 0 +124 675 879 676 0 +675 307 877 879 0 +676 879 878 35 0 +879 877 159 878 0 +124 678 768 677 0 +678 34 769 768 0 +677 768 767 308 0 +768 769 141 767 0 +36 681 682 1044 0 +681 128 680 682 0 +1044 682 680 309 0 +126 689 1058 688 0 +689 36 1059 1058 0 +688 1058 1057 312 0 +1058 1059 181 1057 0 +127 691 979 692 0 +691 313 977 979 0 +692 979 978 38 0 +979 977 171 978 0 +127 694 852 693 0 +694 37 853 852 0 +693 852 851 314 0 +852 853 156 851 0 +39 697 698 1132 0 +697 131 696 698 0 +1132 698 696 315 0 +129 705 1143 704 0 +705 39 1144 1143 0 +704 1143 1142 318 0 +1143 1144 193 1142 0 +130 707 1077 708 0 +707 319 1075 1077 0 +708 1077 1076 41 0 +1077 1075 183 1076 0 +130 710 875 709 0 +710 40 876 875 0 +709 875 874 320 0 +875 876 159 874 0 +42 713 714 1220 0 +713 134 712 714 0 +1220 714 712 321 0 +132 721 1231 720 0 +721 42 1232 1231 0 +720 1231 1230 324 0 +1231 1232 205 1230 0 +133 723 1163 724 0 +723 325 1161 1163 0 +724 1163 1162 44 0 +1163 1161 195 1162 0 +133 726 899 725 0 +726 43 900 899 0 +725 899 898 326 0 +899 900 162 898 0 +45 729 730 1308 0 +729 137 728 730 0 +1308 730 728 327 0 +135 737 1319 736 0 +737 45 1320 1319 0 +736 1319 1318 330 0 +1319 1320 217 1318 0 +136 739 1251 740 0 +739 331 1249 1251 0 +740 1251 1250 47 0 +1251 1249 207 1250 0 +136 742 923 741 0 +742 46 924 923 0 +741 923 922 332 0 +923 924 165 922 0 +48 745 746 1396 0 +745 140 744 746 0 +1396 746 744 333 0 +138 753 1407 752 0 +753 48 1408 1407 0 +752 1407 1406 336 0 +1407 1408 229 1406 0 +139 755 1339 756 0 +755 337 1337 1339 0 +756 1339 1338 50 0 +1339 1337 219 1338 0 +139 758 949 757 0 +758 49 950 949 0 +757 949 948 338 0 +949 950 168 948 0 +51 761 762 1484 0 +761 143 760 762 0 +1484 762 760 339 0 +141 771 1498 770 0 +771 51 1499 1498 0 +770 1498 1497 341 0 +1498 1499 241 1497 0 +142 774 1427 775 0 +774 342 1425 1427 0 +775 1427 1426 52 0 +1427 1425 231 1426 0 +53 781 782 1580 0 +781 146 780 782 0 +1580 782 780 343 0 +144 789 1591 788 0 +789 53 1592 1591 0 +788 1591 1590 346 0 +1591 1592 253 1590 0 +145 791 1517 792 0 +791 347 1515 1517 0 +792 1517 1516 55 0 +1517 1515 243 1516 0 +145 794 1049 793 0 +794 54 1050 1049 0 +793 1049 1048 348 0 +1049 1050 180 1048 0 +56 797 798 1672 0 +797 149 796 798 0 +1672 798 796 349 0 +147 805 1686 804 0 +805 56 1687 1686 0 +804 1686 1685 352 0 +1686 1687 265 1685 0 +148 807 1609 808 0 +807 353 1607 1609 0 +808 1609 1608 58 0 +1609 1607 255 1608 0 +148 810 1023 809 0 +810 57 1024 1023 0 +809 1023 1022 354 0 +1023 1024 177 1022 0 +59 813 814 1768 0 +813 152 812 814 0 +1768 814 812 355 0 +150 821 1782 820 0 +821 59 1783 1782 0 +820 1782 1781 358 0 +1782 1783 277 1781 0 +151 823 1705 824 0 +823 359 1703 1705 0 +824 1705 1704 61 0 +1705 1703 267 1704 0 +151 826 999 825 0 +826 60 1000 999 0 +825 999 998 360 0 +999 1000 174 998 0 +62 829 830 1864 0 +829 155 828 830 0 +1864 830 828 361 0 +153 837 1878 836 0 +837 62 1879 1878 0 +836 1878 1877 364 0 +1878 1879 289 1877 0 +154 839 1801 840 0 +839 365 1799 1801 0 +840 1801 1800 64 0 +1801 1799 279 1800 0 +154 842 975 841 0 +842 63 976 975 0 +841 975 974 366 0 +975 976 171 974 0 +65 845 846 1964 0 +845 158 844 846 0 +1964 846 844 367 0 +156 855 1978 854 0 +855 65 1979 1978 0 +854 1978 1977 369 0 +1978 1979 301 1977 0 +157 858 1899 859 0 +858 370 1897 1899 0 +859 1899 1898 66 0 +1899 1897 291 1898 0 +35 867 868 866 0 +867 161 865 868 0 +866 868 865 304 0 +160 882 903 883 0 +882 372 901 903 0 +883 903 902 67 0 +903 901 162 902 0 +67 891 892 890 0 +891 164 889 892 0 +890 892 889 371 0 +163 906 927 907 0 +906 374 925 927 0 +907 927 926 68 0 +927 925 165 926 0 +68 915 916 914 0 +915 167 913 916 0 +914 916 913 373 0 +166 930 953 931 0 +930 376 951 953 0 +931 953 952 69 0 +953 951 168 952 0 +69 940 941 939 0 +940 170 938 941 0 +939 941 938 375 0 +38 967 968 966 0 +967 173 965 968 0 +966 968 965 310 0 +172 982 1003 983 0 +982 378 1001 1003 0 +983 1003 1002 70 0 +1003 1001 174 1002 0 +70 991 992 990 0 +991 176 989 992 0 +990 992 989 377 0 +175 1006 1027 1007 0 +1006 380 1025 1027 0 +1007 1027 1026 71 0 +1027 1025 177 1026 0 +71 1015 1016 1014 0 +1015 179 1013 1016 0 +1014 1016 1013 379 0 +178 1030 1053 1031 0 +1030 382 1051 1053 0 +1031 1053 1052 72 0 +1053 1051 180 1052 0 +72 1040 1041 1039 0 +1040 182 1038 1041 0 +1039 1041 1038 381 0 +41 1067 1068 1066 0 +1067 185 1065 1068 0 +1066 1068 1065 316 0 +184 1079 1097 1080 0 +1079 385 1095 1097 0 +1080 1097 1096 74 0 +1097 1095 186 1096 0 +184 1082 1489 1081 0 +1082 73 1490 1489 0 +1081 1489 1488 386 0 +1489 1490 240 1488 0 +74 1087 1088 1086 0 +1087 188 1085 1088 0 +1086 1088 1085 383 0 +187 1099 1117 1100 0 +1099 389 1115 1117 0 +1100 1117 1116 76 0 +1117 1115 189 1116 0 +187 1102 1919 1101 0 +1102 75 1920 1919 0 +1101 1919 1918 390 0 +1919 1920 294 1918 0 +76 1107 1108 1106 0 +1107 191 1105 1108 0 +1106 1108 1105 387 0 +190 1119 1139 1120 0 +1119 393 1137 1139 0 +1120 1139 1138 78 0 +1139 1137 192 1138 0 +190 1122 1559 1121 0 +1122 77 1560 1559 0 +1121 1559 1558 394 0 +1559 1560 249 1558 0 +78 1128 1129 1127 0 +1128 194 1126 1129 0 +1127 1129 1126 391 0 +193 1146 1159 1145 0 +1146 79 1160 1159 0 +1145 1159 1158 396 0 +1159 1160 195 1158 0 +44 1151 1152 1150 0 +1151 197 1149 1152 0 +1150 1152 1149 322 0 +196 1166 1185 1167 0 +1166 398 1183 1185 0 +1167 1185 1184 80 0 +1185 1183 198 1184 0 +80 1175 1176 1174 0 +1175 200 1173 1176 0 +1174 1176 1173 397 0 +199 1187 1205 1188 0 +1187 401 1203 1205 0 +1188 1205 1204 82 0 +1205 1203 201 1204 0 +199 1190 1535 1189 0 +1190 81 1536 1535 0 +1189 1535 1534 402 0 +1535 1536 246 1534 0 +82 1195 1196 1194 0 +1195 203 1193 1196 0 +1194 1196 1193 399 0 +202 1207 1227 1208 0 +1207 405 1225 1227 0 +1208 1227 1226 84 0 +1227 1225 204 1226 0 +202 1210 1651 1209 0 +1210 83 1652 1651 0 +1209 1651 1650 406 0 +1651 1652 261 1650 0 +84 1216 1217 1215 0 +1216 206 1214 1217 0 +1215 1217 1214 403 0 +205 1234 1247 1233 0 +1234 85 1248 1247 0 +1233 1247 1246 408 0 +1247 1248 207 1246 0 +47 1239 1240 1238 0 +1239 209 1237 1240 0 +1238 1240 1237 328 0 +208 1254 1273 1255 0 +1254 410 1271 1273 0 +1255 1273 1272 86 0 +1273 1271 210 1272 0 +86 1263 1264 1262 0 +1263 212 1261 1264 0 +1262 1264 1261 409 0 +211 1275 1293 1276 0 +1275 413 1291 1293 0 +1276 1293 1292 88 0 +1293 1291 213 1292 0 +211 1278 1627 1277 0 +1278 87 1628 1627 0 +1277 1627 1626 414 0 +1627 1628 258 1626 0 +88 1283 1284 1282 0 +1283 215 1281 1284 0 +1282 1284 1281 411 0 +214 1295 1315 1296 0 +1295 417 1313 1315 0 +1296 1315 1314 90 0 +1315 1313 216 1314 0 +214 1298 1747 1297 0 +1298 89 1748 1747 0 +1297 1747 1746 418 0 +1747 1748 273 1746 0 +90 1304 1305 1303 0 +1304 218 1302 1305 0 +1303 1305 1302 415 0 +217 1322 1335 1321 0 +1322 91 1336 1335 0 +1321 1335 1334 420 0 +1335 1336 219 1334 0 +50 1327 1328 1326 0 +1327 221 1325 1328 0 +1326 1328 1325 334 0 +220 1342 1361 1343 0 +1342 422 1359 1361 0 +1343 1361 1360 92 0 +1361 1359 222 1360 0 +92 1351 1352 1350 0 +1351 224 1349 1352 0 +1350 1352 1349 421 0 +223 1363 1381 1364 0 +1363 425 1379 1381 0 +1364 1381 1380 94 0 +1381 1379 225 1380 0 +223 1366 1723 1365 0 +1366 93 1724 1723 0 +1365 1723 1722 426 0 +1723 1724 270 1722 0 +94 1371 1372 1370 0 +1371 227 1369 1372 0 +1370 1372 1369 423 0 +226 1383 1403 1384 0 +1383 429 1401 1403 0 +1384 1403 1402 96 0 +1403 1401 228 1402 0 +226 1386 1843 1385 0 +1386 95 1844 1843 0 +1385 1843 1842 430 0 +1843 1844 285 1842 0 +96 1392 1393 1391 0 +1392 230 1390 1393 0 +1391 1393 1390 427 0 +229 1410 1423 1409 0 +1410 97 1424 1423 0 +1409 1423 1422 432 0 +1423 1424 231 1422 0 +52 1415 1416 1414 0 +1415 233 1413 1416 0 +1414 1416 1413 340 0 +232 1430 1449 1431 0 +1430 434 1447 1449 0 +1431 1449 1448 98 0 +1449 1447 234 1448 0 +98 1439 1440 1438 0 +1439 236 1437 1440 0 +1438 1440 1437 433 0 +235 1451 1469 1452 0 +1451 437 1467 1469 0 +1452 1469 1468 100 0 +1469 1467 237 1468 0 +235 1454 1819 1453 0 +1454 99 1820 1819 0 +1453 1819 1818 438 0 +1819 1820 282 1818 0 +100 1459 1460 1458 0 +1459 239 1457 1460 0 +1458 1460 1457 435 0 +238 1471 1493 1472 0 +1471 441 1491 1493 0 +1472 1493 1492 102 0 +1493 1491 240 1492 0 +238 1474 1943 1473 0 +1474 101 1944 1943 0 +1473 1943 1942 442 0 +1943 1944 297 1942 0 +102 1480 1481 1479 0 +1480 242 1478 1481 0 +1479 1481 1478 439 0 +55 1507 1508 1506 0 +1507 245 1505 1508 0 +1506 1508 1505 344 0 +244 1519 1539 1520 0 +1519 445 1537 1539 0 +1520 1539 1538 104 0 +1539 1537 246 1538 0 +244 1522 1677 1521 0 +1522 103 1678 1677 0 +1521 1677 1676 446 0 +1677 1678 264 1676 0 +104 1527 1528 1526 0 +1527 248 1525 1528 0 +1526 1528 1525 443 0 +247 1542 1563 1543 0 +1542 448 1561 1563 0 +1543 1563 1562 105 0 +1563 1561 249 1562 0 +105 1551 1552 1550 0 +1551 251 1549 1552 0 +1550 1552 1549 447 0 +250 1566 1587 1567 0 +1566 450 1585 1587 0 +1567 1587 1586 106 0 +1587 1585 252 1586 0 +106 1576 1577 1575 0 +1576 254 1574 1577 0 +1575 1577 1574 449 0 +253 1594 1895 1593 0 +1594 107 1896 1895 0 +1593 1895 1894 452 0 +1895 1896 291 1894 0 +58 1599 1600 1598 0 +1599 257 1597 1600 0 +1598 1600 1597 350 0 +256 1611 1631 1612 0 +1611 455 1629 1631 0 +1612 1631 1630 109 0 +1631 1629 258 1630 0 +256 1614 1773 1613 0 +1614 108 1774 1773 0 +1613 1773 1772 456 0 +1773 1774 276 1772 0 +109 1619 1620 1618 0 +1619 260 1617 1620 0 +1618 1620 1617 453 0 +259 1634 1655 1635 0 +1634 458 1653 1655 0 +1635 1655 1654 110 0 +1655 1653 261 1654 0 +110 1643 1644 1642 0 +1643 263 1641 1644 0 +1642 1644 1641 457 0 +262 1658 1681 1659 0 +1658 460 1679 1681 0 +1659 1681 1680 111 0 +1681 1679 264 1680 0 +111 1668 1669 1667 0 +1668 266 1666 1669 0 +1667 1669 1666 459 0 +61 1695 1696 1694 0 +1695 269 1693 1696 0 +1694 1696 1693 356 0 +268 1707 1727 1708 0 +1707 463 1725 1727 0 +1708 1727 1726 113 0 +1727 1725 270 1726 0 +268 1710 1869 1709 0 +1710 112 1870 1869 0 +1709 1869 1868 464 0 +1869 1870 288 1868 0 +113 1715 1716 1714 0 +1715 272 1713 1716 0 +1714 1716 1713 461 0 +271 1730 1751 1731 0 +1730 466 1749 1751 0 +1731 1751 1750 114 0 +1751 1749 273 1750 0 +114 1739 1740 1738 0 +1739 275 1737 1740 0 +1738 1740 1737 465 0 +274 1754 1777 1755 0 +1754 468 1775 1777 0 +1755 1777 1776 115 0 +1777 1775 276 1776 0 +115 1764 1765 1763 0 +1764 278 1762 1765 0 +1763 1765 1762 467 0 +64 1791 1792 1790 0 +1791 281 1789 1792 0 +1790 1792 1789 362 0 +280 1803 1823 1804 0 +1803 471 1821 1823 0 +1804 1823 1822 117 0 +1823 1821 282 1822 0 +280 1806 1969 1805 0 +1806 116 1970 1969 0 +1805 1969 1968 472 0 +1969 1970 300 1968 0 +117 1811 1812 1810 0 +1811 284 1809 1812 0 +1810 1812 1809 469 0 +283 1826 1847 1827 0 +1826 474 1845 1847 0 +1827 1847 1846 118 0 +1847 1845 285 1846 0 +118 1835 1836 1834 0 +1835 287 1833 1836 0 +1834 1836 1833 473 0 +286 1850 1873 1851 0 +1850 476 1871 1873 0 +1851 1873 1872 119 0 +1873 1871 288 1872 0 +119 1860 1861 1859 0 +1860 290 1858 1861 0 +1859 1861 1858 475 0 +66 1887 1888 1886 0 +1887 293 1885 1888 0 +1886 1888 1885 368 0 +292 1902 1923 1903 0 +1902 478 1921 1923 0 +1903 1923 1922 120 0 +1923 1921 294 1922 0 +120 1911 1912 1910 0 +1911 296 1909 1912 0 +1910 1912 1909 477 0 +295 1926 1947 1927 0 +1926 480 1945 1947 0 +1927 1947 1946 121 0 +1947 1945 297 1946 0 +121 1935 1936 1934 0 +1935 299 1933 1936 0 +1934 1936 1933 479 0 +298 1950 1973 1951 0 +1950 482 1971 1973 0 +1951 1973 1972 122 0 +1973 1971 300 1972 0 +122 1960 1961 1959 0 +1960 302 1958 1961 0 +1959 1961 1958 481 0 + +End diff --git a/thirdparty/lm6/transmesh.c b/thirdparty/lm6/transmesh.c new file mode 100644 index 00000000..b3e9d6c0 --- /dev/null +++ b/thirdparty/lm6/transmesh.c @@ -0,0 +1,147 @@ + + +/*----------------------------------------------------------*/ +/* */ +/* TRANSMESH V 4.0 */ +/* */ +/*----------------------------------------------------------*/ +/* */ +/* Description: convert mesh file from/to ascii/bin */ +/* Author: Loic MARECHAL */ +/* Creation date: mar 08 2004 */ +/* Last modification: feb 27 2014 */ +/* */ +/*----------------------------------------------------------*/ + + +/*----------------------------------------------------------*/ +/* Includes */ +/*----------------------------------------------------------*/ + +#define TRANSMESH 1 + +#include +#include +#include +#include + + +/*----------------------------------------------------------*/ +/* Check args and copy each fields from infile to outfile */ +/*----------------------------------------------------------*/ + +int main(int argc, char **argv) +{ + int i, j, NmbTyp, SolSiz, TypTab[ GmfMaxTyp ], InpIdx, OutIdx, FilVer=0, InpVer, OutVer=1, dim; + long NmbLin; + float f; + double d; + char *InpNam, *OutNam, *VerNam; + + switch(argc) + { + case 1 : + { + printf("\nTRANSMESH v4.0, feb 27 2014, Loic MARECHAL / INRIA\n"); + printf(" Usage : transmesh source_name destination_name (-options)\n"); + printf(" optional arguments : -v output_file_version\n"); + printf(" version 1: 32 bits integers, 32 bits reals, file size < 2 GigaBytes\n"); + printf(" version 2: 32 bits integers, 64 bits reals, file size < 2 GigaBytes\n"); + printf(" version 3: 32 bits integers, 64 bits reals, file size < 8 ExaBytes\n"); + printf(" version 4: 64 bits integers, 64 bits reals, file size < 8 ExaBytes\n"); + exit(1); + }break; + + case 3 : + { + InpNam = *++argv; + OutNam = *++argv; + }break; + + case 5 : + { + InpNam = *++argv; + OutNam = *++argv; + VerNam = *++argv; + + if(!strcmp(VerNam, "-v")) + { + FilVer = atoi(*++argv); + + if( (FilVer < 1) || (FilVer > 4) ) + { + printf("Wrong size type : %d\n", FilVer); + exit(1); + } + } + }break; + + default : + { + printf("Wrong number of arguments.\n"); + exit(1); + }break; + } + + if(!(InpIdx = GmfOpenMesh(InpNam, GmfRead, &InpVer, &dim))) + { + fprintf(stderr,"Source of error : TRANSMESH / OPEN_MESH\n"); + fprintf(stderr,"Cannot open %s\n", InpNam); + return(1); + } + + if(FilVer) + OutVer = FilVer; + else + OutVer = InpVer; + + if(!(OutIdx = GmfOpenMesh(OutNam, GmfWrite, OutVer, dim))) + { + fprintf(stderr,"Source of error : TRANSMESH / OPEN_MESH\n"); + fprintf(stderr,"Cannot open %s\n", OutNam); + return(1); + } + + for(i=0;i<=GmfMaxKwd;i++) + { + if(!strcmp(GmfKwdFmt[i][0], "Reserved") || !strcmp(GmfKwdFmt[i][0], "End")) + continue; + + GmfGotoKwd(InpIdx, i); + + if(strcmp("i", GmfKwdFmt[i][2])) + { + if(NmbLin = GmfStatKwd(InpIdx, i)) + GmfSetKwd(OutIdx, i); + else + continue; + } + else if(strcmp("sr", GmfKwdFmt[i][3])) + { + if(NmbLin = GmfStatKwd(InpIdx, i)) + GmfSetKwd(OutIdx, i, NmbLin); + else + continue; + } + else + { + if(NmbLin = GmfStatKwd(InpIdx, i, &NmbTyp, &SolSiz, TypTab)) + GmfSetKwd(OutIdx, i, NmbLin, NmbTyp, TypTab); + else + continue; + } + + printf("Parsing %s : %d item\n", GmfKwdFmt[i][0], NmbLin); + + for(j=1;j<=NmbLin;j++) + GmfCpyLin(InpIdx, OutIdx, i); + } + + if(!GmfCloseMesh(InpIdx)) + return(1); + + if(!GmfCloseMesh(OutIdx)) + return(1); + + return(0); +} From bf1cfbe78c7fe879503782615782d409e6aa9bdc Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Thu, 10 Mar 2016 15:22:00 +0100 Subject: [PATCH 310/402] added LM6VolumeImport class. Signed-off-by: Etienne Schmitt --- cgogn/io/CMakeLists.txt | 4 +- cgogn/io/io_utils.cpp | 3 + cgogn/io/io_utils.h | 3 +- cgogn/io/lm6_io.h | 155 ++++++++++++++++++++++++++++++++++++++++ cgogn/io/map_import.h | 4 +- 5 files changed, 166 insertions(+), 3 deletions(-) create mode 100644 cgogn/io/lm6_io.h diff --git a/cgogn/io/CMakeLists.txt b/cgogn/io/CMakeLists.txt index 79cd7772..1db1c0c6 100644 --- a/cgogn/io/CMakeLists.txt +++ b/cgogn/io/CMakeLists.txt @@ -24,6 +24,7 @@ set(HEADER_FILES off_io.h obj_io.h ply_io.h + lm6_io.h mesh_io_gen.h ) @@ -42,12 +43,13 @@ set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "_d") target_include_directories(${PROJECT_NAME} PUBLIC $ $ + $ $ $ $ ) -target_link_libraries(${PROJECT_NAME} tinyxml2 cgogn_core cgogn_geometry ply ${ZLIB_LIBRARIES}) +target_link_libraries(${PROJECT_NAME} tinyxml2 cgogn_core cgogn_geometry ply lm6 ${ZLIB_LIBRARIES}) install(DIRECTORY . DESTINATION include/cgogn/io diff --git a/cgogn/io/io_utils.cpp b/cgogn/io/io_utils.cpp index 2e3eae65..4dd12079 100644 --- a/cgogn/io/io_utils.cpp +++ b/cgogn/io/io_utils.cpp @@ -219,6 +219,9 @@ CGOGN_IO_API FileType get_file_type(const std::string& filename) return FileType::FileType_VTU; if (extension == "vtp") return FileType::FileType_VTP; + if (extension == "meshb") + return FileType::FileType_MESHB; + return FileType::FileType_UNKNOWN; } diff --git a/cgogn/io/io_utils.h b/cgogn/io/io_utils.h index ed302d92..5ccd007c 100644 --- a/cgogn/io/io_utils.h +++ b/cgogn/io/io_utils.h @@ -46,7 +46,8 @@ enum FileType FileType_PLY, FileType_VTK_LEGACY, FileType_VTU, - FileType_VTP + FileType_VTP, + FileType_MESHB }; enum DataType diff --git a/cgogn/io/lm6_io.h b/cgogn/io/lm6_io.h new file mode 100644 index 00000000..21a5d249 --- /dev/null +++ b/cgogn/io/lm6_io.h @@ -0,0 +1,155 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef IO_LM6_IO_H_ +#define IO_LM6_IO_H_ + +#include +#include + +namespace cgogn +{ + +namespace io +{ + +template +class LM6VolumeImport : public VolumeImport +{ + using Inherit = VolumeImport; + using Self = LM6VolumeImport; + template + using ChunkArray = typename Inherit::template ChunkArray; + + // MeshImportGen interface +public: + inline LM6VolumeImport() {} + + virtual void clear() override + { + Inherit::clear(); + } + +protected: + virtual bool import_file_impl(const std::string& filename) override + { + int version = -1; + int dimension = -1; + int mesh_index = GmfOpenMesh(filename.c_str(), GmfRead, &version, &dimension); + if (mesh_index == 0) + return false; + + const int number_of_vertices = GmfStatKwd(mesh_index, GmfVertices); + const int number_of_tetras = GmfStatKwd(mesh_index, GmfTetrahedra); + const int number_of_hexas = GmfStatKwd(mesh_index, GmfHexahedra); + const int number_of_prisms = GmfStatKwd(mesh_index, GmfPrisms); + const int number_of_pyramids = GmfStatKwd(mesh_index, GmfPyramids); + + + this->volumes_vertex_indices_.reserve(4*number_of_tetras + 8*number_of_hexas + 6*number_of_prisms + 5*number_of_pyramids); + + this->nb_vertices_ = number_of_vertices; + this->nb_volumes_ = number_of_tetras + number_of_hexas + number_of_prisms + number_of_pyramids; + this->volumes_nb_vertices_.reserve(this->nb_volumes_); + + if (number_of_vertices == 0 || this->nb_volumes_ == 0u) + { + GmfCloseMesh(mesh_index); + clear(); + return false; + } + + ChunkArray* position = this->vertex_attributes_.template add_attribute("position"); + int ref; + + GmfGotoKwd(mesh_index, GmfVertices); + for (int i = 0 ; i < number_of_vertices; ++i) + { + unsigned int idx = this->vertex_attributes_.template insert_lines<1>(); + VEC3& v = position->operator [](idx); + (void) GmfGetLin(mesh_index, GmfVertices, &v[0],&v[1], &v[2], &ref); + } + + if (number_of_tetras > 0) + { + GmfGotoKwd(mesh_index, GmfTetrahedra); + std::array ids; + for (int i = 0 ; i < number_of_tetras; ++i) + { + this->volumes_nb_vertices_.push_back(4); + (void) GmfGetLin(mesh_index, GmfTetrahedra, &ids[0],&ids[1], &ids[2], &ids[3], &ref); + for (int x : ids) + this->volumes_vertex_indices_.push_back(static_cast(x)); + } + } + + if (number_of_hexas > 0) + { + GmfGotoKwd(mesh_index, GmfHexahedra); + std::array ids; + for (int i = 0 ; i < number_of_hexas; ++i) + { + this->volumes_nb_vertices_.push_back(8); + (void) GmfGetLin(mesh_index, GmfHexahedra, &ids[0],&ids[1], &ids[2], &ids[3], &ids[4], &ids[5], &ids[6], &ids[7], &ref); + for (int x : ids) + this->volumes_vertex_indices_.push_back(static_cast(x)); + } + } + + if (number_of_prisms > 0) + { + GmfGotoKwd(mesh_index, GmfPrisms); + std::array ids; + for (int i = 0 ; i < number_of_prisms; ++i) + { + this->volumes_nb_vertices_.push_back(6); + (void) GmfGetLin(mesh_index, GmfPrisms, &ids[0],&ids[1], &ids[2], &ids[3], &ids[4], &ids[5], &ref); + for (int x : ids) + this->volumes_vertex_indices_.push_back(static_cast(x)); + } + } + + if (number_of_pyramids > 0) + { + GmfGotoKwd(mesh_index, GmfPyramids); + std::array ids; + for (int i = 0 ; i < number_of_pyramids; ++i) + { + this->volumes_nb_vertices_.push_back(5); + (void) GmfGetLin(mesh_index, GmfPyramids, &ids[0],&ids[1], &ids[2], &ids[3], &ids[4], &ref); + for (int x : ids) + this->volumes_vertex_indices_.push_back(static_cast(x)); + } + } + + GmfCloseMesh(mesh_index); + return true; + } +}; + + +} // namespace io +} // namespace cgogn + + +#endif // IO_LM6_IO_H_ diff --git a/cgogn/io/map_import.h b/cgogn/io/map_import.h index 52711c32..a8cf97cb 100644 --- a/cgogn/io/map_import.h +++ b/cgogn/io/map_import.h @@ -36,6 +36,7 @@ #include #include #include +#include namespace cgogn { @@ -99,7 +100,8 @@ inline std::unique_ptr > newVolumeImport(const std::str switch (file_type) { case FileType::FileType_VTK_LEGACY: - case FileType::FileType_VTU: return make_unique>(); + case FileType::FileType_VTU: return make_unique>(); + case FileType::FileType_MESHB: return make_unique>(); default: std::cerr << "SurfaceImport does not handle files with extension \"" << get_extension(filename) << "\"." << std::endl; return std::unique_ptr> (); From ff7dbf644bb1944cc87301cac0a94a1eae1cb95f Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Thu, 10 Mar 2016 15:22:15 +0100 Subject: [PATCH 311/402] added an exemple of mixed mesh. Signed-off-by: Etienne Schmitt --- data/meshes/hex_dominant.meshb | Bin 0 -> 444020 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 data/meshes/hex_dominant.meshb diff --git a/data/meshes/hex_dominant.meshb b/data/meshes/hex_dominant.meshb new file mode 100644 index 0000000000000000000000000000000000000000..a5a1bcefba90263fbdaa3aa3966fe303a664b1a0 GIT binary patch literal 444020 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 laJlG?j!qrI!_Y3-XV+r!}mj1@+HB`OfT$q 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%0AKPyPIY8^es8A%)HfNU%T2}$)!hcT{@Dh7 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 z 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 Date: Thu, 10 Mar 2016 15:42:39 +0100 Subject: [PATCH 312/402] test corrections --- CMakeLists.txt | 2 ++ cgogn/core/cmap/map_base_data.h | 3 ++- cgogn/core/tests/cmap/cmap1_test.cpp | 10 +++++----- cgogn/core/tests/cmap/cmap1_topo_test.cpp | 11 ++++++----- cgogn/core/tests/cmap/cmap2_test.cpp | 10 +++++----- cgogn/core/tests/cmap/cmap2_topo_test.cpp | 10 +++++----- cgogn/core/tests/utils/name_types_test.cpp | 10 +++++----- 7 files changed, 30 insertions(+), 26 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 95f43b2d..72fc6457 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,8 @@ project(CGoGN LANGUAGES CXX C ) +enable_testing() + #### Default build type if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release") diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index 58ffa201..219c55c3 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -39,8 +39,9 @@ #include #include -#define CGOGN_CHECK_DYNAMIC_TYPE cgogn_message_assert(typeid(*this).hash_code() == typeid(Self).hash_code(),\ +#define CGOGN_CHECK_DYNAMIC_TYPE cgogn_message_assert( (std::is_same::value),\ std::string("dynamic type of current object : ") + cgogn::internal::demangle(std::string(typeid(*this).name())) + std::string(",\nwhereas Self = ") + cgogn::name_of_type(Self())) + #ifndef _MSC_VER #define CGOGN_CHECK_CONCRETE_TYPE static_assert(std::is_same::value,"The concrete map type has to be equal to Self") #else diff --git a/cgogn/core/tests/cmap/cmap1_test.cpp b/cgogn/core/tests/cmap/cmap1_test.cpp index 8d17f0b0..ff63858d 100644 --- a/cgogn/core/tests/cmap/cmap1_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_test.cpp @@ -78,12 +78,12 @@ class CMap1Test : public ::testing::Test unsigned int count = 0u; for (unsigned int i = 0u; i < n; ++i) { - unsigned int n = 1u + std::rand() % 10; - Dart d = cmap_.add_face(n); - count += n; + unsigned int m = 1u + std::rand() % 10; + Dart d = cmap_.add_face(m); + count += m; - n = std::rand() % 10u; - while (n-- > 0u) d = cmap_.phi1(d); + m = std::rand() % 10u; + while (m-- > 0u) d = cmap_.phi1(d); darts_.push_back(d); } diff --git a/cgogn/core/tests/cmap/cmap1_topo_test.cpp b/cgogn/core/tests/cmap/cmap1_topo_test.cpp index af0c926a..a03ef439 100644 --- a/cgogn/core/tests/cmap/cmap1_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_topo_test.cpp @@ -82,12 +82,12 @@ class CMap1TopoTest : public CMap1, public ::testing::Test unsigned int count = 0u; for (unsigned int i = 0u; i < n; ++i) { - unsigned int n = 1u + std::rand() % 10u; - Dart d = add_face_topo(n); - count += n; + unsigned int m = 1u + std::rand() % 10u; + Dart d = add_face_topo(m); + count += m; - n = std::rand() % 10u; - while (n-- > 0u) d = phi1(d); + m = std::rand() % 10u; + while (m-- > 0u) d = phi1(d); darts_.push_back(d); } @@ -182,6 +182,7 @@ TEST_F(CMap1TopoTest, remove_face) --count_faces; } } + EXPECT_EQ(nb_darts(), count_vertices); EXPECT_EQ(nb_cells(), count_vertices); EXPECT_EQ(nb_cells(), count_faces); diff --git a/cgogn/core/tests/cmap/cmap2_test.cpp b/cgogn/core/tests/cmap/cmap2_test.cpp index c147016c..995c1d21 100644 --- a/cgogn/core/tests/cmap/cmap2_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_test.cpp @@ -85,12 +85,12 @@ class CMap2Test : public ::testing::Test unsigned int count = 0u; for (unsigned int i = 0u; i < n; ++i) { - unsigned int n = 1u + std::rand() % 10u; - Dart d = cmap_.add_face(n); - count += n; + unsigned int m = 1u + std::rand() % 10u; + Dart d = cmap_.add_face(m); + count += m; - n = std::rand() % 10u; - while (n-- > 0u) d = cmap_.phi1(d); + m = std::rand() % 10u; + while (m-- > 0u) d = cmap_.phi1(d); darts_.push_back(d); } diff --git a/cgogn/core/tests/cmap/cmap2_topo_test.cpp b/cgogn/core/tests/cmap/cmap2_topo_test.cpp index 0987faf5..cee9cc8d 100644 --- a/cgogn/core/tests/cmap/cmap2_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_topo_test.cpp @@ -139,12 +139,12 @@ class CMap2TopoTest : public CMap2, public ::testing::Test unsigned int count = 0u; for (unsigned int i = 0u; i < n; ++i) { - unsigned int n = 1u + std::rand() % 10u; - Dart d = add_face_topo(n); - count += n; + unsigned int m = 1u + std::rand() % 10u; + Dart d = add_face_topo(m); + count += m; - n = std::rand() % 10u; - while (n-- > 0u) d = phi1(d); + m = std::rand() % 10u; + while (m-- > 0u) d = phi1(d); darts_.push_back(d); } diff --git a/cgogn/core/tests/utils/name_types_test.cpp b/cgogn/core/tests/utils/name_types_test.cpp index d7713d5c..864f15e0 100644 --- a/cgogn/core/tests/utils/name_types_test.cpp +++ b/cgogn/core/tests/utils/name_types_test.cpp @@ -42,13 +42,13 @@ TEST(NameTypesTest, NumTypes) EXPECT_EQ(cgogn::name_of_type(unsigned_char()), "unsigned char"); EXPECT_EQ(cgogn::name_of_type(wchar_t()), "wchar_t"); -#ifndef _MSC_VER - EXPECT_EQ(cgogn::name_of_type(char16_t()), "char16_t"); - EXPECT_EQ(cgogn::name_of_type(char32_t()), "char32_t"); -#else +#if _MSC_VER == 1800 // VS2013 EXPECT_EQ(cgogn::name_of_type(char16_t()), "unsigned short"); EXPECT_EQ(cgogn::name_of_type(char32_t()), "unsigned int"); -#endif // _MSC_VER +#else + EXPECT_EQ(cgogn::name_of_type(char16_t()), "char16_t"); + EXPECT_EQ(cgogn::name_of_type(char32_t()), "char32_t"); +#endif // VS2013 EXPECT_EQ(cgogn::name_of_type(short()), "short"); EXPECT_EQ(cgogn::name_of_type(unsigned_short()), "unsigned short"); From 28067035fc00147d8b8ff0de116aa506218ac148 Mon Sep 17 00:00:00 2001 From: thery Date: Thu, 10 Mar 2016 15:55:23 +0100 Subject: [PATCH 313/402] static_assert pb in mr --- cgogn/multiresolution/cph/ihcmap3.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cgogn/multiresolution/cph/ihcmap3.h b/cgogn/multiresolution/cph/ihcmap3.h index 1a218e26..95753469 100644 --- a/cgogn/multiresolution/cph/ihcmap3.h +++ b/cgogn/multiresolution/cph/ihcmap3.h @@ -362,9 +362,10 @@ class IHCMap3_T :public CMap3_T, public CPH3 template inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const { - static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || - ORBIT == Orbit::PHI2 || ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21, - "Orbit not supported in a CMap2"); + //static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || + // ORBIT == Orbit::PHI2 || ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21, + // "Orbit not supported in a CMap2"); + // PAS POSSIBLE SOUS VS2013! switch (ORBIT) { case Orbit::DART: f(c.dart); break; From 5f97b53784bb4bcc1ef541e278ad0f5cff30eb5b Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Thu, 10 Mar 2016 17:35:00 +0100 Subject: [PATCH 314/402] fix bug of intersection with degenerated faces --- cgogn/geometry/algos/picking.h | 6 +++--- cgogn/geometry/functions/intersection.h | 22 +++++++++++++++------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/cgogn/geometry/algos/picking.h b/cgogn/geometry/algos/picking.h index 4ca51e53..cb956ea6 100644 --- a/cgogn/geometry/algos/picking.h +++ b/cgogn/geometry/algos/picking.h @@ -77,7 +77,7 @@ inline void picking_internal_face(MAP& m, const typename MAP::template VertexAtt std::vector& ear_indices = ear_indices_th[th]; ear_indices.clear(); cgogn::geometry::compute_ear_triangulation(m,f,position,ear_indices); - for(unsigned int i=0; i::max(); + Scalar min_d2 = std::numeric_limits::max(); Vertex closest_vertex; Face f = std::get<0>(fs); @@ -178,7 +178,7 @@ bool picking_edge(MAP& m, const typename MAP::template VertexAttributeHandler::max(); + Scalar min_d2 = std::numeric_limits::max(); Edge closest_edge; Face f = std::get<0>(fs); diff --git a/cgogn/geometry/functions/intersection.h b/cgogn/geometry/functions/intersection.h index d7dab710..2f7ecf2a 100644 --- a/cgogn/geometry/functions/intersection.h +++ b/cgogn/geometry/functions/intersection.h @@ -46,24 +46,32 @@ bool intersection_ray_triangle(const VEC3_T& P, const VEC3_T& Dir, const VEC3_T& unsigned int np = 0 ; unsigned int nn = 0 ; + unsigned int nz = 0 ; - if (x >Scalar(0)) + if (x > Scalar(0)) ++np ; - else + else if (x < Scalar(0)) ++nn ; + else + ++nz; - if (y >Scalar(0)) + if (y > Scalar(0)) ++np ; - else + else if (y < Scalar(0)) ++nn ; + else + ++nz; - if (z >Scalar(0)) + + if (z > Scalar(0)) ++np ; - else + else if (z < Scalar(0)) ++nn ; + else + ++nz; // line intersect the triangle - if ((np != 0) && (nn != 0)) + if (((np != 0) && (nn != 0)) || (nz == 3)) return false ; Scalar sum = x + y + z ; From f9f71e5e0ccefc0c3d27ea0cd1abfd7934b5f44c Mon Sep 17 00:00:00 2001 From: thery Date: Thu, 10 Mar 2016 18:02:40 +0100 Subject: [PATCH 315/402] fix static assert pb in IHCMap3::foreach_dart_of_orbit --- cgogn/multiresolution/cph/ihcmap3.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cgogn/multiresolution/cph/ihcmap3.h b/cgogn/multiresolution/cph/ihcmap3.h index 95753469..6c1c27c2 100644 --- a/cgogn/multiresolution/cph/ihcmap3.h +++ b/cgogn/multiresolution/cph/ihcmap3.h @@ -362,10 +362,12 @@ class IHCMap3_T :public CMap3_T, public CPH3 template inline void foreach_dart_of_orbit(Cell c, const FUNC& f) const { - //static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || - // ORBIT == Orbit::PHI2 || ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21, - // "Orbit not supported in a CMap2"); - // PAS POSSIBLE SOUS VS2013! + static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); + static_assert(ORBIT == Orbit::DART || ORBIT == Orbit::PHI1 || ORBIT == Orbit::PHI2 || + ORBIT == Orbit::PHI1_PHI2 || ORBIT == Orbit::PHI21 || + ORBIT == Orbit::PHI1_PHI3 || ORBIT == Orbit::PHI2_PHI3 || ORBIT == Orbit::PHI21_PHI31, + "Orbit not supported in a IHCMap3"); + switch (ORBIT) { case Orbit::DART: f(c.dart); break; From 770259ae734b3aa0cb25db4c9437e701214dccc3 Mon Sep 17 00:00:00 2001 From: Lionel Untereiner Date: Fri, 11 Mar 2016 17:51:48 +0100 Subject: [PATCH 316/402] fix export --- cgogn/io/map_export.h | 120 ++++++++++++++++++++++++------------------ 1 file changed, 68 insertions(+), 52 deletions(-) diff --git a/cgogn/io/map_export.h b/cgogn/io/map_export.h index cdfc33ec..a19c89e6 100644 --- a/cgogn/io/map_export.h +++ b/cgogn/io/map_export.h @@ -53,6 +53,9 @@ namespace io template bool export_off(MAP& map, const typename MAP::template VertexAttributeHandler& position, const std::string& filename) { + using Vertex = typename MAP::Vertex; + using Face = typename MAP::Face; + std::ofstream fp(filename.c_str(), std::ios::out); if (!fp.good()) { @@ -61,7 +64,7 @@ bool export_off(MAP& map, const typename MAP::template VertexAttributeHandler() << " "<< map.template nb_cells() << " 0"<< std::endl; // nb_edge unused ? + fp << map.template nb_cells() << " "<< map.template nb_cells() << " 0"<< std::endl; // nb_edge unused ? // set precision for real output fp<< std::setprecision(12); @@ -69,12 +72,12 @@ bool export_off(MAP& map, const typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); + typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); ids.set_all_container_values(UINT_MAX); unsigned int count = 0; - map.template foreach_cell([&] (typename MAP::Face f) + map.template foreach_cell([&] (Face f) { - map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) + map.template foreach_incident_vertex(f, [&] (Vertex v) { if (ids[v]==UINT_MAX) { @@ -88,12 +91,12 @@ bool export_off(MAP& map, const typename MAP::template VertexAttributeHandler prim; prim.reserve(20); - map.template foreach_cell([&] (typename MAP::Face f) + map.template foreach_cell([&] (Face f) { unsigned int valence = 0; prim.clear(); - map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) + map.template foreach_incident_vertex(f, [&] (Vertex v) { prim.push_back(ids[v]); ++valence; @@ -121,6 +124,9 @@ bool export_off(MAP& map, const typename MAP::template VertexAttributeHandler bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandler& position, const std::string& filename) { + using Vertex = typename MAP::Vertex; + using Face = typename MAP::Face; + std::ofstream fp(filename.c_str(), std::ios::out|std::ofstream::binary); if (!fp.good()) { @@ -131,8 +137,8 @@ bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandle fp << "OFF BINARY"<< std::endl; unsigned int nb_cells[3]; - nb_cells[0] = swap_endianness_system_big(map.template nb_cells()); - nb_cells[1] = swap_endianness_system_big(map.template nb_cells()); + nb_cells[0] = swap_endianness_native_big(map.template nb_cells()); + nb_cells[1] = swap_endianness_native_big(map.template nb_cells()); nb_cells[2] = 0; fp.write(reinterpret_cast(nb_cells),3*sizeof(unsigned int)); @@ -140,7 +146,7 @@ bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandle // two pass of traversal to avoid huge buffer (with same performance); // first pass to save positions & store contiguous indices - typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); + typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); ids.set_all_container_values(UINT_MAX); @@ -151,9 +157,9 @@ bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandle std::vector buffer_pos; buffer_pos.reserve(BUFFER_SZ+3); - map.template foreach_cell([&] (typename MAP::Face f) + map.template foreach_cell([&] (Face f) { - map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) + map.template foreach_incident_vertex(f, [&] (Vertex v) { if (ids[v]==UINT_MAX) { @@ -162,9 +168,9 @@ bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandle // VEC3 can be double ! float Pf[3]={float(P[0]),float(P[1]),float(P[2])}; unsigned int* ui_vec = reinterpret_cast(Pf); - ui_vec[0] = swap_endianness_system_big(ui_vec[0]); - ui_vec[1] = swap_endianness_system_big(ui_vec[1]); - ui_vec[2] = swap_endianness_system_big(ui_vec[2]); + ui_vec[0] = swap_endianness_native_big(ui_vec[0]); + ui_vec[1] = swap_endianness_native_big(ui_vec[1]); + ui_vec[2] = swap_endianness_native_big(ui_vec[2]); buffer_pos.push_back(Pf[0]); buffer_pos.push_back(Pf[1]); @@ -191,20 +197,20 @@ bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandle std::vector prim; prim.reserve(20); - map.template foreach_cell([&] (typename MAP::Face f) + map.template foreach_cell([&] (Face f) { unsigned int valence = 0; prim.clear(); - map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) + map.template foreach_incident_vertex(f, [&] (Vertex v) { prim.push_back(ids[v]); ++valence; }); - buffer_prims.push_back(swap_endianness_system_big(valence)); + buffer_prims.push_back(swap_endianness_native_big(valence)); for(unsigned int i: prim) - buffer_prims.push_back(swap_endianness_system_big(i)); + buffer_prims.push_back(swap_endianness_native_big(i)); if (buffer_prims.size() >= BUFFER_SZ) { @@ -236,6 +242,9 @@ bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandle template bool export_obj(MAP& map, const typename MAP::template VertexAttributeHandler& position, const std::string& filename) { + using Vertex = typename MAP::Vertex; + using Face = typename MAP::Face; + std::ofstream fp(filename.c_str(), std::ios::out); if (!fp.good()) { @@ -250,12 +259,12 @@ bool export_obj(MAP& map, const typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); + typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); ids.set_all_container_values(UINT_MAX); unsigned int count = 1; - map.template foreach_cell([&] (typename MAP::Face f) + map.template foreach_cell([&] (Face f) { - map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) + map.template foreach_incident_vertex(f, [&] (Vertex v) { if (ids[v]==UINT_MAX) { @@ -270,10 +279,10 @@ bool export_obj(MAP& map, const typename MAP::template VertexAttributeHandler prim; prim.reserve(20); - map.template foreach_cell([&] (typename MAP::Face f) + map.template foreach_cell([&] (Face f) { fp << "f"; - map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) + map.template foreach_incident_vertex(f, [&] (Vertex v) { fp << " " << ids[v]; }); @@ -297,6 +306,9 @@ bool export_obj(MAP& map, const typename MAP::template VertexAttributeHandler bool export_obj(MAP& map, const typename MAP::template VertexAttributeHandler& position, const typename MAP::template VertexAttributeHandler& normal, const std::string& filename) { + using Vertex = typename MAP::Vertex; + using Face = typename MAP::Face; + std::ofstream fp(filename.c_str(), std::ios::out); if (!fp.good()) { @@ -310,18 +322,18 @@ bool export_obj(MAP& map, const typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); + typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); ids.set_all_container_values(UINT_MAX); unsigned int count = 1; std::vector indices; - indices.reserve(map.template nb_cells()); - map.template foreach_cell([&] (typename MAP::Face f) + indices.reserve(map.template nb_cells()); + map.template foreach_cell([&] (Face f) { - map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) + map.template foreach_incident_vertex(f, [&] (Vertex v) { if (ids[v]==UINT_MAX) { - indices.push_back(map.template get_embedding(v)); + indices.push_back(map.template get_embedding(v)); ids[v] = count++; const VEC3& P = position[v]; fp <<"v " << P[0] << " " << P[1] << " " << P[2] << std::endl; @@ -341,10 +353,10 @@ bool export_obj(MAP& map, const typename MAP::template VertexAttributeHandler prim; prim.reserve(20); - map.template foreach_cell([&] (typename MAP::Face f) + map.template foreach_cell([&] (Face f) { fp << "f"; - map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) + map.template foreach_incident_vertex(f, [&] (Vertex v) { fp << " " << ids[v] << "//" << ids[v]; }); @@ -361,6 +373,9 @@ bool export_obj(MAP& map, const typename MAP::template VertexAttributeHandler bool export_stl_ascii(MAP& map, const typename MAP::template VertexAttributeHandler& position, const std::string& filename) { + using Vertex = typename MAP::Vertex; + using Face = typename MAP::Face; + std::ofstream fp(filename.c_str(), std::ios::out); if (!fp.good()) { @@ -376,14 +391,14 @@ bool export_stl_ascii(MAP& map, const typename MAP::template VertexAttributeHand std::vector table_indices; table_indices.reserve(256); - map.template foreach_cell([&] (typename MAP::Face f) + map.template foreach_cell([&] (Face f) { if (map.is_triangle(f)) { VEC3 N = geometry::face_normal(map,f,position); fp << "facet normal "<< N[0] << " "<< N[1]<< " " << N[2]<< std::endl; fp << "outer loop"<< std::endl; - map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) + map.template foreach_incident_vertex(f, [&] (Vertex v) { const VEC3& P = position[v]; fp <<"vertex " << P[0] << " " << P[1] << " " << P[2] << std::endl; @@ -434,7 +449,8 @@ bool export_stl_bin(MAP& map, const typename MAP::template VertexAttributeHandle //REAL32[3] – Vertex 3 //UINT16 – Attribute byte count //end - + using Vertex = typename MAP::Vertex; + using Face = typename MAP::Face; std::ofstream fp(filename.c_str(), std::ios::out|std::ofstream::binary); if (!fp.good()) @@ -445,7 +461,7 @@ bool export_stl_bin(MAP& map, const typename MAP::template VertexAttributeHandle // header + nb triangles unsigned int header[21]; - header[20] = map.template nb_cells(); + header[20] = map.template nb_cells(); fp.write(reinterpret_cast(header),21*sizeof(unsigned int)); // buffer @@ -475,16 +491,16 @@ bool export_stl_bin(MAP& map, const typename MAP::template VertexAttributeHandle unsigned int nb_tri = 0; // write face cutted in triangle if necessary - map.template foreach_cell([&] (typename MAP::Face f) + map.template foreach_cell([&] (Face f) { if (map.is_triangle(f)) { Dart d = f.dart; - const VEC3& A = position[typename MAP::Vertex(d)]; + const VEC3& A = position[Vertex(d)]; d = map.phi1(d); - const VEC3& B = position[typename MAP::Vertex(d)]; + const VEC3& B = position[Vertex(d)]; d = map.phi1(d); - const VEC3& C = position[typename MAP::Vertex(d)]; + const VEC3& C = position[Vertex(d)]; write_tri(A,B,C); ++nb_tri; } @@ -545,11 +561,11 @@ bool export_ply(MAP& map, const typename MAP::template VertexAttributeHandler() << std::endl ; + fp << "element vertex " << map.template nb_cells() << std::endl ; fp << "property float x" << std::endl ; fp << "property float y" << std::endl ; fp << "property float z" << std::endl ; - fp << "element face " << map.template nb_cells() << std::endl ; + fp << "element face " << map.template nb_cells() << std::endl ; fp << "property list uint uint vertex_indices" << std::endl ; fp << "end_header" << std::endl ; @@ -559,12 +575,12 @@ bool export_ply(MAP& map, const typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); + typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); ids.set_all_container_values(UINT_MAX); unsigned int count = 0; - map.template foreach_cell([&] (typename MAP::Face f) + map.template foreach_cell([&] (Face f) { - map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) + map.template foreach_incident_vertex(f, [&] (Vertex v) { if (ids[v]==UINT_MAX) { @@ -578,12 +594,12 @@ bool export_ply(MAP& map, const typename MAP::template VertexAttributeHandler prim; prim.reserve(20); - map.template foreach_cell([&] (typename MAP::Face f) + map.template foreach_cell([&] (Face f) { unsigned int valence = 0; prim.clear(); - map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) + map.template foreach_incident_vertex(f, [&] (Vertex v) { prim.push_back(ids[v]); ++valence; @@ -619,18 +635,18 @@ bool export_ply_bin(MAP& map, const typename MAP::template VertexAttributeHandle fp << "comment File generated by the CGoGN library" << std::endl ; fp << "comment See : http://cgogn.unistra.fr/" << std::endl ; fp << "comment or contact : cgogn@unistra.fr" << std::endl ; - fp << "element vertex " << map.template nb_cells() << std::endl ; + fp << "element vertex " << map.template nb_cells() << std::endl ; fp << "property " << nameOfTypePly(position[0][0]) << " x" << std::endl ; fp << "property " << nameOfTypePly(position[0][1]) << " y" << std::endl ; fp << "property " << nameOfTypePly(position[0][2]) << " z" << std::endl ; - fp << "element face " << map.template nb_cells() << std::endl ; + fp << "element face " << map.template nb_cells() << std::endl ; fp << "property list uint uint vertex_indices" << std::endl ; fp << "end_header" << std::endl ; // two pass of traversal to avoid huge buffer (with same performance); // first pass to save positions & store contiguous indices - typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); + typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); ids.set_all_container_values(UINT_MAX); @@ -641,9 +657,9 @@ bool export_ply_bin(MAP& map, const typename MAP::template VertexAttributeHandle std::vector buffer_pos; buffer_pos.reserve(BUFFER_SZ); - map.template foreach_cell([&] (typename MAP::Face f) + map.template foreach_cell([&] (Face f) { - map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) + map.template foreach_incident_vertex(f, [&] (Vertex v) { if (ids[v]==UINT_MAX) { @@ -671,12 +687,12 @@ bool export_ply_bin(MAP& map, const typename MAP::template VertexAttributeHandle std::vector prim; prim.reserve(20); - map.template foreach_cell([&] (typename MAP::Face f) + map.template foreach_cell([&] (Face f) { unsigned int valence = 0; prim.clear(); - map.template foreach_incident_vertex(f, [&] (typename MAP::Vertex v) + map.template foreach_incident_vertex(f, [&] (Vertex v) { prim.push_back(ids[v]); ++valence; From feb6289ffc8dff0df9c8e41b5e49aab9c7db4e97 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Tue, 15 Mar 2016 14:48:26 +0100 Subject: [PATCH 317/402] efficient topo rendering --- cgogn/core/cmap/cmap3.h | 29 +- cgogn/geometry/algos/ear_triangulation.h | 8 +- cgogn/rendering/CMakeLists.txt | 2 + cgogn/rendering/examples/CMakeLists.txt | 3 +- cgogn/rendering/examples/viewer_topo.cpp | 21 +- cgogn/rendering/examples/viewer_topo3.cpp | 226 ++++++++++++++++ cgogn/rendering/map_render.h | 179 ++++++++++++ cgogn/rendering/shaders/shader_program.h | 4 +- .../rendering/shaders/shader_round_point.cpp | 13 +- cgogn/rendering/shaders/shader_round_point.h | 2 +- .../rendering/shaders/shader_simple_color.cpp | 4 +- cgogn/rendering/shaders/shader_simple_color.h | 2 +- cgogn/rendering/topo_render.cpp | 122 +++++++++ cgogn/rendering/topo_render.h | 256 ++++++++++++++++++ 14 files changed, 844 insertions(+), 27 deletions(-) create mode 100644 cgogn/rendering/examples/viewer_topo3.cpp create mode 100644 cgogn/rendering/topo_render.cpp create mode 100644 cgogn/rendering/topo_render.h diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 257af27f..a399eb19 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -304,6 +304,16 @@ class CMap3_T : public CMap2_T return Inherit::degree(Face2(f.dart)); } + inline bool has_degree(Face f, unsigned int degree) const + { + return Inherit::has_degree(Face2(f.dart), degree); + } + + inline bool has_degree(Face2 f, unsigned int degree) const + { + return Inherit::has_degree(f, degree); + } + protected: /******************************************************************************* @@ -553,6 +563,7 @@ class CMap3_T : public CMap2_T foreach_dart_of_orbit(Face2(f.dart), [&func] (Dart v) { func(Vertex(v)); }); } + template inline void foreach_incident_edge(Face f, const FUNC& func) const { @@ -572,21 +583,33 @@ class CMap3_T : public CMap2_T inline void foreach_incident_vertex(Volume v, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); - Inherit::foreach_incident_vertex(v, func); +// Inherit::foreach_incident_vertex(v, func); + Inherit::foreach_incident_vertex(v, [&func] (Vertex2 ve) + { + func(Vertex(ve.dart)); + }); } template inline void foreach_incident_edge(Volume v, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); - Inherit::foreach_incident_edge(v, func); +// Inherit::foreach_incident_edge(v, func); + Inherit::foreach_incident_face(v, [&func] (Edge2 e) + { + func(Edge(e.dart)); + }); } template inline void foreach_incident_face(Volume v, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); - Inherit::foreach_incident_face(v, func); +// Inherit::foreach_incident_face(v, func); + Inherit::foreach_incident_face(v, [&func] (Face2 f) + { + func(Face(f.dart)); + }); } /******************************************************************************* diff --git a/cgogn/geometry/algos/ear_triangulation.h b/cgogn/geometry/algos/ear_triangulation.h index 7c0672cf..f6e2d384 100644 --- a/cgogn/geometry/algos/ear_triangulation.h +++ b/cgogn/geometry/algos/ear_triangulation.h @@ -223,7 +223,7 @@ class EarTriangulation * @param f the face to tringulate * @param position attribute of position to use */ - EarTriangulation(MAP& map, Cell f, const typename MAP::template VertexAttributeHandler& position): + EarTriangulation(MAP& map, typename MAP::Face f, const typename MAP::template VertexAttributeHandler& position): map_(map), positions_(position), ears_(cmp_VP) @@ -236,7 +236,7 @@ class EarTriangulation } // compute normals for orientation - normalPoly_ = geometry::face_normal(map_,f,position); + normalPoly_ = geometry::face_normal(map_,Cell(f.dart),position); // first pass create polygon in chained list with angle computation VertexPoly* vpp = nullptr; @@ -393,7 +393,7 @@ class EarTriangulation * @param table_indices table of indices (vertex embedding) to fill (append) */ template -static void compute_ear_triangulation(MAP& map, Cell f, const typename MAP::template VertexAttributeHandler& position, std::vector& table_indices) +static void compute_ear_triangulation(MAP& map, typename MAP::Face f, const typename MAP::template VertexAttributeHandler& position, std::vector& table_indices) { EarTriangulation tri(map, f, position); tri.compute_indices(table_indices); @@ -406,7 +406,7 @@ static void compute_ear_triangulation(MAP& map, Cell f, const typen * @param position */ template -static void apply_ear_triangulation(MAP& map, Cell f, const typename MAP::template VertexAttributeHandler& position) +static void apply_ear_triangulation(MAP& map,typename MAP::Face f, const typename MAP::template VertexAttributeHandler& position) { EarTriangulation tri(map, f, position); tri.triangulate(); diff --git a/cgogn/rendering/CMakeLists.txt b/cgogn/rendering/CMakeLists.txt index a7f10a95..c4b82ee6 100644 --- a/cgogn/rendering/CMakeLists.txt +++ b/cgogn/rendering/CMakeLists.txt @@ -19,6 +19,7 @@ set(HEADER_FILES shaders/shader_round_point.h shaders/shader_point_sprite.h drawer.h + topo_render.h ) set(SOURCE_FILES @@ -32,6 +33,7 @@ set(SOURCE_FILES shaders/shader_round_point.cpp shaders/shader_point_sprite.cpp drawer.cpp + topo_render.cpp ) add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) diff --git a/cgogn/rendering/examples/CMakeLists.txt b/cgogn/rendering/examples/CMakeLists.txt index 770502d2..44bc8f1e 100644 --- a/cgogn/rendering/examples/CMakeLists.txt +++ b/cgogn/rendering/examples/CMakeLists.txt @@ -28,6 +28,7 @@ add_executable(picking_viewer picking_viewer.cpp) target_link_libraries(picking_viewer cgogn_core cgogn_io cgogn_rendering QOGLViewer) - +add_executable(viewer_topo3 viewer_topo3.cpp) +target_link_libraries(viewer_topo3 cgogn_core cgogn_io cgogn_rendering QOGLViewer) diff --git a/cgogn/rendering/examples/viewer_topo.cpp b/cgogn/rendering/examples/viewer_topo.cpp index be14bb61..ab9078e0 100644 --- a/cgogn/rendering/examples/viewer_topo.cpp +++ b/cgogn/rendering/examples/viewer_topo.cpp @@ -37,6 +37,10 @@ #include #include +#include + +#include + #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) using Map2 = cgogn::CMap2; @@ -67,10 +71,12 @@ class Viewer : public QOGLViewer VertexAttributeHandler vertex_position_; cgogn::geometry::BoundingBox bb_; + cgogn::rendering::MapRender* render_; cgogn::rendering::VBO* vbo_pos_; cgogn::rendering::ShaderFlat* shader_flat_; - cgogn::rendering::Drawer* drawer_topo; + + cgogn::rendering::TopoRender* topo_render; bool flat_rendering_; bool topo_rendering_; @@ -105,7 +111,7 @@ void Viewer::closeEvent(QCloseEvent*) delete render_; delete vbo_pos_; delete shader_flat_; - delete drawer_topo; + delete topo_render; } Viewer::Viewer() : @@ -115,7 +121,7 @@ Viewer::Viewer() : render_(nullptr), vbo_pos_(nullptr), shader_flat_(nullptr), - drawer_topo(nullptr), + topo_render(nullptr), flat_rendering_(true), topo_rendering_(true) {} @@ -159,7 +165,9 @@ void Viewer::draw() } if (topo_rendering_) - drawer_topo->call_list(proj,view); + { + topo_render->draw(proj,view); + } } @@ -171,6 +179,7 @@ void Viewer::init() cgogn::rendering::update_vbo(vertex_position_, *vbo_pos_); + render_ = new cgogn::rendering::MapRender(); render_->init_primitives(map_, cgogn::rendering::TRIANGLES, vertex_position_); @@ -183,8 +192,8 @@ void Viewer::init() shader_flat_->set_ambiant_color(QColor(5,5,5)); shader_flat_->release(); - drawer_topo = new cgogn::rendering::Drawer(this); - cgogn::rendering::create_drawer_topo2(map_,vertex_position_,*drawer_topo); + topo_render = new cgogn::rendering::TopoRender(this); + topo_render->update_map2(map_,vertex_position_); } int main(int argc, char** argv) diff --git a/cgogn/rendering/examples/viewer_topo3.cpp b/cgogn/rendering/examples/viewer_topo3.cpp new file mode 100644 index 00000000..3f6ebdac --- /dev/null +++ b/cgogn/rendering/examples/viewer_topo3.cpp @@ -0,0 +1,226 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#include +#include + +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#include + +#define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) + +using Map3 = cgogn::CMap3; +using Vec3 = Eigen::Vector3d; +//using Vec3 = cgogn::geometry::Vec_T>; + +template +using VertexAttributeHandler = Map3::VertexAttributeHandler; + + +class Viewer : public QOGLViewer +{ +public: + Viewer(); + Viewer(const Viewer&) = delete; + Viewer& operator=(const Viewer&) = delete; + + virtual void draw(); + virtual void init(); + + virtual void keyPressEvent(QKeyEvent *); + void import(const std::string& volumeMesh); + virtual ~Viewer(); + virtual void closeEvent(QCloseEvent *e); + +private: + Map3 map_; + VertexAttributeHandler vertex_position_; + + cgogn::geometry::BoundingBox bb_; + + cgogn::rendering::MapRender* render_; + cgogn::rendering::VBO* vbo_pos_; + cgogn::rendering::ShaderFlat* shader_flat_; + + cgogn::rendering::TopoRender* topo_render; + + bool flat_rendering_; + bool topo_rendering_; + +}; + + +// +// IMPLEMENTATION +// + + +void Viewer::import(const std::string& volumeMesh) +{ + cgogn::io::import_volume(map_, volumeMesh); + + vertex_position_ = map_.get_attribute("position"); + + cgogn::geometry::compute_bounding_box(vertex_position_, bb_); + + setSceneRadius(bb_.diag_size()/2.0); + Vec3 center = bb_.center(); + setSceneCenter(qoglviewer::Vec(center[0], center[1], center[2])); + showEntireScene(); +} + +Viewer::~Viewer() +{} + +void Viewer::closeEvent(QCloseEvent*) +{ + delete render_; + delete vbo_pos_; + delete shader_flat_; + delete topo_render; +} + +Viewer::Viewer() : + map_(), + vertex_position_(), + bb_(), + render_(nullptr), + vbo_pos_(nullptr), + shader_flat_(nullptr), + topo_render(nullptr), + flat_rendering_(true), + topo_rendering_(true) +{} + +void Viewer::keyPressEvent(QKeyEvent *ev) +{ + switch (ev->key()) { + case Qt::Key_F: + flat_rendering_ = !flat_rendering_; + break; + case Qt::Key_T: + topo_rendering_ = !topo_rendering_; + break; + default: + break; + } + // enable QGLViewer keys + QOGLViewer::keyPressEvent(ev); + //update drawing + update(); +} + +void Viewer::draw() +{ + QMatrix4x4 proj; + QMatrix4x4 view; + camera()->getProjectionMatrix(proj); + camera()->getModelViewMatrix(view); + + if (flat_rendering_) + { + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1.0f, 1.0f); + shader_flat_->bind(); + shader_flat_->set_matrices(proj,view); + shader_flat_->bind_vao(0); + render_->draw(cgogn::rendering::TRIANGLES); + shader_flat_->release_vao(0); + shader_flat_->release(); + glDisable(GL_POLYGON_OFFSET_FILL); + } + + if (topo_rendering_) + { + topo_render->draw(proj,view); + } + +} + +void Viewer::init() +{ + glClearColor(0.1f,0.1f,0.3f,0.0f); + + vbo_pos_ = new cgogn::rendering::VBO(3); + cgogn::rendering::update_vbo(vertex_position_, *vbo_pos_); + + + + render_ = new cgogn::rendering::MapRender(); +// render_->init_primitives(map_, cgogn::rendering::TRIANGLES, vertex_position_); + + shader_flat_ = new cgogn::rendering::ShaderFlat; + shader_flat_->add_vao(); + shader_flat_->set_vao(0, vbo_pos_); + shader_flat_->bind(); + shader_flat_->set_front_color(QColor(0,150,0)); + shader_flat_->set_back_color(QColor(0,0,150)); + shader_flat_->set_ambiant_color(QColor(5,5,5)); + shader_flat_->release(); + + topo_render = new cgogn::rendering::TopoRender(this); +// topo_render->update_map3(map_,vertex_position_); + + cgogn::Cell f(*(map_.begin())); + Vec3 normal = cgogn::geometry::face_normal(map_,f, vertex_position_); + +} + +int main(int argc, char** argv) +{ + std::string volumeMesh; + if (argc < 2) + { + std::cout << "USAGE: " << argv[0] << " [filename]" << std::endl; + volumeMesh = std::string(DEFAULT_MESH_PATH) + std::string("liverHexa.vtu"); + std::cout << "Using default mesh : " << volumeMesh << std::endl; + } + else + volumeMesh = std::string(argv[1]); + + QApplication application(argc, argv); + qoglviewer::init_ogl_context(); + + // Instantiate the viewer. + Viewer viewer; + viewer.setWindowTitle("simpleViewer"); + viewer.import(volumeMesh); + viewer.show(); + + // Run main loop. + return application.exec(); +} diff --git a/cgogn/rendering/map_render.h b/cgogn/rendering/map_render.h index f7eb40b4..0757cfa9 100644 --- a/cgogn/rendering/map_render.h +++ b/cgogn/rendering/map_render.h @@ -32,6 +32,8 @@ #include #include +#include + namespace cgogn { @@ -336,6 +338,183 @@ void add_volume_to_drawer(MAP& m, typename MAP::Volume vo, const typename MAP::t } +template +class Topo2Render +{ + VBO& vbo_topo_; + +}; + +template +void create_topo2(MAP& m, const typename MAP::template VertexAttributeHandler& position, VBO& vbo_topo) +{ + using Vertex = typename MAP::Vertex; + using Face = typename MAP::Face; + using Scalar = typename VEC3::Scalar; + + const Scalar expl1 = 0.95; + const Scalar expl2 = 0.85; + + const Scalar opp_expl1 = 1.0 -expl1; + const Scalar opp_expl2 = 1.0 - expl2; + + std::vector> out_pos; + out_pos.reserve(1024*1024); + + std::vector> out_pos2; + out_pos2.reserve(1024*1024); + + + std::vector local_vertices; + local_vertices.reserve(256); + + m.foreach_cell([&] (Face f) + { + local_vertices.clear(); + VEC3 center; + center.setZero(); + unsigned int count = 0u; + m.foreach_incident_vertex(f, [&] (Vertex v) + { + local_vertices.push_back(position[v]); + center += position[v]; + count++; + }); + center /= Scalar(count); + + // phi2 mid-edge: N -> 2N-1 + for (unsigned int i=0; i N-1 + for (unsigned int i=0; i 3N-1 + for (unsigned int i=0; i 4N-1 + for (unsigned int i=0; i +//void create_topo2(MAP& m, const typename MAP::template VertexAttributeHandler& position, VBO& vbo_topo) +//{ +// using Vertex = typename MAP::Vertex; +// using Face = typename MAP::Face; +// using Scalar = typename VEC3::Scalar; + +// const Scalar expl1 = 0.95; +// const Scalar expl2 = 0.85; + +// const Scalar opp_expl1 = 1.0 -expl1; +// const Scalar opp_expl2 = 1.0 - expl2; + +// using BufferVBO = std::vector>; + +// std::vector out_pos; +// out_pos.resize(cgogn::get_nb_threads()-1); +// for(auto& b: out_pos) +// b.reserve(1024*1024); + +// std::vector out_pos2; +// out_pos2.resize(cgogn::get_nb_threads()-1); +// for(auto& b: out_pos2) +// b.reserve(1024*1024); + + +// std::vector> thr_local_vertices; +// thr_local_vertices.resize(cgogn::get_nb_threads()-1); +// for(auto& b: thr_local_vertices) +// b.reserve(256); + +// m.parallel_foreach_cell([&] (Face f, unsigned int thr) +// { +// std::vector& local_vertices = thr_local_vertices[thr]; +// local_vertices.clear(); +// VEC3 center; +// center.setZero(); +// unsigned int count = 0u; +// m.foreach_incident_vertex(f, [&] (Vertex v) +// { +// local_vertices.push_back(position[v]); +// center += position[v]; +// count++; +// }); +// center /= Scalar(count); + +// // phi2 mid-edge: N -> 2N-1 +// for (unsigned int i=0; i N-1 +// for (unsigned int i=0; i 3N-1 +// for (unsigned int i=0; i 4N-1 +// for (unsigned int i=0; icreate(); return static_cast(vaos_.size() - 1); } @@ -88,7 +88,7 @@ class CGOGN_RENDERING_API ShaderProgram : protected QOpenGLFunctions_3_3_Core void alloc_vao(unsigned int nb) { while (vaos_.size() < nb) - vaos_.emplace_back(new QOpenGLVertexArrayObject); + vaos_.push_back(new QOpenGLVertexArrayObject); } /** diff --git a/cgogn/rendering/shaders/shader_round_point.cpp b/cgogn/rendering/shaders/shader_round_point.cpp index ab9f44d8..b9a18359 100644 --- a/cgogn/rendering/shaders/shader_round_point.cpp +++ b/cgogn/rendering/shaders/shader_round_point.cpp @@ -149,7 +149,6 @@ ShaderRoundPoint::ShaderRoundPoint(bool color_per_vertex) prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); prg_.bindAttributeLocation("vertex_color", ATTRIB_COLOR); prg_.link(); - get_matrices_uniforms(); } else { @@ -158,9 +157,9 @@ ShaderRoundPoint::ShaderRoundPoint(bool color_per_vertex) prg_.addShaderFromSourceCode(QOpenGLShader::Fragment, fragment_shader_source_); prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); prg_.link(); - - get_matrices_uniforms(); } + + get_matrices_uniforms(); unif_color_ = prg_.uniformLocation("color"); unif_width_ = prg_.uniformLocation("pointSizes"); @@ -172,7 +171,7 @@ ShaderRoundPoint::ShaderRoundPoint(bool color_per_vertex) void ShaderRoundPoint::set_color(const QColor& rgb) { - if (unif_color_) + if (unif_color_>=0) prg_.setUniformValue(unif_color_, rgb); } @@ -185,7 +184,7 @@ void ShaderRoundPoint::set_width(float wpix) prg_.setUniformValue(unif_width_, wd); } -bool ShaderRoundPoint::set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color) +bool ShaderRoundPoint::set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color, unsigned int stride, unsigned first) { if (i >= vaos_.size()) { @@ -201,7 +200,7 @@ bool ShaderRoundPoint::set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color) // position vbo vbo_pos->bind(); ogl->glEnableVertexAttribArray(ATTRIB_POS); - ogl->glVertexAttribPointer(ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + ogl->glVertexAttribPointer(ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, stride*vbo_pos->vector_dimension()*4, reinterpret_cast(first*vbo_pos->vector_dimension()*4)); vbo_pos->release(); if (vbo_color) @@ -209,7 +208,7 @@ bool ShaderRoundPoint::set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color) // color vbo vbo_color->bind(); ogl->glEnableVertexAttribArray(ATTRIB_COLOR); - ogl->glVertexAttribPointer(ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + ogl->glVertexAttribPointer(ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, stride*vbo_pos->vector_dimension()*4, reinterpret_cast(first*vbo_pos->vector_dimension()*4)); vbo_color->release(); } diff --git a/cgogn/rendering/shaders/shader_round_point.h b/cgogn/rendering/shaders/shader_round_point.h index 1590ec54..85137431 100644 --- a/cgogn/rendering/shaders/shader_round_point.h +++ b/cgogn/rendering/shaders/shader_round_point.h @@ -77,7 +77,7 @@ class CGOGN_RENDERING_API ShaderRoundPoint : public ShaderProgram * @param vbo_color pointer on color vbo * @return true if ok */ - bool set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color=NULL); + bool set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color=NULL, unsigned int stride=0, unsigned first=0); }; } // namespace rendering diff --git a/cgogn/rendering/shaders/shader_simple_color.cpp b/cgogn/rendering/shaders/shader_simple_color.cpp index 5f06f895..1d0c06e0 100644 --- a/cgogn/rendering/shaders/shader_simple_color.cpp +++ b/cgogn/rendering/shaders/shader_simple_color.cpp @@ -72,7 +72,7 @@ void ShaderSimpleColor::set_color(const QColor& rgb) prg_.setUniformValue(unif_color_, rgb); } -bool ShaderSimpleColor::set_vao(unsigned int i, VBO* vbo_pos) +bool ShaderSimpleColor::set_vao(unsigned int i, VBO* vbo_pos, unsigned int stride, unsigned first) { if (i >= vaos_.size()) { @@ -88,7 +88,7 @@ bool ShaderSimpleColor::set_vao(unsigned int i, VBO* vbo_pos) // position vbo vbo_pos->bind(); ogl->glEnableVertexAttribArray(ATTRIB_POS); - ogl->glVertexAttribPointer(ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + ogl->glVertexAttribPointer(ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE,stride*vbo_pos->vector_dimension()*4, reinterpret_cast(first*vbo_pos->vector_dimension()*4)); vbo_pos->release(); vaos_[i]->release(); diff --git a/cgogn/rendering/shaders/shader_simple_color.h b/cgogn/rendering/shaders/shader_simple_color.h index 50ac3e76..2e8a5ad2 100644 --- a/cgogn/rendering/shaders/shader_simple_color.h +++ b/cgogn/rendering/shaders/shader_simple_color.h @@ -64,7 +64,7 @@ class CGOGN_RENDERING_API ShaderSimpleColor : public ShaderProgram * @param vbo_pos pointer on position vbo (XYZ) * @return true if ok */ - bool set_vao(unsigned int i, VBO* vbo_pos); + bool set_vao(unsigned int i, VBO* vbo_pos, unsigned int stride=0, unsigned first=0); }; } // namespace rendering diff --git a/cgogn/rendering/topo_render.cpp b/cgogn/rendering/topo_render.cpp new file mode 100644 index 00000000..400a2c95 --- /dev/null +++ b/cgogn/rendering/topo_render.cpp @@ -0,0 +1,122 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#define CGOGN_RENDERING_DLL_EXPORT + +#include + +#include +#include +#include + +namespace cgogn +{ + +namespace rendering +{ + +// static members init +ShaderSimpleColor* TopoRender::shader_cpv_ = nullptr; +ShaderBoldLine* TopoRender::shader_bl_ = nullptr; +ShaderRoundPoint* TopoRender::shader_rp_ = nullptr; +int TopoRender::nb_instances_ = 0; + +TopoRender::TopoRender(QOpenGLFunctions_3_3_Core* ogl33): + ogl33_(ogl33), + dart_color_(255,255,255), + phi2_color_(255,0,0), + phi3_color_(255,255,0), + shrink_f_(0.8f), + shrink_e_(0.9f) +{ + nb_instances_++; + + vbo_topo_ = new cgogn::rendering::VBO(3); + + if (!shader_bl_) + shader_bl_ = new ShaderBoldLine(); + vao_bl_ = shader_bl_->add_vao(); + shader_bl_->set_vao(vao_bl_,vbo_topo_); + + if (!shader_rp_) + shader_rp_ = new ShaderRoundPoint(); + vao_rp_ = shader_rp_->add_vao(); + shader_rp_->set_vao(vao_rp_,vbo_topo_,nullptr,2,0); + +} + +TopoRender::~TopoRender() +{ + delete vbo_topo_; + + nb_instances_--; + if (nb_instances_ ==0) + { + // delete shaders when last TopoRender is deleted + // ensure context still enable when delete shaders + delete shader_rp_; + delete shader_bl_; + delete shader_cpv_; + } +} + +void TopoRender::draw(const QMatrix4x4& projection, const QMatrix4x4& modelview, bool with_blending) +{ + unsigned int lw = 2.0; + if(with_blending) + { + ogl33_->glEnable(GL_BLEND); + ogl33_->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + lw = 3.0; + } + + shader_rp_->bind(); + shader_rp_->set_matrices(projection,modelview); + shader_rp_->set_width(2*lw); + shader_rp_->set_color(dart_color_); + shader_rp_->bind_vao(vao_rp_); + ogl33_->glDrawArrays(GL_POINTS,0,vbo_topo_->size()/4); + shader_rp_->release_vao(vao_rp_); + shader_rp_->release(); + + shader_bl_->bind(); + shader_bl_->set_matrices(projection,modelview); + shader_bl_->bind_vao(vao_bl_); + shader_bl_->set_width(lw); + shader_bl_->set_color(dart_color_); + ogl33_->glDrawArrays(GL_LINES,0,vbo_topo_->size()/2); + shader_bl_->set_color(phi2_color_); + ogl33_->glDrawArrays(GL_LINES,vbo_topo_->size()/2,vbo_topo_->size()/2); + shader_bl_->release_vao(vao_bl_); + shader_bl_->release(); + + ogl33_->glDisable(GL_BLEND); + +} + + + + +} // namespace rendering + +} // namespace cgogn diff --git a/cgogn/rendering/topo_render.h b/cgogn/rendering/topo_render.h new file mode 100644 index 00000000..d766778c --- /dev/null +++ b/cgogn/rendering/topo_render.h @@ -0,0 +1,256 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef RENDERING_TOPO_RENDER_H_ +#define RENDERING_TOPO_RENDER_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace cgogn +{ + +namespace rendering +{ + + +class CGOGN_RENDERING_API TopoRender +{ + using Vec3f = std::array; + +protected: + + static ShaderSimpleColor* shader_cpv_; + static ShaderBoldLine* shader_bl_; + static ShaderRoundPoint* shader_rp_; + static int nb_instances_; + + VBO* vbo_topo_; + + unsigned int vao_bl_; + unsigned int vao_rp_; + + QOpenGLFunctions_3_3_Core* ogl33_; + + + QColor dart_color_; + QColor phi2_color_; + QColor phi3_color_; + + float shrink_v_; + float shrink_f_; + float shrink_e_; + +public: + + /** + * constructor, init all buffers (data and OpenGL) and shader + * @Warning need OpenGL context + */ + TopoRender(QOpenGLFunctions_3_3_Core* ogl33); + + /** + * release buffers and shader + */ + ~TopoRender(); + + template + void update_map2(MAP& m, const typename MAP::template VertexAttributeHandler& position); + + template + void update_map3(MAP& m, const typename MAP::template VertexAttributeHandler& position); + + + void draw(const QMatrix4x4& projection, const QMatrix4x4& modelview, bool with_blending=true); +}; + +template +void TopoRender::update_map2(MAP& m, const typename MAP::template VertexAttributeHandler& position) +{ + using Vertex = typename MAP::Vertex; + using Face = typename MAP::Face; + using Scalar = typename VEC3::Scalar; + + Scalar opp_shrink_e = 1.0 -shrink_e_; + Scalar opp_shrink_f = 1.0 - shrink_f_; + + std::vector> out_pos; + out_pos.reserve(1024*1024); + + std::vector> out_pos2; + out_pos2.reserve(1024*1024); + + + std::vector local_vertices; + local_vertices.reserve(256); + + m.foreach_cell([&] (Face f) + { + local_vertices.clear(); + VEC3 center; + center.setZero(); + unsigned int count = 0u; + m.foreach_incident_vertex(f, [&] (Vertex v) + { + local_vertices.push_back(position[v]); + center += position[v]; + count++; + }); + center /= Scalar(count); + + // phi2 mid-edge: N -> 2N-1 + for (unsigned int i=0; i N-1 + for (unsigned int i=0; i 3N-1 + for (unsigned int i=0; i 4N-1 + for (unsigned int i=0; iallocate(nbvec*2,3); + vbo_topo_->bind(); + vbo_topo_->copy_data(0, nbvec*12, out_pos[0].data()); + vbo_topo_->copy_data(nbvec*12, nbvec*12, out_pos2[0].data()); + vbo_topo_->bind(); + +} + + +template +void TopoRender::update_map3(MAP& m, const typename MAP::template VertexAttributeHandler& position) +{ + using Vertex = typename MAP::Vertex; + using Face = typename MAP::Face; + using Volume = typename MAP::Volume; + using Scalar = typename VEC3::Scalar; + + Scalar opp_shrink_e = 1.0 -shrink_e_; + Scalar opp_shrink_f = 1.0 - shrink_f_; + Scalar opp_shrink_v = 1.0 - shrink_v_; + + std::vector> out_pos; + out_pos.reserve(1024*1024); + + std::vector> out_pos2; + out_pos2.reserve(1024*1024); + + + std::vector local_vertices; + local_vertices.reserve(256); + + m.foreach_cell([&] (Volume v) + { + VEC3 center_vol = geometry::centroid(m,v,position); + m.foreach_incident_face(v, [&] (Face f) + { + local_vertices.clear(); + VEC3 center; + center.setZero(); + unsigned int count = 0u; + m.foreach_incident_vertex(f, [&] (Vertex v) + { + local_vertices.push_back(position[v]); + center += position[v]; + count++; + }); + center /= Scalar(count); + + // phi2 mid-edge: N -> 2N-1 + for (unsigned int i=0; i 3N-1 + for (unsigned int i=0; i N-1 + for (unsigned int i=0; i 4N-1 + for (unsigned int i=0; i 5N-1 + for (unsigned int i=0; iallocate(nbvec*3,3); + vbo_topo_->bind(); + vbo_topo_->copy_data(0, nbvec*12, out_pos[0].data()); + vbo_topo_->copy_data(nbvec*12, nbvec*24, out_pos2[0].data()); + vbo_topo_->bind(); +} + +} // namespace rendering + +} // namespace cgogn + +#endif // RENDERING_TOPO_RENDER_H_ From 8e0aad41e11df6116e6bdef23745f54f1a35a220 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Tue, 15 Mar 2016 17:20:11 +0100 Subject: [PATCH 318/402] topo3 --- cgogn/core/cmap/cmap3.h | 77 +++++++++++++++++++++++ cgogn/rendering/examples/viewer_topo3.cpp | 10 ++- cgogn/rendering/topo_render.cpp | 36 ++++++++--- cgogn/rendering/topo_render.h | 55 +++++++++++----- 4 files changed, 145 insertions(+), 33 deletions(-) diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index e736ba65..3598e14e 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -611,6 +611,44 @@ class CMap3_T : public CMap2_T }); } + + // redeclare CMap2 hidden functions + template + inline void foreach_incident_edge(Vertex2 v, const FUNC& func) const + { + Inherit::foreach_incident_edge(v,func); + } + + template + inline void foreach_incident_face(Vertex2 v, const FUNC& func) const + { + Inherit::foreach_incident_face(v,func); + } + + template + inline void foreach_incident_vertex(Edge2 e, const FUNC& func) const + { + Inherit::foreach_incident_vertex(e,func); + } + + template + inline void foreach_incident_face(Edge2 e, const FUNC& func) const + { + Inherit::foreach_incident_face(e,func); + } + + template + inline void foreach_incident_vertex(Face2 f, const FUNC& func) const + { + Inherit::foreach_incident_vertex(f,func); + } + + template + inline void foreach_incident_edge(Face2 f, const FUNC& func) const + { + Inherit::foreach_incident_edge(f,func); + } + /******************************************************************************* * Adjacence traversal *******************************************************************************/ @@ -829,8 +867,47 @@ class CMap3_T : public CMap2_T }); }); } + + //redeclare CMap2 hidden functions + template + inline void foreach_adjacent_vertex_through_edge(Vertex2 v, const FUNC& func) const + { + Inherit::foreach_adjacent_vertex_through_edge(v,func); + } + + template + inline void foreach_adjacent_vertex_through_face(Vertex2 v, const FUNC& func) const + { + Inherit::foreach_adjacent_vertex_through_face(v,func); + } + + template + inline void foreach_adjacent_edge_through_vertex(Edge2 e, const FUNC& func) const + { + Inherit::foreach_adjacent_edge_through_vertex(e,func); + } + + template + inline void foreach_adjacent_edge_through_face(Edge2 e, const FUNC& func) const + { + Inherit::foreach_adjacent_edge_through_face(e,func); + } + + template + inline void foreach_adjacent_face_through_vertex(Face2 f, const FUNC& func) const + { + Inherit::foreach_adjacent_face_through_vertex(f,func); + } + + template + inline void foreach_adjacent_face_through_edge(Face2 f, const FUNC& func) const + { + Inherit::foreach_adjacent_face_through_vertex(f,func); + } }; + + template struct CMap3Type { diff --git a/cgogn/rendering/examples/viewer_topo3.cpp b/cgogn/rendering/examples/viewer_topo3.cpp index 3f6ebdac..97324b23 100644 --- a/cgogn/rendering/examples/viewer_topo3.cpp +++ b/cgogn/rendering/examples/viewer_topo3.cpp @@ -181,22 +181,20 @@ void Viewer::init() render_ = new cgogn::rendering::MapRender(); -// render_->init_primitives(map_, cgogn::rendering::TRIANGLES, vertex_position_); + render_->init_primitives(map_, cgogn::rendering::TRIANGLES, vertex_position_); shader_flat_ = new cgogn::rendering::ShaderFlat; shader_flat_->add_vao(); shader_flat_->set_vao(0, vbo_pos_); shader_flat_->bind(); shader_flat_->set_front_color(QColor(0,150,0)); - shader_flat_->set_back_color(QColor(0,0,150)); + shader_flat_->set_back_color(QColor(0,150,0)); shader_flat_->set_ambiant_color(QColor(5,5,5)); shader_flat_->release(); topo_render = new cgogn::rendering::TopoRender(this); -// topo_render->update_map3(map_,vertex_position_); + topo_render->update_map3(map_,vertex_position_); - cgogn::Cell f(*(map_.begin())); - Vec3 normal = cgogn::geometry::face_normal(map_,f, vertex_position_); } @@ -206,7 +204,7 @@ int main(int argc, char** argv) if (argc < 2) { std::cout << "USAGE: " << argv[0] << " [filename]" << std::endl; - volumeMesh = std::string(DEFAULT_MESH_PATH) + std::string("liverHexa.vtu"); + volumeMesh = std::string(DEFAULT_MESH_PATH) + std::string("nine_hexas.vtu"); std::cout << "Using default mesh : " << volumeMesh << std::endl; } else diff --git a/cgogn/rendering/topo_render.cpp b/cgogn/rendering/topo_render.cpp index 400a2c95..a70de2f8 100644 --- a/cgogn/rendering/topo_render.cpp +++ b/cgogn/rendering/topo_render.cpp @@ -46,28 +46,33 @@ TopoRender::TopoRender(QOpenGLFunctions_3_3_Core* ogl33): dart_color_(255,255,255), phi2_color_(255,0,0), phi3_color_(255,255,0), - shrink_f_(0.8f), + shrink_v_(0.6f), + shrink_f_(0.85f), shrink_e_(0.9f) { nb_instances_++; - vbo_topo_ = new cgogn::rendering::VBO(3); + vbo_darts_ = new cgogn::rendering::VBO(3); + vbo_relations_ = new cgogn::rendering::VBO(3); if (!shader_bl_) shader_bl_ = new ShaderBoldLine(); vao_bl_ = shader_bl_->add_vao(); - shader_bl_->set_vao(vao_bl_,vbo_topo_); + shader_bl_->set_vao(vao_bl_,vbo_darts_); + vao_bl2_ = shader_bl_->add_vao(); + shader_bl_->set_vao(vao_bl2_,vbo_relations_); if (!shader_rp_) shader_rp_ = new ShaderRoundPoint(); vao_rp_ = shader_rp_->add_vao(); - shader_rp_->set_vao(vao_rp_,vbo_topo_,nullptr,2,0); + shader_rp_->set_vao(vao_rp_,vbo_darts_,nullptr,2,0); } TopoRender::~TopoRender() { - delete vbo_topo_; + delete vbo_darts_; + delete vbo_relations_; nb_instances_--; if (nb_instances_ ==0) @@ -95,19 +100,30 @@ void TopoRender::draw(const QMatrix4x4& projection, const QMatrix4x4& modelview, shader_rp_->set_width(2*lw); shader_rp_->set_color(dart_color_); shader_rp_->bind_vao(vao_rp_); - ogl33_->glDrawArrays(GL_POINTS,0,vbo_topo_->size()/4); + ogl33_->glDrawArrays(GL_POINTS,0,vbo_darts_->size()/2); shader_rp_->release_vao(vao_rp_); shader_rp_->release(); shader_bl_->bind(); shader_bl_->set_matrices(projection,modelview); - shader_bl_->bind_vao(vao_bl_); shader_bl_->set_width(lw); + + shader_bl_->bind_vao(vao_bl_); shader_bl_->set_color(dart_color_); - ogl33_->glDrawArrays(GL_LINES,0,vbo_topo_->size()/2); - shader_bl_->set_color(phi2_color_); - ogl33_->glDrawArrays(GL_LINES,vbo_topo_->size()/2,vbo_topo_->size()/2); + ogl33_->glDrawArrays(GL_LINES,0,vbo_darts_->size()); shader_bl_->release_vao(vao_bl_); + + shader_bl_->bind_vao(vao_bl2_); + shader_bl_->set_color(phi2_color_); + ogl33_->glDrawArrays(GL_LINES,0,vbo_darts_->size()); + + if (vbo_relations_->size() > vbo_darts_->size()) + { + shader_bl_->set_color(phi3_color_); + ogl33_->glDrawArrays(GL_LINES,vbo_darts_->size(),vbo_darts_->size()); + } + shader_bl_->release_vao(vao_bl2_); + shader_bl_->release(); ogl33_->glDisable(GL_BLEND); diff --git a/cgogn/rendering/topo_render.h b/cgogn/rendering/topo_render.h index d766778c..5d9ba4c0 100644 --- a/cgogn/rendering/topo_render.h +++ b/cgogn/rendering/topo_render.h @@ -52,9 +52,11 @@ class CGOGN_RENDERING_API TopoRender static ShaderRoundPoint* shader_rp_; static int nb_instances_; - VBO* vbo_topo_; + VBO* vbo_darts_; + VBO* vbo_relations_; unsigned int vao_bl_; + unsigned int vao_bl2_; unsigned int vao_rp_; QOpenGLFunctions_3_3_Core* ogl33_; @@ -154,12 +156,18 @@ void TopoRender::update_map2(MAP& m, const typename MAP::template VertexAttribut } }); + std::size_t nbvec = out_pos.size(); - vbo_topo_->allocate(nbvec*2,3); - vbo_topo_->bind(); - vbo_topo_->copy_data(0, nbvec*12, out_pos[0].data()); - vbo_topo_->copy_data(nbvec*12, nbvec*12, out_pos2[0].data()); - vbo_topo_->bind(); + vbo_darts_->allocate(nbvec,3); + vbo_darts_->bind(); + vbo_darts_->copy_data(0, nbvec*12, out_pos[0].data()); + vbo_darts_->release(); + + vbo_relations_->allocate(nbvec,3); + vbo_relations_->bind(); + vbo_relations_->copy_data(0, nbvec*12, out_pos2[0].data()); + vbo_relations_->release(); + } @@ -182,6 +190,9 @@ void TopoRender::update_map3(MAP& m, const typename MAP::template VertexAttribut std::vector> out_pos2; out_pos2.reserve(1024*1024); + std::vector> out_pos3; + out_pos3.reserve(1024*1024); + std::vector local_vertices; local_vertices.reserve(256); @@ -225,28 +236,38 @@ void TopoRender::update_map3(MAP& m, const typename MAP::template VertexAttribut for (unsigned int i=0; iallocate(nbvec*3,3); - vbo_topo_->bind(); - vbo_topo_->copy_data(0, nbvec*12, out_pos[0].data()); - vbo_topo_->copy_data(nbvec*12, nbvec*24, out_pos2[0].data()); - vbo_topo_->bind(); + vbo_darts_->allocate(nbvec,3); + vbo_darts_->bind(); + vbo_darts_->copy_data(0, nbvec*12, out_pos[0].data()); + vbo_darts_->release(); + + vbo_relations_->allocate(2*nbvec,3); + vbo_relations_->bind(); + vbo_relations_->copy_data(0, nbvec*12, out_pos2[0].data()); + vbo_relations_->copy_data(nbvec*12, nbvec*12, out_pos3[0].data()); + + vbo_relations_->release(); + + } } // namespace rendering From 44c822469b7bda954c7e0693e5b56a8480436052 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Tue, 15 Mar 2016 18:21:31 +0100 Subject: [PATCH 319/402] Correction of foreach_dart() iterator to cope with boudary_marker --- cgogn/core/cmap/cmap2.h | 25 +++++++-- cgogn/core/cmap/cmap2_builder.h | 7 +++ cgogn/core/cmap/map_base.h | 21 +++++--- cgogn/core/cmap/map_base_data.h | 4 +- cgogn/core/tests/cmap/cmap2_test.cpp | 66 ++++++++++++++--------- cgogn/core/tests/cmap/cmap2_topo_test.cpp | 28 ++++++---- 6 files changed, 105 insertions(+), 46 deletions(-) diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 475d93bc..76ce0421 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -142,11 +142,19 @@ class CMap2_T : public CMap1_T (*phi2_)[d.index] = d; } + /** + * @brief Check the integrity of a dart + * @param d the dart to check + * @return true if the integrity constraints are locally statisfied + * PHI2 should be an involution without fixed poit and + * the boundary marker is identical for all darts of a face. + */ inline bool check_integrity(Dart d) const { return (Inherit::check_integrity(d) && phi2(phi2(d)) == d && - phi2(d) != d); + phi2(d) != d && + ( this->is_boundary(d) == this->is_boundary(this->phi1(d)) )); } /** @@ -202,6 +210,8 @@ class CMap2_T : public CMap1_T * \brief Add a face in the map. * \param size : the number of darts in the built face * \return A dart of the built face. + * Two 1-face are built. The first one is the returned face, + * the second is a boundary face that closes the map. */ Dart add_face_topo(unsigned int size) { @@ -211,6 +221,7 @@ class CMap2_T : public CMap1_T Dart it = d; do { + this->set_boundary(e,true); phi2_sew(it, e); it = this->phi1(it); e = this->phi_1(e); @@ -293,6 +304,9 @@ class CMap2_T : public CMap1_T phi2_sew(d, ne); // Sew the new 1D-edges phi2_sew(e, nd); // To build the new 2D-edges + this->set_boundary(nd,this->is_boundary(d)); + this->set_boundary(ne,this->is_boundary(e)); + return nd; } @@ -356,13 +370,13 @@ class CMap2_T : public CMap1_T Dart e = this->phi_1(this->phi2(d)); cgogn_message_assert(d == this->phi_1(this->phi2(e)), "merge_adjacent_edge: the degree of the vertex of d should be 2"); -// TODO + // TODO } void merge_adjacent_faces_topo(Dart d) { Dart e = this->phi2(d); -// TODO + // TODO } protected: @@ -385,6 +399,9 @@ class CMap2_T : public CMap1_T Dart ne = Inherit::split_vertex_topo(ee); // cut the edge before e (insert a new dart before e) this->phi1_sew(dd, ee); // subdivide phi1 cycle at the inserted darts phi2_sew(nd, ne); // build the new 2D-edge from the inserted darts + + this->set_boundary(nd,this->is_boundary(dd)); + this->set_boundary(ne,this->is_boundary(ee)); } public: @@ -605,7 +622,7 @@ class CMap2_T : public CMap1_T * Incidence traversal *******************************************************************************/ - public: +public: template inline void foreach_incident_edge(Vertex v, const FUNC& func) const diff --git a/cgogn/core/cmap/cmap2_builder.h b/cgogn/core/cmap/cmap2_builder.h index 47676628..4ef794d2 100644 --- a/cgogn/core/cmap/cmap2_builder.h +++ b/cgogn/core/cmap/cmap2_builder.h @@ -89,6 +89,11 @@ class CMap2Builder_T map_.phi2_unsew(d); } + inline void set_boundary(Dart d, bool b) + { + map_.set_boundary(d, b); + } + inline Dart add_face_topo_parent(unsigned int nb_edges) { return map_.CMap2::Inherit::add_face_topo(nb_edges); @@ -106,6 +111,7 @@ class CMap2Builder_T cgogn_message_assert(map_.phi2(d) == d, "CMap2: close hole called on a dart that is not a phi2 fix point"); Dart first = map_.add_dart(); // First edge of the face that will fill the hole + set_boundary(first,true); map_.phi2_sew(d, first); // 2-sew the new edge to the hole Dart d_next = d; // Turn around the hole @@ -121,6 +127,7 @@ class CMap2Builder_T if (d_phi1 != d) { Dart next = map_.split_vertex_topo(first); // Add a vertex into the built face + set_boundary(next,true); phi2_sew(d_next, next); // and 2-sew the face to the hole } } while (d_phi1 != d); diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index fc2da05e..48cede6e 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -349,6 +349,8 @@ class MapBase : public MapBaseData [this] (Cell c) { new_orbit_embedding(c); }, [] (Dart) { return true; } ); + + cgogn_assert(check_map_integrity()); } template @@ -473,8 +475,7 @@ class MapBase : public MapBaseData // check the integrity of topological relations or the correct sewing of darts foreach_dart_until([&cmap, &result] (Dart d) { - if (!cmap->check_integrity(d)) - result = false; + result = cmap->check_integrity(d); return result; }); if (!result) @@ -625,16 +626,20 @@ class MapBase : public MapBaseData const Self& map_; const MASK& mask_; Dart dart_; + Dart end_; inline const_iterator(const Self& map, Dart d, const MASK& mask) : map_(map), dart_(d), mask_(mask) - {} + { + end_ = Dart(map_.topology_.end()); + } inline const_iterator(const const_iterator& it) : map_(it.map_), dart_(it.dart_), + end_(it.end_), mask_(it.mask_) {} @@ -642,17 +647,18 @@ class MapBase : public MapBaseData { map_ = it.map_; dart_ = it.dart_; + end_ = it.end_; mask_ = it.mask_; return *this; } inline const_iterator& operator++() { - const Dart end = Dart(map_.topology_.end()); + cgogn_assert(dart_.index < end_.index); do { map_.topology_.next(dart_.index); - } while (dart_ != end && !mask_(dart_)); + } while (dart_ != end_ && !mask_(dart_)); return *this; } @@ -664,12 +670,14 @@ class MapBase : public MapBaseData inline bool operator!=(const const_iterator& it) const { cgogn_assert(&map_ == &(it.map_)); + cgogn_assert(end_ == it.end_); return dart_ != it.dart_; } inline bool operator==(const const_iterator& it) const { cgogn_assert(&map_ == &(it.map_)); + cgogn_assert(end_ == it.end_); return dart_ == it.dart_; } }; @@ -678,7 +686,8 @@ class MapBase : public MapBaseData inline const_iterator begin(const MASK& mask) const { Dart d = Dart(this->topology_.begin()); - const Dart end = Dart(this->topology_.end()); + Dart end = Dart(this->topology_.end()); + while (d != end && !mask(d)) this->topology_.next(d.index); return const_iterator(*this, d, mask); diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index c1c14cf2..24ba6329 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -263,8 +263,8 @@ class MapBaseData : public MapGen { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); cgogn_message_assert(is_embedded(), "Invalid parameter: orbit not embedded"); - cgogn_message_assert((*embeddings_[ORBIT])[c.dart.index] != EMBNULL, "get_embedding result is EMBNULL"); - +// cgogn_message_assert((*embeddings_[ORBIT])[c.dart.index] != EMBNULL, "get_embedding result is EMBNULL"); + if ((*embeddings_[ORBIT])[c.dart.index] == EMBNULL) std::cerr << "EMBNULL pour " << orbit_name(ORBIT) << std::endl; return (*embeddings_[ORBIT])[c.dart.index]; } diff --git a/cgogn/core/tests/cmap/cmap2_test.cpp b/cgogn/core/tests/cmap/cmap2_test.cpp index 995c1d21..78df3ed0 100644 --- a/cgogn/core/tests/cmap/cmap2_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_test.cpp @@ -133,31 +133,49 @@ class CMap2Test : public ::testing::Test } } // Close the map (remove remaining boundary) - cmap_.foreach_dart([&] (Dart d) - { - if (cmap_.phi2(d) == d) mbuild.close_hole_topo(d); - }); + cmap_.foreach_dart( + [&] (Dart d) + { + if (cmap_.phi2(d) == d) mbuild.close_hole_topo(d); + }, + [this] (Dart d) { return true; } + ); // Embed the map - cmap_.foreach_dart([&] (Dart d) - { - mbuild.new_orbit_embedding(CDart(d)); - }); - cmap_.foreach_cell([&] (Vertex v) - { - mbuild.new_orbit_embedding(v); - }); - cmap_.foreach_cell([&] (Edge e) - { - mbuild.new_orbit_embedding(e); - }); - cmap_.foreach_cell([&] (Face f) - { - mbuild.new_orbit_embedding(f); - }); - cmap_.foreach_cell([&] (Volume w) - { - mbuild.new_orbit_embedding(w); - }); + cmap_.foreach_dart( + [&] (Dart d) + { + mbuild.new_orbit_embedding(CDart(d)); + }, + [this] (Dart d) { return true; } + ); + cmap_.foreach_cell( + [&] (Vertex v) + { + mbuild.new_orbit_embedding(v); + }, + [this] (Dart d) { return true; } + ); + cmap_.foreach_cell( + [&] (Edge e) + { + mbuild.new_orbit_embedding(e); + }, + [this] (Dart d) { return true; } + ); + cmap_.foreach_cell( + [&] (Face f) + { + mbuild.new_orbit_embedding(f); + }, + [this] (Dart d) { return true; } + ); + cmap_.foreach_cell( + [&] (Volume w) + { + mbuild.new_orbit_embedding(w); + }, + [this] (Dart d) { return true; } + ); } }; diff --git a/cgogn/core/tests/cmap/cmap2_topo_test.cpp b/cgogn/core/tests/cmap/cmap2_topo_test.cpp index cee9cc8d..3e27818b 100644 --- a/cgogn/core/tests/cmap/cmap2_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_topo_test.cpp @@ -242,14 +242,14 @@ TEST_F(CMap2TopoTest, add_face_topo) EXPECT_EQ(nb_darts(), 2u); EXPECT_EQ(nb_cells(), 1u); EXPECT_EQ(nb_cells(), 1u); - EXPECT_EQ(nb_cells(), 2u); + EXPECT_EQ(nb_cells(), 1u); EXPECT_EQ(nb_cells(), 1u); add_face_topo(10u); EXPECT_EQ(nb_darts(), 22u); EXPECT_EQ(nb_cells(), 11u); EXPECT_EQ(nb_cells(), 11u); - EXPECT_EQ(nb_cells(), 4u); + EXPECT_EQ(nb_cells(), 2u); EXPECT_EQ(nb_cells(), 2u); unsigned int count_vertices = 11u + add_faces(NB_MAX); @@ -257,7 +257,7 @@ TEST_F(CMap2TopoTest, add_face_topo) EXPECT_EQ(nb_darts(), 2u * count_vertices); EXPECT_EQ(nb_cells(), count_vertices); EXPECT_EQ(nb_cells(), count_vertices); - EXPECT_EQ(nb_cells(), 2u * (NB_MAX + 2u)); + EXPECT_EQ(nb_cells(), NB_MAX + 2u); EXPECT_EQ(nb_cells(), NB_MAX + 2u); EXPECT_TRUE(check_map_integrity()); } @@ -313,18 +313,26 @@ TEST_F(CMap2TopoTest, cut_face_topo) for (Dart d : darts_) { - unsigned int k = degree(Face(d)); + Dart dd = d; + if (std::rand() % 2 == 1) dd = phi2(d); + + bool boundary_face = is_boundary(dd); + + unsigned int k = degree(Face(dd)); if (k > 1u) { - Dart e = d; // find a second dart in the face of d (distinct from d) + Dart e = dd; // find a second dart in the face of d (distinct from d) unsigned int i = std::rand() % 10u; while (i-- > 0u) e = phi1(e); - if (e == d) e = phi1(e); + if (e == dd) e = phi1(e); + + cut_face_topo(dd, e); - cut_face_topo(d, e); - ++count_edges; - ++count_faces; - EXPECT_EQ(degree(Face(d)) + degree(Face(e)), k + 2); + if (!boundary_face) { + ++count_edges; + ++count_faces; + } + EXPECT_EQ(degree(Face(dd)) + degree(Face(e)), k + 2); } } EXPECT_EQ(nb_cells(), count_vertices); From 5fe9f7ea7b4cb79fbf821603571256a9f2d6eb30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 15 Mar 2016 19:13:11 +0100 Subject: [PATCH 320/402] added the CGOGN_FUNC macro. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It allows to get the function name both with msvc and gcc/clang. Signed-off-by: Étienne Schmitt --- cgogn/core/utils/definitions.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cgogn/core/utils/definitions.h b/cgogn/core/utils/definitions.h index 3b38cec3..dbf5ce38 100644 --- a/cgogn/core/utils/definitions.h +++ b/cgogn/core/utils/definitions.h @@ -86,6 +86,13 @@ #endif #endif +// macro for the function name +#if defined(_MSC_VER) +#define CGOGN_FUNC __FUNCTION__ +#else +#define CGOGN_FUNC __func__ +#endif + /** * \def CGOGN_DEBUG * \brief This macro is set when compiling in debug mode From b74d6d6dd667472722f7130a1e107d92ad096c03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 15 Mar 2016 19:16:04 +0100 Subject: [PATCH 321/402] Added the add_stamp method in cmap3. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A stamp is a connector between a face of degree 4 and one or two face(s) of degree 3. Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/cmap3.h | 23 +++++++++++++++++++++-- cgogn/core/cmap/cmap3_builder.h | 10 ++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 257af27f..664d11f1 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -264,11 +264,11 @@ class CMap3_T : public CMap2_T // creation of quads around circunference and storing vertices for (unsigned int i = 0u; i < n; ++i) - m_tableVertDarts.emplace_back(this->Inherit::Inherit::add_face_topo(4u)); + m_tableVertDarts.push_back(this->Inherit::Inherit::add_face_topo(4u)); // storing a dart from the vertex pointed by phi1(phi1(d)) for (unsigned int i = 0u; i < n; ++i) - m_tableVertDarts.emplace_back(this->phi1(this->phi1(m_tableVertDarts[i]))); + m_tableVertDarts.push_back(this->phi1(this->phi1(m_tableVertDarts[i]))); // sewing the quads for (unsigned int i = 0u; i < n-1u; ++i) @@ -296,6 +296,25 @@ class CMap3_T : public CMap2_T return dres; } + /** + * @brief add_stamp_volume_topo : a flat volume with one face composed of two triangles and another compose of one quad + * @return a dart of the quad + */ + Dart add_stamp_volume_topo() + { + const Dart d_quad = Inherit::Inherit::add_face_topo(4u); + const Dart d_tri1 = Inherit::Inherit::add_face_topo(3u); + const Dart d_tri2 = Inherit::Inherit::add_face_topo(3u); + + this->phi2_sew(d_tri1, d_tri2); + this->phi2_sew(d_quad, this->phi1(d_tri1)); + this->phi2_sew(this->phi1(d_quad), this->phi_1(d_tri2)); + this->phi2_sew(this->phi1(this->phi1(d_quad)), this->phi1(d_tri2)); + this->phi2_sew(this->phi_1(d_quad), this->phi_1(d_tri1)); + + return d_quad; + } + public: diff --git a/cgogn/core/cmap/cmap3_builder.h b/cgogn/core/cmap/cmap3_builder.h index aca59328..5f943b04 100644 --- a/cgogn/core/cmap/cmap3_builder.h +++ b/cgogn/core/cmap/cmap3_builder.h @@ -115,6 +115,16 @@ class CMap3Builder_T return map_.add_pyramid_topo(nb_edges); } + inline Dart add_stamp_volume_topo() + { + return map_.add_stamp_volume_topo(); + } + + template + inline void set_embedding(Dart d, unsigned int emb) + { + map_.template set_embedding(d, emb); + } inline void close_hole_topo(Dart d) { From 18a888549edfd603b18f4e47ee7239d9166f7e94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 15 Mar 2016 19:16:18 +0100 Subject: [PATCH 322/402] Fixed display of vec. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/geometry/types/vec.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cgogn/geometry/types/vec.h b/cgogn/geometry/types/vec.h index c3caa2ad..1e474a32 100644 --- a/cgogn/geometry/types/vec.h +++ b/cgogn/geometry/types/vec.h @@ -253,8 +253,9 @@ class Vec_T inline friend std::ostream& operator<<(std::ostream& o, const Self& v) { o << "("; - for (auto& c : v.data_) - o << c << ","; + for (std::size_t i = 0ul ; i < std::tuple_size::value -1ul; ++i ) + o << v.data_[i] << ","; + o << v.data_[std::tuple_size::value -1ul]; o << ")"; return o; } From 6b1c67ac58304880a638124c06dcf0bab0a70af8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 15 Mar 2016 19:17:23 +0100 Subject: [PATCH 323/402] lm6_import : using the add_cell utilitary methods. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/io_utils.cpp | 2 +- cgogn/io/lm6_io.h | 33 ++++++++++++++++++++------------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/cgogn/io/io_utils.cpp b/cgogn/io/io_utils.cpp index 4dd12079..a9e9ad76 100644 --- a/cgogn/io/io_utils.cpp +++ b/cgogn/io/io_utils.cpp @@ -219,7 +219,7 @@ CGOGN_IO_API FileType get_file_type(const std::string& filename) return FileType::FileType_VTU; if (extension == "vtp") return FileType::FileType_VTP; - if (extension == "meshb") + if (extension == "meshb" || extension == "mesh" ) return FileType::FileType_MESHB; return FileType::FileType_UNKNOWN; diff --git a/cgogn/io/lm6_io.h b/cgogn/io/lm6_io.h index 21a5d249..efb28cae 100644 --- a/cgogn/io/lm6_io.h +++ b/cgogn/io/lm6_io.h @@ -86,8 +86,11 @@ class LM6VolumeImport : public VolumeImport for (int i = 0 ; i < number_of_vertices; ++i) { unsigned int idx = this->vertex_attributes_.template insert_lines<1>(); - VEC3& v = position->operator [](idx); + std::array v; (void) GmfGetLin(mesh_index, GmfVertices, &v[0],&v[1], &v[2], &ref); + position->operator [](idx)[0] = v[0]; + position->operator [](idx)[1] = v[1]; + position->operator [](idx)[2] = v[2]; } if (number_of_tetras > 0) @@ -96,36 +99,38 @@ class LM6VolumeImport : public VolumeImport std::array ids; for (int i = 0 ; i < number_of_tetras; ++i) { - this->volumes_nb_vertices_.push_back(4); (void) GmfGetLin(mesh_index, GmfTetrahedra, &ids[0],&ids[1], &ids[2], &ids[3], &ref); - for (int x : ids) - this->volumes_vertex_indices_.push_back(static_cast(x)); + for (auto& id : ids) + --id; + this->add_tetra(*position, ids[0],ids[1], ids[2], ids[3], true); } } + if (number_of_hexas > 0) { GmfGotoKwd(mesh_index, GmfHexahedra); std::array ids; for (int i = 0 ; i < number_of_hexas; ++i) { - this->volumes_nb_vertices_.push_back(8); (void) GmfGetLin(mesh_index, GmfHexahedra, &ids[0],&ids[1], &ids[2], &ids[3], &ids[4], &ids[5], &ids[6], &ids[7], &ref); - for (int x : ids) - this->volumes_vertex_indices_.push_back(static_cast(x)); + for (auto& id : ids) + --id; + this->add_hexa(*position, ids[0],ids[1], ids[5], ids[4], ids[3],ids[2], ids[6], ids[7], false); } } + if (number_of_prisms > 0) { GmfGotoKwd(mesh_index, GmfPrisms); std::array ids; for (int i = 0 ; i < number_of_prisms; ++i) { - this->volumes_nb_vertices_.push_back(6); (void) GmfGetLin(mesh_index, GmfPrisms, &ids[0],&ids[1], &ids[2], &ids[3], &ids[4], &ids[5], &ref); - for (int x : ids) - this->volumes_vertex_indices_.push_back(static_cast(x)); + for (auto& id : ids) + --id; + this->add_triangular_prism(*position, ids[0],ids[1], ids[2], ids[3], ids[4],ids[5]); } } @@ -135,13 +140,15 @@ class LM6VolumeImport : public VolumeImport std::array ids; for (int i = 0 ; i < number_of_pyramids; ++i) { - this->volumes_nb_vertices_.push_back(5); (void) GmfGetLin(mesh_index, GmfPyramids, &ids[0],&ids[1], &ids[2], &ids[3], &ids[4], &ref); - for (int x : ids) - this->volumes_vertex_indices_.push_back(static_cast(x)); + for (auto& id : ids) + --id; + this->add_pyramid(*position, ids[0],ids[1], ids[2], ids[3], ids[4]); } } + + GmfCloseMesh(mesh_index); return true; } From 4f2d1ec11ea40b9877d348cef343505f3cffe8e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 15 Mar 2016 19:17:50 +0100 Subject: [PATCH 324/402] Fixed SurfaceImport -> VolumeImport. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/map_import.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cgogn/io/map_import.h b/cgogn/io/map_import.h index a8cf97cb..d8a3b5f7 100644 --- a/cgogn/io/map_import.h +++ b/cgogn/io/map_import.h @@ -103,7 +103,7 @@ inline std::unique_ptr > newVolumeImport(const std::str case FileType::FileType_VTU: return make_unique>(); case FileType::FileType_MESHB: return make_unique>(); default: - std::cerr << "SurfaceImport does not handle files with extension \"" << get_extension(filename) << "\"." << std::endl; + std::cerr << "VolumeImport does not handle files with extension \"" << get_extension(filename) << "\"." << std::endl; return std::unique_ptr> (); } } From 945a2043d322615ab9c5705dbb1debbaba83433d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 15 Mar 2016 19:26:07 +0100 Subject: [PATCH 325/402] Updated create_map function to deal with stamp volumes. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/volume_import.h | 157 ++++++++++++++++++++++++++++++++------- cgogn/io/vtk_io.h | 4 +- 2 files changed, 131 insertions(+), 30 deletions(-) diff --git a/cgogn/io/volume_import.h b/cgogn/io/volume_import.h index b472c3b6..6512e59c 100644 --- a/cgogn/io/volume_import.h +++ b/cgogn/io/volume_import.h @@ -249,44 +249,143 @@ class VolumeImport : public MeshImportGen } + // utilitary function + auto sew_volumes = [&mbuild,&map,&m](Dart w1, Dart w2) + { + const Dart w1_begin = w1; + do { + mbuild.phi3_sew(w1, w2); + w1 = map.phi1(w1); + w2 = map.phi_1(w2); + } while (w1_begin != w1); + }; + + //reconstruct neighbourhood - unsigned int nbBoundaryFaces = 0; + unsigned int nbBoundaryFaces = 0u; for (Dart d : map) { if (m.is_marked(d)) { - std::vector& vec = darts_per_vertex[Vertex(map.phi1(d))]; - Dart good_dart; - for(auto it = vec.begin(); it != vec.end() && good_dart.is_nil(); ++it) + + // 1st step : for every dart of the face we try to find a valid phi3 candidate. If we can't it's a boundary face. { - if(map.get_embedding(Vertex(map.phi1(*it))) == map.get_embedding(Vertex(d)) && - map.get_embedding(Vertex(map.phi_1(*it))) == map.get_embedding(Vertex(map.phi1(map.phi1(d))))) + Dart d_it = d; + do { - good_dart = *it; - } + const std::vector& vec = darts_per_vertex[Vertex(map.phi1(d_it))]; + for(auto it = vec.begin(); it != vec.end() && good_dart.is_nil(); ++it) + { + if(map.get_embedding(Vertex(map.phi1(*it))) == map.get_embedding(Vertex(d_it)) && + map.get_embedding(Vertex(map.phi_1(*it))) == map.get_embedding(Vertex(map.phi1(map.phi1(d_it))))) + { + good_dart = *it; + } + } + d_it = map.phi1(d_it); + } while (good_dart.is_nil() && (d_it != d)); + d = map.phi_1(d_it); } - if (!good_dart.is_nil()) + if (!good_dart.is_nil()) //not a boundary faces { const unsigned int degD = map.degree(Face(d)); const unsigned int degGD = map.degree(Face(good_dart)); - //std::cout << "degD = " << degD << " et degGD = " << degGD << std::endl; - if(degD == degGD) + if(degD == degGD) // normal case : the two opposite faces have the same degree { -// map.sew_volumes(d, good_dart, false); - Dart f1_it = d; - Dart f2_it = good_dart; - do { - mbuild.phi3_sew(f1_it, f2_it); - f1_it = map.phi1(f1_it); - f2_it = map.phi_1(f2_it); - } while (f1_it != d); + sew_volumes(d, good_dart); m.unmark_orbit(Face(d)); } - // else - // std::cout << "erreur : degD != degGD" << std::endl; + else + { + // there is one face of degree 4 and one face of degree 3. + if(degD > degGD) // face of d is quad + { + const Dart another_d = map.phi1(map.phi1(d)); + const std::vector& vec = darts_per_vertex[Vertex(map.phi_1(d))]; + + Dart another_good_dart; + for(auto it = vec.begin(); it != vec.end() && another_good_dart.is_nil(); ++it) + { + if(map.get_embedding(Vertex(map.phi1(*it))) == map.get_embedding(Vertex(another_d)) && + map.get_embedding(Vertex(map.phi_1(*it))) == map.get_embedding(Vertex(map.phi1(map.phi1(another_d))))) + { + another_good_dart = *it ; + } + } + + // we add a stamp volume between the faces + const Dart d_quad = mbuild.add_stamp_volume_topo(); + { + Dart q1_it = d; + Dart q2_it = map.phi_1(d_quad); + do { + mbuild.init_parent_vertex_embedding(q2_it, map.get_embedding(Vertex(q1_it))); + q1_it = map.phi1(q1_it); + q2_it = map.phi_1(q2_it); + } while (q1_it != d); + } + + sew_volumes(d, map.phi1(map.phi1(d_quad))); + m.unmark_orbit(Face(d)); + + sew_volumes(good_dart, map.phi2(map.phi1(map.phi1(d_quad)))); + m.unmark_orbit(Face(good_dart)); + + if(!another_good_dart.is_nil()) + { + sew_volumes(another_good_dart, map.phi2(d_quad)); + m.unmark_orbit(Face(another_good_dart)); + } else + { + m.unmark_orbit(Face2(map.phi2(d_quad))); + ++nbBoundaryFaces; + } + } + else { // // face of d is tri + const Dart another_dart = map.phi_1(d); + std::vector& vec = darts_per_vertex[Vertex(d)]; + + Dart another_good_dart; + for(auto it = vec.begin(); it != vec.end() && another_good_dart.is_nil(); ++it) + { + if(map.get_embedding(Vertex(map.phi1(*it))) == map.get_embedding(Vertex(another_dart)) && + map.get_embedding(Vertex(map.phi_1(*it))) == map.get_embedding(Vertex(map.phi1(map.phi1(good_dart))))) + { + another_good_dart = *it ; + } + } + + const Dart d_quad = mbuild.add_stamp_volume_topo(); + { + Dart q1_it = good_dart; + Dart q2_it = d_quad; + do { + mbuild.init_parent_vertex_embedding(q2_it, map.get_embedding(Vertex(q1_it))); + q1_it = map.phi1(q1_it); + q2_it = map.phi_1(q2_it); + } while (q1_it != good_dart); + } + + sew_volumes(d_quad, map.phi_1(good_dart)); + m.unmark_orbit(Face(good_dart)); + + + sew_volumes(d, map.phi2(map.phi_1(d_quad))); + m.unmark_orbit(Face(d)); + + if (!another_good_dart.is_nil()) + { + sew_volumes(another_good_dart, map.phi1(map.phi2(map.phi1(d_quad)))); + m.unmark_orbit(Face(another_good_dart)); + } else { + m.unmark_orbit(Face2(map.phi1(map.phi2(map.phi1(d_quad))))); + ++nbBoundaryFaces; + } + } + } } else { @@ -299,7 +398,7 @@ class VolumeImport : public MeshImportGen if (nbBoundaryFaces > 0) { unsigned int nbH = mbuild.close_map(); - std::cout << "Map closed (" << nbBoundaryFaces << " boundary faces / " << nbH << " holes)" << std::endl; + std::cout << CGOGN_FUNC << ": Map closed with " << nbBoundaryFaces << " boundary face(s) and " << nbH << " hole(s)." << std::endl; } if (this->volume_attributes_.get_nb_attributes() > 0) @@ -312,9 +411,10 @@ class VolumeImport : public MeshImportGen } template - void add_hexa(ChunkArrayconst& pos,unsigned int& p0, unsigned int& p1, unsigned int& p2, unsigned int& p3, unsigned int& p4, unsigned int& p5, unsigned int& p6, unsigned int& p7) + void add_hexa(ChunkArrayconst& pos,unsigned int p0, unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned int p5, unsigned int p6, unsigned int p7, bool reoriente) { - this->reoriente_hexa(pos, p0, p1, p2, p3, p4, p5, p6, p7); + if (reoriente) + this->reoriente_hexa(pos, p0, p1, p2, p3, p4, p5, p6, p7); this->volumes_nb_vertices_.push_back(8u); this->volumes_vertex_indices_.push_back(p0); this->volumes_vertex_indices_.push_back(p1); @@ -338,9 +438,10 @@ class VolumeImport : public MeshImportGen } template - void add_tetra(ChunkArrayconst& pos,unsigned int& p0, unsigned int& p1, unsigned int& p2, unsigned int& p3) + void add_tetra(ChunkArrayconst& pos,unsigned int p0, unsigned int p1, unsigned int p2, unsigned int p3, bool reoriente) { - this->reoriente_tetra(pos,p0,p1,p2,p3); + if (reoriente) + this->reoriente_tetra(pos,p0,p1,p2,p3); this->volumes_nb_vertices_.push_back(4u); this->volumes_vertex_indices_.push_back(p0); this->volumes_vertex_indices_.push_back(p1); @@ -349,7 +450,7 @@ class VolumeImport : public MeshImportGen } template - void add_pyramid(ChunkArrayconst& pos,unsigned int& p0, unsigned int& p1, unsigned int& p2, unsigned int& p3, unsigned int& p4) + void add_pyramid(ChunkArrayconst& pos,unsigned int p0, unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4) { this->volumes_nb_vertices_.push_back(5u); this->volumes_vertex_indices_.push_back(p0); @@ -360,7 +461,7 @@ class VolumeImport : public MeshImportGen } template - void add_triangular_prism(ChunkArrayconst& pos,unsigned int& p0, unsigned int& p1, unsigned int& p2, unsigned int& p3, unsigned int& p4, unsigned int& p5) + void add_triangular_prism(ChunkArrayconst& pos,unsigned int p0, unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned int p5) { this->volumes_nb_vertices_.push_back(6u); this->volumes_vertex_indices_.push_back(p0); diff --git a/cgogn/io/vtk_io.h b/cgogn/io/vtk_io.h index 3a08683a..f61552c4 100644 --- a/cgogn/io/vtk_io.h +++ b/cgogn/io/vtk_io.h @@ -845,12 +845,12 @@ class VtkVolumeImport : public VtkIO:: std::swap(ids[curr_offset+2],ids[curr_offset+3]); std::swap(ids[curr_offset+6],ids[curr_offset+7]); } - this->add_hexa(pos, ids[curr_offset+0],ids[curr_offset+1],ids[curr_offset+2],ids[curr_offset+3],ids[curr_offset+4],ids[curr_offset+5],ids[curr_offset+6],ids[curr_offset+7]); + this->add_hexa(pos, ids[curr_offset+0],ids[curr_offset+1],ids[curr_offset+2],ids[curr_offset+3],ids[curr_offset+4],ids[curr_offset+5],ids[curr_offset+6],ids[curr_offset+7], true); curr_offset+=8u; }else { if (type_vol[i]== VTK_CELL_TYPES::VTK_TETRA) { - this->add_tetra(pos, ids[curr_offset+0],ids[curr_offset+1],ids[curr_offset+2],ids[curr_offset+3]); + this->add_tetra(pos, ids[curr_offset+0],ids[curr_offset+1],ids[curr_offset+2],ids[curr_offset+3], true); curr_offset+=4u; } else { if (type_vol[i]== VTK_CELL_TYPES::VTK_PYRAMID) From 504f63673f306a9d2f2fa2ae802a5fbfcf4edd79 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Wed, 16 Mar 2016 10:25:35 +0100 Subject: [PATCH 326/402] const_iterator_nomask --- cgogn/core/cmap/cmap2_builder.h | 7 +- cgogn/core/cmap/cmap3_builder.h | 7 +- cgogn/core/cmap/map_base.h | 172 +++++++++++++++++++++++++++ cgogn/core/cmap/map_base_data.h | 4 +- cgogn/core/examples/map/map.cpp | 2 +- cgogn/core/tests/cmap/cmap2_test.cpp | 66 ++++------ cgogn/io/examples/cmap2_import.cpp | 4 +- 7 files changed, 205 insertions(+), 57 deletions(-) diff --git a/cgogn/core/cmap/cmap2_builder.h b/cgogn/core/cmap/cmap2_builder.h index 4ef794d2..59c165c9 100644 --- a/cgogn/core/cmap/cmap2_builder.h +++ b/cgogn/core/cmap/cmap2_builder.h @@ -200,14 +200,11 @@ class CMap2Builder_T inline void close_map() { std::vector fix_point_darts; - map_.foreach_dart( - [&] (Dart d) + map_.foreach_dart_nomask( [&] (Dart d) { if (map_.phi2(d) == d) fix_point_darts.push_back(d); - }, - [] (Dart) { return true; } - ); + }); for (Dart d : fix_point_darts) { if (map_.phi2(d) == d) diff --git a/cgogn/core/cmap/cmap3_builder.h b/cgogn/core/cmap/cmap3_builder.h index 3e62ebcd..97473843 100644 --- a/cgogn/core/cmap/cmap3_builder.h +++ b/cgogn/core/cmap/cmap3_builder.h @@ -185,14 +185,11 @@ class CMap3Builder_T { // Search the map for topological holes (fix points of phi3) std::vector fix_point_darts; - map_.foreach_dart( - [&] (Dart d) + map_.foreach_dart_nomask( [&] (Dart d) { if (map_.phi3(d) == d) fix_point_darts.push_back(d); - }, - [] (Dart) { return true; } - ); + }); unsigned int nb = 0u; for (Dart d : fix_point_darts) { diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 48cede6e..03a12115 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -618,6 +618,11 @@ class MapBase : public MapBaseData protected: + /*! + * \Brief Iterator that use MASK to filter the traversed darts + * MASK is an functor that determine if a dart should be traversed or skipped. + * It returns true when a dart is to be traversed and false to make the iterator skip it. + */ template class const_iterator { @@ -699,6 +704,76 @@ class MapBase : public MapBaseData return const_iterator(*this, Dart(this->topology_.end()), mask); } + /*! + * \Brief Specialized Iterator do not filter the traversed darts + * All dart are traversed by by iterator. + */ + class const_iterator_nomask + { + public: + + const Self& map_; + Dart dart_; + Dart end_; + + inline const_iterator_nomask(const Self& map, Dart d) : + map_(map), + dart_(d) + { + end_ = Dart(map_.topology_.end()); + } + + inline const_iterator_nomask(const const_iterator_nomask& it) : + map_(it.map_), + dart_(it.dart_), + end_(it.end_) + {} + + inline const_iterator_nomask& operator=(const const_iterator_nomask& it) + { + map_ = it.map_; + dart_ = it.dart_; + end_ = it.end_; + return *this; + } + + inline const_iterator_nomask& operator++() + { + cgogn_assert(dart_.index < end_.index); + map_.topology_.next(dart_.index); + return *this; + } + + inline const Dart& operator*() const + { + return dart_; + } + + inline bool operator!=(const const_iterator_nomask& it) const + { + cgogn_assert(&map_ == &(it.map_)); + cgogn_assert(end_ == it.end_); + return dart_ != it.dart_; + } + + inline bool operator==(const const_iterator_nomask& it) const + { + cgogn_assert(&map_ == &(it.map_)); + cgogn_assert(end_ == it.end_); + return dart_ == it.dart_; + } + }; + + inline const_iterator_nomask begin() const + { + return const_iterator_nomask(*this, Dart(this->topology_.begin())); + } + + inline const_iterator_nomask end() const + { + return const_iterator_nomask(*this, Dart(this->topology_.end())); + } + public: /** @@ -729,6 +804,15 @@ class MapBase : public MapBaseData f(*it); } + template + inline void foreach_dart_nomask(const FUNC& f) const + { + static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); + + for (const_iterator_nomask it = this->begin(), end = this->end(); it != end; ++it) + f(*it); + } + template inline void parallel_foreach_dart(const FUNC& f) const { @@ -812,6 +896,75 @@ class MapBase : public MapBaseData } } + template + inline void parallel_foreach_dart_nomask(const FUNC& f) const + { + static_assert(check_func_ith_parameter_type(FUNC, 0, Dart), "Wrong function first parameter type"); + static_assert(check_func_ith_parameter_type(FUNC, 1, unsigned int), "Wrong function second parameter type"); + + using Future = std::future::type>; + using VecDarts = std::vector; + + ThreadPool* thread_pool = cgogn::get_thread_pool(); + const std::size_t nb_threads_pool = thread_pool->get_nb_threads(); + + std::array, 2> dart_buffers; + std::array, 2> futures; + dart_buffers[0].reserve(nb_threads_pool); + dart_buffers[1].reserve(nb_threads_pool); + futures[0].reserve(nb_threads_pool); + futures[1].reserve(nb_threads_pool); + + Buffers* dbuffs = cgogn::get_dart_buffers(); + + const_iterator_nomask it = this->begin(); + const const_iterator_nomask end = this->end(); + + while (it != end) + { + for (unsigned int i = 0u; i < 2u; ++i) + { + for (unsigned int j = 0u; j < nb_threads_pool && it != end; ++j) + { + dart_buffers[i].push_back(dbuffs->get_buffer()); + cgogn_assert(dart_buffers[i].size() <= nb_threads_pool); + std::vector& darts = *dart_buffers[i].back(); + darts.reserve(PARALLEL_BUFFER_SIZE); + for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != end; ++k) + { + darts.push_back(*it); + ++it; + } + + futures[i].push_back(thread_pool->enqueue([&darts, &f] (unsigned int th_id) + { + for (auto d : darts) + f(d, th_id); + })); + } + + const unsigned int id = (i+1u) % 2u; + + for (auto& fu : futures[id]) + fu.wait(); + for (auto& b : dart_buffers[id]) + dbuffs->release_cell_buffer(b); + + futures[id].clear(); + dart_buffers[id].clear(); + + // if we reach the end of the map while filling buffers from the second set we need to clean them too. + if (it == end && i == 1u) + { + for (auto& fu : futures[1u]) + fu.wait(); + for (auto &b : dart_buffers[1u]) + dbuffs->release_buffer(b); + } + } + } + } + /** * \brief apply a function on each dart of the map and stops when the function returns false * @tparam FUNC type of the callable @@ -844,6 +997,19 @@ class MapBase : public MapBaseData } } + template + inline void foreach_dart_until_nomask(const FUNC& f) const + { + static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); + static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); + + for (const_iterator_nomask it = this->begin(), end = this->end(); it != end; ++it) + { + if (!f(*it)) + break; + } + } + /** * \brief apply a function on each orbit of the map * @tparam FUNC type of the callable @@ -855,6 +1021,12 @@ class MapBase : public MapBaseData foreach_cell(f, [this] (Dart d) { return !this->is_boundary(d); }); } + template + inline void foreach_cell_nomask(const FUNC& f) const + { + foreach_cell(f, [this] (Dart) { return true; }); + } + template inline void foreach_boundary_cell(const FUNC& f) const { diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index 24ba6329..c1c14cf2 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -263,8 +263,8 @@ class MapBaseData : public MapGen { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); cgogn_message_assert(is_embedded(), "Invalid parameter: orbit not embedded"); -// cgogn_message_assert((*embeddings_[ORBIT])[c.dart.index] != EMBNULL, "get_embedding result is EMBNULL"); - if ((*embeddings_[ORBIT])[c.dart.index] == EMBNULL) std::cerr << "EMBNULL pour " << orbit_name(ORBIT) << std::endl; + cgogn_message_assert((*embeddings_[ORBIT])[c.dart.index] != EMBNULL, "get_embedding result is EMBNULL"); + return (*embeddings_[ORBIT])[c.dart.index]; } diff --git a/cgogn/core/examples/map/map.cpp b/cgogn/core/examples/map/map.cpp index 8490326e..f619b757 100644 --- a/cgogn/core/examples/map/map.cpp +++ b/cgogn/core/examples/map/map.cpp @@ -95,7 +95,7 @@ int test1(MAP& map) dm.mark(d1); std::cout << "Darts :" << std::endl; - map.foreach_dart([] (Dart d) { std::cout << d << std::endl; }); + map.foreach_dart_nomask([] (Dart d) { std::cout << d << std::endl; }); std::cout << "End Darts" << std::endl; std::cout << "Vertices :" << std::endl; diff --git a/cgogn/core/tests/cmap/cmap2_test.cpp b/cgogn/core/tests/cmap/cmap2_test.cpp index 78df3ed0..fab9b7ec 100644 --- a/cgogn/core/tests/cmap/cmap2_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_test.cpp @@ -133,49 +133,31 @@ class CMap2Test : public ::testing::Test } } // Close the map (remove remaining boundary) - cmap_.foreach_dart( - [&] (Dart d) - { - if (cmap_.phi2(d) == d) mbuild.close_hole_topo(d); - }, - [this] (Dart d) { return true; } - ); + cmap_.foreach_dart_nomask( [&] (Dart d) + { + if (cmap_.phi2(d) == d) mbuild.close_hole_topo(d); + }); // Embed the map - cmap_.foreach_dart( - [&] (Dart d) - { - mbuild.new_orbit_embedding(CDart(d)); - }, - [this] (Dart d) { return true; } - ); - cmap_.foreach_cell( - [&] (Vertex v) - { - mbuild.new_orbit_embedding(v); - }, - [this] (Dart d) { return true; } - ); - cmap_.foreach_cell( - [&] (Edge e) - { - mbuild.new_orbit_embedding(e); - }, - [this] (Dart d) { return true; } - ); - cmap_.foreach_cell( - [&] (Face f) - { - mbuild.new_orbit_embedding(f); - }, - [this] (Dart d) { return true; } - ); - cmap_.foreach_cell( - [&] (Volume w) - { - mbuild.new_orbit_embedding(w); - }, - [this] (Dart d) { return true; } - ); + cmap_.foreach_dart_nomask( [&] (Dart d) + { + mbuild.new_orbit_embedding(CDart(d)); + }); + cmap_.foreach_cell_nomask( [&] (Vertex v) + { + mbuild.new_orbit_embedding(v); + }); + cmap_.foreach_cell_nomask( [&] (Edge e) + { + mbuild.new_orbit_embedding(e); + }); + cmap_.foreach_cell_nomask( [&] (Face f) + { + mbuild.new_orbit_embedding(f); + }); + cmap_.foreach_cell_nomask( [&] (Volume w) + { + mbuild.new_orbit_embedding(w); + }); } }; diff --git a/cgogn/io/examples/cmap2_import.cpp b/cgogn/io/examples/cmap2_import.cpp index fe0768d2..3723dd9f 100644 --- a/cgogn/io/examples/cmap2_import.cpp +++ b/cgogn/io/examples/cmap2_import.cpp @@ -43,14 +43,14 @@ int main(int argc, char** argv) cgogn::io::import_surface(map, surfaceMesh); unsigned int nb_darts = 0; - map.foreach_dart([&nb_darts] (cgogn::Dart) { nb_darts++; }); + map.foreach_dart_nomask([&nb_darts] (cgogn::Dart) { nb_darts++; }); std::cout << "nb darts -> " << nb_darts << std::endl; unsigned int nb_darts_2 = 0; std::vector nb_darts_per_thread(cgogn::NB_THREADS - 1); for (unsigned int& n : nb_darts_per_thread) n = 0; - map.parallel_foreach_dart([&nb_darts_per_thread] (cgogn::Dart, unsigned int thread_index) + map.parallel_foreach_dart_nomask([&nb_darts_per_thread] (cgogn::Dart, unsigned int thread_index) { nb_darts_per_thread[thread_index]++; }); From 368ab640d82a02d9c773ed6ce39e7dbe2dbdad54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 16 Mar 2016 10:44:48 +0100 Subject: [PATCH 327/402] checking orientation for prisms and pyramids too. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/lm6_io.h | 8 +++----- cgogn/io/volume_import.h | 40 +++++++++++++++++++++++++++++++--------- cgogn/io/vtk_io.h | 4 ++-- 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/cgogn/io/lm6_io.h b/cgogn/io/lm6_io.h index efb28cae..622e92df 100644 --- a/cgogn/io/lm6_io.h +++ b/cgogn/io/lm6_io.h @@ -102,7 +102,7 @@ class LM6VolumeImport : public VolumeImport (void) GmfGetLin(mesh_index, GmfTetrahedra, &ids[0],&ids[1], &ids[2], &ids[3], &ref); for (auto& id : ids) --id; - this->add_tetra(*position, ids[0],ids[1], ids[2], ids[3], true); + this->add_tetra(*position, ids[0],ids[1], ids[2], ids[3], false); } } @@ -130,7 +130,7 @@ class LM6VolumeImport : public VolumeImport (void) GmfGetLin(mesh_index, GmfPrisms, &ids[0],&ids[1], &ids[2], &ids[3], &ids[4], &ids[5], &ref); for (auto& id : ids) --id; - this->add_triangular_prism(*position, ids[0],ids[1], ids[2], ids[3], ids[4],ids[5]); + this->add_triangular_prism(*position, ids[0],ids[1], ids[2], ids[3], ids[4],ids[5], false); } } @@ -143,12 +143,10 @@ class LM6VolumeImport : public VolumeImport (void) GmfGetLin(mesh_index, GmfPyramids, &ids[0],&ids[1], &ids[2], &ids[3], &ids[4], &ref); for (auto& id : ids) --id; - this->add_pyramid(*position, ids[0],ids[1], ids[2], ids[3], ids[4]); + this->add_pyramid(*position, ids[0],ids[1], ids[2], ids[3], ids[4], false); } } - - GmfCloseMesh(mesh_index); return true; } diff --git a/cgogn/io/volume_import.h b/cgogn/io/volume_import.h index 6ae0d361..cb8732db 100644 --- a/cgogn/io/volume_import.h +++ b/cgogn/io/volume_import.h @@ -412,9 +412,9 @@ class VolumeImport : public MeshImportGen } template - void add_hexa(ChunkArrayconst& pos,unsigned int p0, unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned int p5, unsigned int p6, unsigned int p7, bool reoriente) + void add_hexa(ChunkArrayconst& pos,unsigned int p0, unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned int p5, unsigned int p6, unsigned int p7, bool check_orientation) { - if (reoriente) + if (check_orientation) this->reoriente_hexa(pos, p0, p1, p2, p3, p4, p5, p6, p7); this->volumes_nb_vertices_.push_back(8u); this->volumes_vertex_indices_.push_back(p0); @@ -439,9 +439,9 @@ class VolumeImport : public MeshImportGen } template - void add_tetra(ChunkArrayconst& pos,unsigned int p0, unsigned int p1, unsigned int p2, unsigned int p3, bool reoriente) + void add_tetra(ChunkArrayconst& pos,unsigned int p0, unsigned int p1, unsigned int p2, unsigned int p3, bool check_orientation) { - if (reoriente) + if (check_orientation) this->reoriente_tetra(pos,p0,p1,p2,p3); this->volumes_nb_vertices_.push_back(4u); this->volumes_vertex_indices_.push_back(p0); @@ -451,9 +451,18 @@ class VolumeImport : public MeshImportGen } template - void add_pyramid(ChunkArrayconst& pos,unsigned int p0, unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4) + inline void reoriente_tetra(ChunkArrayconst& pos, unsigned int& p0, unsigned int& p1, unsigned int& p2, unsigned int& p3) + { + if (geometry::test_orientation_3D(pos[p0], pos[p1],pos[p2],pos[p3]) == geometry::Orientation3D::OVER) + std::swap(p1, p2); + } + + template + void add_pyramid(ChunkArrayconst& pos,unsigned int p0, unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, bool check_orientation) { this->volumes_nb_vertices_.push_back(5u); + if (check_orientation) + this->reoriente_pyramid(pos,p0,p1,p2,p3,p4); this->volumes_vertex_indices_.push_back(p0); this->volumes_vertex_indices_.push_back(p1); this->volumes_vertex_indices_.push_back(p2); @@ -462,8 +471,17 @@ class VolumeImport : public MeshImportGen } template - void add_triangular_prism(ChunkArrayconst& pos,unsigned int p0, unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned int p5) + inline void reoriente_pyramid(ChunkArrayconst& pos, unsigned int& p0, unsigned int& p1, unsigned int& p2, unsigned int& p3, unsigned int& p4) + { + if (geometry::test_orientation_3D(pos[p4], pos[p0],pos[p1],pos[p2]) == geometry::Orientation3D::OVER) + std::swap(p1, p3); + } + + template + void add_triangular_prism(ChunkArrayconst& pos,unsigned int p0, unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned int p5, bool check_orientation) { + if (check_orientation) + this->reoriente_triangular_prism(pos,p0,p1,p2,p3,p4,p5); this->volumes_nb_vertices_.push_back(6u); this->volumes_vertex_indices_.push_back(p0); this->volumes_vertex_indices_.push_back(p1); @@ -474,12 +492,16 @@ class VolumeImport : public MeshImportGen } template - inline void reoriente_tetra(ChunkArrayconst& pos, unsigned int& p0, unsigned int& p1, unsigned int& p2, unsigned int& p3) + inline void reoriente_triangular_prism(ChunkArrayconst& pos, unsigned int& p0, unsigned int& p1, unsigned int& p2, unsigned int& p3, unsigned int& p4, unsigned int& p5) { - if (geometry::test_orientation_3D(pos[p0], pos[p1],pos[p2],pos[p3]) == geometry::Orientation3D::OVER) - std::swap(p1, p2); + if (geometry::test_orientation_3D(pos[p3], pos[p0],pos[p1],pos[p2]) == geometry::Orientation3D::OVER) + { + std::swap(p1,p2); + std::swap(p4,p5); + } } + }; #if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_VOLUME_IMPORT_CPP_)) diff --git a/cgogn/io/vtk_io.h b/cgogn/io/vtk_io.h index ffb57db9..47800c1f 100644 --- a/cgogn/io/vtk_io.h +++ b/cgogn/io/vtk_io.h @@ -855,12 +855,12 @@ class VtkVolumeImport : public VtkIO:: } else { if (type_vol[i]== VTK_CELL_TYPES::VTK_PYRAMID) { - this->add_pyramid(pos, ids[curr_offset+0],ids[curr_offset+1],ids[curr_offset+2],ids[curr_offset+3],ids[curr_offset+4]); + this->add_pyramid(pos, ids[curr_offset+0],ids[curr_offset+1],ids[curr_offset+2],ids[curr_offset+3],ids[curr_offset+4],true); curr_offset+=5u; } else { if (type_vol[i]== VTK_CELL_TYPES::VTK_WEDGE) { - this->add_triangular_prism(pos, ids[curr_offset+0],ids[curr_offset+1],ids[curr_offset+2],ids[curr_offset+3],ids[curr_offset+4],ids[curr_offset+5]); + this->add_triangular_prism(pos, ids[curr_offset+0],ids[curr_offset+1],ids[curr_offset+2],ids[curr_offset+3],ids[curr_offset+4],ids[curr_offset+5],true); curr_offset+=6u; } } From 10f08de2a3255e96c5ff8c011461bc7f34ce737d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 16 Mar 2016 11:31:21 +0100 Subject: [PATCH 328/402] added conventions for ordering the indices of volume cells in VolumeImport. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/volume_import.h | 64 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/cgogn/io/volume_import.h b/cgogn/io/volume_import.h index cb8732db..d7600acb 100644 --- a/cgogn/io/volume_import.h +++ b/cgogn/io/volume_import.h @@ -38,6 +38,70 @@ #include +/******************************************************************************* +* CGoGN convention for ordering the indices for volume cells in the VolumeImport class (prior to the map creation) +* +*-->Tetras: any order. The orientation is checked when calling add_tetra. +* 3 +* ,/|`\ +* ,/ | `\ +* ,/ '. `\ +* ,/ | `\ +* ,/ | `\ +*2-----------'.--------1 +* `\. | ,/ +* `\. | ,/ +* `\. '. ,/ +* `\. |/ +* `0 +* +*-->Pyramids: First the indices of the quad face, then the top. The orientation is checked when calling add_pyramid. +* 4 +* ,/|\ +* ,/ .'|\ +* ,/ | | \ +* ,/ .' | `. +* ,/ | '. \ +* ,/ .' | \ +* ,/ | | \ +*0----------.'----3 `. +* `\ | `\ \ +* `\ .' `\ - \ +* `\ | `\ \ +* `\.' `\` +* 1----------------2 +* +*-->Prisms: First the indices of one of the triangular face then the indices of the opposite face (same order). The orientation is checked when calling add_prism. +* 3 +* ,/|`\ +* ,/ | `\ +* ,/ | `\ +*4------+------5 +*| | | +*| | | +*| | | +*| | | +*| | | +*| 0 | +*| ,/ `\ | +*| ,/ `\ | +*|,/ `\| +*1-------------2 +* +*-->Hexas: First the indices of one face then the indices of the opposite face (same order). The orientation is checked when calling add_hexa. +*7----------6 +*|\ |\ +*| \ | \ +*| \ | \ +*| 3------+---2 +*| | |-- | +*4---+------5 | +* \ | \ | +* \ | \ | +* \| \| +* 0----------1 +*******************************************************************************/ + namespace cgogn { From ab5f7b2803c00d61b0f7aa7d857b0e17396c952a Mon Sep 17 00:00:00 2001 From: David Cazier Date: Wed, 16 Mar 2016 11:36:04 +0100 Subject: [PATCH 329/402] no more iterator ... --- cgogn/core/cmap/map_base.h | 244 ++++++++++--------------------------- 1 file changed, 67 insertions(+), 177 deletions(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 03a12115..fc341993 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -619,159 +619,49 @@ class MapBase : public MapBaseData protected: /*! - * \Brief Iterator that use MASK to filter the traversed darts - * MASK is an functor that determine if a dart should be traversed or skipped. - * It returns true when a dart is to be traversed and false to make the iterator skip it. + * \Brief Methods to iterate over darts with a MASK that filters the traversed darts + * A MASK is an functor that determine if a dart should be traversed or skipped. + * It return false when a dart should be skipped, true in other cases. */ template - class const_iterator + inline Dart begin(const MASK& mask) const { - public: - - const Self& map_; - const MASK& mask_; - Dart dart_; - Dart end_; - - inline const_iterator(const Self& map, Dart d, const MASK& mask) : - map_(map), - dart_(d), - mask_(mask) - { - end_ = Dart(map_.topology_.end()); - } - - inline const_iterator(const const_iterator& it) : - map_(it.map_), - dart_(it.dart_), - end_(it.end_), - mask_(it.mask_) - {} - - inline const_iterator& operator=(const const_iterator& it) - { - map_ = it.map_; - dart_ = it.dart_; - end_ = it.end_; - mask_ = it.mask_; - return *this; - } - - inline const_iterator& operator++() - { - cgogn_assert(dart_.index < end_.index); - do - { - map_.topology_.next(dart_.index); - } while (dart_ != end_ && !mask_(dart_)); - return *this; - } - - inline const Dart& operator*() const - { - return dart_; - } + Dart d = Dart(this->topology_.begin()); + Dart end = Dart(this->topology_.end()); - inline bool operator!=(const const_iterator& it) const - { - cgogn_assert(&map_ == &(it.map_)); - cgogn_assert(end_ == it.end_); - return dart_ != it.dart_; - } + while (d != end && !mask(d)) + this->topology_.next(d.index); - inline bool operator==(const const_iterator& it) const - { - cgogn_assert(&map_ == &(it.map_)); - cgogn_assert(end_ == it.end_); - return dart_ == it.dart_; - } - }; + return d; + } template - inline const_iterator begin(const MASK& mask) const + inline void next(Dart& d, const MASK& mask) const { - Dart d = Dart(this->topology_.begin()); Dart end = Dart(this->topology_.end()); + this->topology_.next(d.index); while (d != end && !mask(d)) this->topology_.next(d.index); - return const_iterator(*this, d, mask); } - template - inline const_iterator end(const MASK& mask) const + inline Dart end() const { - return const_iterator(*this, Dart(this->topology_.end()), mask); + return Dart(this->topology_.end()); } /*! - * \Brief Specialized Iterator do not filter the traversed darts - * All dart are traversed by by iterator. + * \Brief Methods to iterate over all darts. + * All darts are traversed (lying on the boundary or not). */ - class const_iterator_nomask + inline Dart begin() const { - public: - - const Self& map_; - Dart dart_; - Dart end_; - - inline const_iterator_nomask(const Self& map, Dart d) : - map_(map), - dart_(d) - { - end_ = Dart(map_.topology_.end()); - } - - inline const_iterator_nomask(const const_iterator_nomask& it) : - map_(it.map_), - dart_(it.dart_), - end_(it.end_) - {} - - inline const_iterator_nomask& operator=(const const_iterator_nomask& it) - { - map_ = it.map_; - dart_ = it.dart_; - end_ = it.end_; - return *this; - } - - inline const_iterator_nomask& operator++() - { - cgogn_assert(dart_.index < end_.index); - map_.topology_.next(dart_.index); - return *this; - } - - inline const Dart& operator*() const - { - return dart_; - } - - inline bool operator!=(const const_iterator_nomask& it) const - { - cgogn_assert(&map_ == &(it.map_)); - cgogn_assert(end_ == it.end_); - return dart_ != it.dart_; - } - - inline bool operator==(const const_iterator_nomask& it) const - { - cgogn_assert(&map_ == &(it.map_)); - cgogn_assert(end_ == it.end_); - return dart_ == it.dart_; - } - }; - - inline const_iterator_nomask begin() const - { - return const_iterator_nomask(*this, Dart(this->topology_.begin())); + return Dart(this->topology_.begin()); } - inline const_iterator_nomask end() const + inline void next(Dart& d) const { - return const_iterator_nomask(*this, Dart(this->topology_.end())); + this->topology_.next(d.index); } public: @@ -800,8 +690,8 @@ class MapBase : public MapBaseData static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); - for (const_iterator it = this->begin(mask), end = this->end(mask); it != end; ++it) - f(*it); + for (Dart it = begin(mask), last = end(); it != last; next(it, mask)) + f(it); } template @@ -809,8 +699,8 @@ class MapBase : public MapBaseData { static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); - for (const_iterator_nomask it = this->begin(), end = this->end(); it != end; ++it) - f(*it); + for (Dart it = begin(), last = end(); it != last; next(it)) + f(it); } template @@ -848,23 +738,23 @@ class MapBase : public MapBaseData Buffers* dbuffs = cgogn::get_dart_buffers(); - const_iterator it = this->begin(mask); - const const_iterator end = this->end(mask); + Dart it = begin(mask); + Dart last = end(); - while (it != end) + while (it != last) { for (unsigned int i = 0u; i < 2u; ++i) { - for (unsigned int j = 0u; j < nb_threads_pool && it != end; ++j) + for (unsigned int j = 0u; j < nb_threads_pool && it != last; ++j) { dart_buffers[i].push_back(dbuffs->get_buffer()); cgogn_assert(dart_buffers[i].size() <= nb_threads_pool); std::vector& darts = *dart_buffers[i].back(); darts.reserve(PARALLEL_BUFFER_SIZE); - for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != end; ++k) + for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != last; ++k) { - darts.push_back(*it); - ++it; + darts.push_back(it); + next(it, mask); } futures[i].push_back(thread_pool->enqueue([&darts, &f] (unsigned int th_id) @@ -885,7 +775,7 @@ class MapBase : public MapBaseData dart_buffers[id].clear(); // if we reach the end of the map while filling buffers from the second set we need to clean them too. - if (it == end && i == 1u) + if (it == last && i == 1u) { for (auto& fu : futures[1u]) fu.wait(); @@ -917,23 +807,23 @@ class MapBase : public MapBaseData Buffers* dbuffs = cgogn::get_dart_buffers(); - const_iterator_nomask it = this->begin(); - const const_iterator_nomask end = this->end(); + Dart it = begin(); + Dart last = end(); - while (it != end) + while (it != last) { for (unsigned int i = 0u; i < 2u; ++i) { - for (unsigned int j = 0u; j < nb_threads_pool && it != end; ++j) + for (unsigned int j = 0u; j < nb_threads_pool && it != last; ++j) { dart_buffers[i].push_back(dbuffs->get_buffer()); cgogn_assert(dart_buffers[i].size() <= nb_threads_pool); std::vector& darts = *dart_buffers[i].back(); darts.reserve(PARALLEL_BUFFER_SIZE); - for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != end; ++k) + for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != last; ++k) { - darts.push_back(*it); - ++it; + darts.push_back(it); + next(it); } futures[i].push_back(thread_pool->enqueue([&darts, &f] (unsigned int th_id) @@ -954,7 +844,7 @@ class MapBase : public MapBaseData dart_buffers[id].clear(); // if we reach the end of the map while filling buffers from the second set we need to clean them too. - if (it == end && i == 1u) + if (it == last && i == 1u) { for (auto& fu : futures[1u]) fu.wait(); @@ -990,9 +880,9 @@ class MapBase : public MapBaseData static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); - for (const_iterator it = this->begin(mask), end = this->end(mask); it != end; ++it) + for (Dart it = begin(mask), last = end(); it != last; next(it, mask)) { - if (!f(*it)) + if (!f(it)) break; } } @@ -1003,9 +893,9 @@ class MapBase : public MapBaseData static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); - for (const_iterator_nomask it = this->begin(), end = this->end(); it != end; ++it) + for (Dart it = begin(), last = end(); it != last; next(it)) { - if (!f(*it)) + if (!f(it)) break; } } @@ -1165,11 +1055,11 @@ class MapBase : public MapBaseData using CellType = typename function_traits::template arg<0>::type; DartMarker dm(*to_concrete()); - for (const_iterator it = this->begin(mask), end = this->end(mask); it != end; ++it) + for (Dart it = begin(mask), last = end(); it != last; next(it, mask)) { - if (!dm.is_marked(*it)) + if (!dm.is_marked(it)) { - CellType c(*it); + CellType c(it); dm.mark_orbit(c); f(c); } @@ -1198,27 +1088,27 @@ class MapBase : public MapBaseData Buffers* dbuffs = cgogn::get_dart_buffers(); DartMarker dm(*to_concrete()); - const_iterator it = this->begin(mask); - const const_iterator end = this->end(mask); + Dart it = begin(mask); + Dart last = end(); unsigned int i = 0u; // buffer id (0/1) unsigned int j = 0u; // thread id (0..nb_threads_pool) - while (it != end) + while (it != last) { // fill buffer cells_buffers[i].push_back(dbuffs->template get_cell_buffer()); VecCell& cells = *cells_buffers[i].back(); cells.reserve(PARALLEL_BUFFER_SIZE); - for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != end; ) + for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != last; ) { - if (!dm.is_marked(*it)) + if (!dm.is_marked(it)) { - CellType c(*it); + CellType c(it); dm.mark_orbit(c); cells.push_back(c); ++k; } - ++it; + next(it, mask); } //launch thread futures[i].push_back(thread_pool->enqueue([&cells, &f] (unsigned int th_id) @@ -1258,9 +1148,9 @@ class MapBase : public MapBaseData static const Orbit ORBIT = CellType::ORBIT; CellMarker cm(*to_concrete()); - for (const_iterator it = this->begin(mask), end = this->end(mask); it != end; ++it) + for (Dart it = begin(mask), last = end(); it != last; next(it, mask)) { - CellType c(*it); + CellType c(it); if (!cm.is_marked(c)) { cm.mark(c); @@ -1291,27 +1181,27 @@ class MapBase : public MapBaseData Buffers* dbuffs = cgogn::get_dart_buffers(); CellMarker cm(*to_concrete()); - const_iterator it = this->begin(mask); - const const_iterator end = this->end(mask); + Dart it = begin(mask); + Dart last = end(); unsigned int i = 0u; // buffer id (0/1) unsigned int j = 0u; // thread id (0..nb_threads_pool) - while (it != end) + while (it != last) { // fill buffer cells_buffers[i].push_back(dbuffs->template get_cell_buffer()); VecCell& cells = *cells_buffers[i].back(); cells.reserve(PARALLEL_BUFFER_SIZE); - for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != end; ) + for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != last; ) { - CellType c(*it); + CellType c(it); if (!cm.is_marked(c)) { cm.mark(c); cells.push_back(c); ++k; } - ++it; + next(it, mask); } // launch thread futures[i].push_back(thread_pool->enqueue([&cells, &f] (unsigned int th_id) @@ -1452,11 +1342,11 @@ class MapBase : public MapBaseData using CellType = typename function_traits::template arg<0>::type; DartMarker dm(*to_concrete()); - for (const_iterator it = this->begin(mask), end = this->end(mask); it != end; ++it) + for (Dart it = begin(mask), last = end(); it != last; next(it, mask)) { - if (!dm.is_marked(*it)) + if (!dm.is_marked(it)) { - CellType c(*it); + CellType c(it); dm.mark_orbit(c); if(!f(c)) break; @@ -1471,9 +1361,9 @@ class MapBase : public MapBaseData static const Orbit ORBIT = CellType::ORBIT; CellMarker cm(*to_concrete()); - for (const_iterator it = this->begin(mask), end = this->end(mask); it != end; ++it) + for (Dart it = begin(mask), last = end(); it != last; next(it, mask)) { - CellType c(*it); + CellType c(it); if (!cm.is_marked(c)) { cm.mark(c); From 45bb9b1619683a7488df1334186c51974ea15d9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 16 Mar 2016 12:02:13 +0100 Subject: [PATCH 330/402] fixed orientation of triangular prism. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/volume_import.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cgogn/io/volume_import.h b/cgogn/io/volume_import.h index d7600acb..1f96c2ff 100644 --- a/cgogn/io/volume_import.h +++ b/cgogn/io/volume_import.h @@ -71,12 +71,12 @@ * `\.' `\` * 1----------------2 * -*-->Prisms: First the indices of one of the triangular face then the indices of the opposite face (same order). The orientation is checked when calling add_prism. +*-->Triangular prisms: First the indices of one of the triangular face then the indices of the opposite face (same order). The orientation is checked when calling add_triangular_prism. * 3 * ,/|`\ * ,/ | `\ * ,/ | `\ -*4------+------5 +*5------+------4 *| | | *| | | *| | | @@ -86,7 +86,7 @@ *| ,/ `\ | *| ,/ `\ | *|,/ `\| -*1-------------2 +*2-------------1 * *-->Hexas: First the indices of one face then the indices of the opposite face (same order). The orientation is checked when calling add_hexa. *7----------6 From 8bd100afe179d90fb7b7fc5c34a36bfbf59728c0 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Wed, 16 Mar 2016 12:35:32 +0100 Subject: [PATCH 331/402] do while :) --- cgogn/core/cmap/map_base.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index fc341993..14cfc902 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -640,9 +640,9 @@ class MapBase : public MapBaseData { Dart end = Dart(this->topology_.end()); - this->topology_.next(d.index); - while (d != end && !mask(d)) + do { this->topology_.next(d.index); + } while (d != end && !mask(d)) } inline Dart end() const From 024a46ec6467a6b21aab297ef9ee38549fea4509 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Wed, 16 Mar 2016 13:14:46 +0100 Subject: [PATCH 332/402] typo --- cgogn/core/cmap/map_base.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 14cfc902..e357897b 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -642,7 +642,7 @@ class MapBase : public MapBaseData do { this->topology_.next(d.index); - } while (d != end && !mask(d)) + } while (d != end && !mask(d)); } inline Dart end() const From fa9057d1a9d1a672e1c6214a846f2aa4dfc74ba9 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Wed, 16 Mar 2016 13:36:38 +0100 Subject: [PATCH 333/402] Trying a specialization ... --- cgogn/core/cmap/map_base.h | 46 ++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index e357897b..551f1f98 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -651,19 +651,31 @@ class MapBase : public MapBaseData } /*! - * \Brief Methods to iterate over all darts. - * All darts are traversed (lying on the boundary or not). + * \Brief Specialized methods to iterate over all darts. + * All darts are traversed without any MASK filtering. */ - inline Dart begin() const + inline Dart begin(const bool&) const { - return Dart(this->topology_.begin()); + Dart d = Dart(this->topology_.begin()); + + return d; } - inline void next(Dart& d) const + inline void next(Dart& d, const bool&) const { this->topology_.next(d.index); } +// inline Dart begin() const +// { +// return Dart(this->topology_.begin()); +// } + +// inline void next(Dart& d) const +// { +// this->topology_.next(d.index); +// } + public: /** @@ -683,25 +695,31 @@ class MapBase : public MapBaseData foreach_dart(f, [this] (Dart d) { return this->is_boundary(d); }); } + template + inline void foreach_dart_nomask(const FUNC& f) const + { + foreach_dart(f, true); + } + template inline void foreach_dart(const FUNC& f, const MASK& mask) const { static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); - static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); - static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); +// static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); +// static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); for (Dart it = begin(mask), last = end(); it != last; next(it, mask)) f(it); } - template - inline void foreach_dart_nomask(const FUNC& f) const - { - static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); +// template +// inline void foreach_dart_nomask(const FUNC& f) const +// { +// static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); - for (Dart it = begin(), last = end(); it != last; next(it)) - f(it); - } +// for (Dart it = begin(), last = end(); it != last; next(it)) +// f(it); +// } template inline void parallel_foreach_dart(const FUNC& f) const From 8da6184a70de727819c84d720a670b4771ba0c22 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Wed, 16 Mar 2016 16:27:47 +0100 Subject: [PATCH 334/402] Trying another template approach ... --- cgogn/core/cmap/cmap2_builder.h | 2 +- cgogn/core/cmap/cmap3_builder.h | 2 +- cgogn/core/cmap/map_base.h | 412 ++++++++------------------- cgogn/core/tests/cmap/cmap2_test.cpp | 14 +- 4 files changed, 120 insertions(+), 310 deletions(-) diff --git a/cgogn/core/cmap/cmap2_builder.h b/cgogn/core/cmap/cmap2_builder.h index 59c165c9..bccad9cd 100644 --- a/cgogn/core/cmap/cmap2_builder.h +++ b/cgogn/core/cmap/cmap2_builder.h @@ -200,7 +200,7 @@ class CMap2Builder_T inline void close_map() { std::vector fix_point_darts; - map_.foreach_dart_nomask( [&] (Dart d) + map_.template foreach_dart( [&] (Dart d) { if (map_.phi2(d) == d) fix_point_darts.push_back(d); diff --git a/cgogn/core/cmap/cmap3_builder.h b/cgogn/core/cmap/cmap3_builder.h index 97473843..641ad922 100644 --- a/cgogn/core/cmap/cmap3_builder.h +++ b/cgogn/core/cmap/cmap3_builder.h @@ -185,7 +185,7 @@ class CMap3Builder_T { // Search the map for topological holes (fix points of phi3) std::vector fix_point_darts; - map_.foreach_dart_nomask( [&] (Dart d) + map_.template foreach_dart( [&] (Dart d) { if (map_.phi3(d) == d) fix_point_darts.push_back(d); diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 551f1f98..09e039d2 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -339,16 +339,12 @@ class MapBase : public MapBaseData this->embeddings_[ORBIT] = ca; // initialize all darts indices to EMBNULL for this ORBIT - foreach_dart( - [this, ca] (Dart d) { (*ca)[d.index] = EMBNULL; }, - [] (Dart) { return true; } - ); + foreach_dart( + [this, ca] (Dart d) { (*ca)[d.index] = EMBNULL; }); // initialize the indices of the existing orbits - foreach_cell( - [this] (Cell c) { new_orbit_embedding(c); }, - [] (Dart) { return true; } - ); + foreach_cell( + [this] (Cell c) { new_orbit_embedding(c); }); cgogn_assert(check_map_integrity()); } @@ -417,8 +413,7 @@ class MapBase : public MapBaseData counter[i] = 0; // Check that the indexation of cells is correct - foreach_cell_until_dart_marking( - [&] (CellType c) + foreach_cell_until_dart_marking( [&] (CellType c) { unsigned int idx = this->get_embedding(c); // check used indices are valid @@ -447,9 +442,7 @@ class MapBase : public MapBaseData }); return result; - }, - [] (Dart) { return true; } - ); + }); // check that all cells present in the attribute handler are used if (result) { @@ -616,6 +609,32 @@ class MapBase : public MapBaseData * Traversals *******************************************************************************/ +public: + + enum Mask: unsigned int + { + NOMASK = 0, + BOUNDARY, + NOBOUNDARY + }; + + template + inline bool is_masked(Dart d) const { + switch (MASK) { + case NOMASK: + return true; + break; + case BOUNDARY: + return this->is_boundary(d); + break; + case NOBOUNDARY: + return !this->is_boundary(d); + break; + default: + break; + } + } + protected: /*! @@ -623,26 +642,31 @@ class MapBase : public MapBaseData * A MASK is an functor that determine if a dart should be traversed or skipped. * It return false when a dart should be skipped, true in other cases. */ - template - inline Dart begin(const MASK& mask) const + template + inline Dart begin() const { Dart d = Dart(this->topology_.begin()); - Dart end = Dart(this->topology_.end()); - while (d != end && !mask(d)) - this->topology_.next(d.index); + if (MASK != NOMASK) { + Dart end = Dart(this->topology_.end()); + + while (d != end && !is_masked(d)) + this->topology_.next(d.index); + } return d; } - template - inline void next(Dart& d, const MASK& mask) const + template + inline void next(Dart& d) const { - Dart end = Dart(this->topology_.end()); + this->topology_.next(d.index); - do { - this->topology_.next(d.index); - } while (d != end && !mask(d)); + if (MASK != NOMASK) { + Dart end = Dart(this->topology_.end()); + while (d != end && !is_masked(d)) + this->topology_.next(d.index); + } } inline Dart end() const @@ -650,32 +674,6 @@ class MapBase : public MapBaseData return Dart(this->topology_.end()); } - /*! - * \Brief Specialized methods to iterate over all darts. - * All darts are traversed without any MASK filtering. - */ - inline Dart begin(const bool&) const - { - Dart d = Dart(this->topology_.begin()); - - return d; - } - - inline void next(Dart& d, const bool&) const - { - this->topology_.next(d.index); - } - -// inline Dart begin() const -// { -// return Dart(this->topology_.begin()); -// } - -// inline void next(Dart& d) const -// { -// this->topology_.next(d.index); -// } - public: /** @@ -683,63 +681,20 @@ class MapBase : public MapBaseData * @tparam FUNC type of the callable * @param f a callable */ - template + template inline void foreach_dart(const FUNC& f) const - { - foreach_dart(f, [this] (Dart d) { return !this->is_boundary(d); }); - } - - template - inline void foreach_boundary_dart(const FUNC& f) const - { - foreach_dart(f, [this] (Dart d) { return this->is_boundary(d); }); - } - - template - inline void foreach_dart_nomask(const FUNC& f) const - { - foreach_dart(f, true); - } - - template - inline void foreach_dart(const FUNC& f, const MASK& mask) const { static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); -// static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); -// static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); - for (Dart it = begin(mask), last = end(); it != last; next(it, mask)) + for (Dart it = begin(), last = end(); it != last; next(it)) f(it); } -// template -// inline void foreach_dart_nomask(const FUNC& f) const -// { -// static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); - -// for (Dart it = begin(), last = end(); it != last; next(it)) -// f(it); -// } - - template + template inline void parallel_foreach_dart(const FUNC& f) const - { - parallel_foreach_dart(f, [this] (Dart d) { return !this->is_boundary(d); }); - } - - template - inline void parallel_foreach_boundary_dart(const FUNC& f) const - { - parallel_foreach_dart(f, [this] (Dart d) { return this->is_boundary(d); }); - } - - template - inline void parallel_foreach_dart(const FUNC& f, const MASK& mask) const { static_assert(check_func_ith_parameter_type(FUNC, 0, Dart), "Wrong function first parameter type"); static_assert(check_func_ith_parameter_type(FUNC, 1, unsigned int), "Wrong function second parameter type"); - static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); - static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); using Future = std::future::type>; using VecDarts = std::vector; @@ -756,7 +711,7 @@ class MapBase : public MapBaseData Buffers* dbuffs = cgogn::get_dart_buffers(); - Dart it = begin(mask); + Dart it = begin(); Dart last = end(); while (it != last) @@ -772,76 +727,7 @@ class MapBase : public MapBaseData for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != last; ++k) { darts.push_back(it); - next(it, mask); - } - - futures[i].push_back(thread_pool->enqueue([&darts, &f] (unsigned int th_id) - { - for (auto d : darts) - f(d, th_id); - })); - } - - const unsigned int id = (i+1u) % 2u; - - for (auto& fu : futures[id]) - fu.wait(); - for (auto& b : dart_buffers[id]) - dbuffs->release_cell_buffer(b); - - futures[id].clear(); - dart_buffers[id].clear(); - - // if we reach the end of the map while filling buffers from the second set we need to clean them too. - if (it == last && i == 1u) - { - for (auto& fu : futures[1u]) - fu.wait(); - for (auto &b : dart_buffers[1u]) - dbuffs->release_buffer(b); - } - } - } - } - - template - inline void parallel_foreach_dart_nomask(const FUNC& f) const - { - static_assert(check_func_ith_parameter_type(FUNC, 0, Dart), "Wrong function first parameter type"); - static_assert(check_func_ith_parameter_type(FUNC, 1, unsigned int), "Wrong function second parameter type"); - - using Future = std::future::type>; - using VecDarts = std::vector; - - ThreadPool* thread_pool = cgogn::get_thread_pool(); - const std::size_t nb_threads_pool = thread_pool->get_nb_threads(); - - std::array, 2> dart_buffers; - std::array, 2> futures; - dart_buffers[0].reserve(nb_threads_pool); - dart_buffers[1].reserve(nb_threads_pool); - futures[0].reserve(nb_threads_pool); - futures[1].reserve(nb_threads_pool); - - Buffers* dbuffs = cgogn::get_dart_buffers(); - - Dart it = begin(); - Dart last = end(); - - while (it != last) - { - for (unsigned int i = 0u; i < 2u; ++i) - { - for (unsigned int j = 0u; j < nb_threads_pool && it != last; ++j) - { - dart_buffers[i].push_back(dbuffs->get_buffer()); - cgogn_assert(dart_buffers[i].size() <= nb_threads_pool); - std::vector& darts = *dart_buffers[i].back(); - darts.reserve(PARALLEL_BUFFER_SIZE); - for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != last; ++k) - { - darts.push_back(it); - next(it); + next(it); } futures[i].push_back(thread_pool->enqueue([&darts, &f] (unsigned int th_id) @@ -878,40 +764,13 @@ class MapBase : public MapBaseData * @tparam FUNC type of the callable * @param f a callable */ - template + template inline void foreach_dart_until(const FUNC& f) const - { - foreach_dart_until(f, [this] (Dart d) { return !this->is_boundary(d); }); - } - - template - inline void foreach_boundary_dart_until(const FUNC& f) const - { - foreach_dart_until(f, [this] (Dart d) { return this->is_boundary(d); }); - } - - template - inline void foreach_dart_until(const FUNC& f, const MASK& mask) const - { - static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); - static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); - static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); - static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); - - for (Dart it = begin(mask), last = end(); it != last; next(it, mask)) - { - if (!f(it)) - break; - } - } - - template - inline void foreach_dart_until_nomask(const FUNC& f) const { static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); - for (Dart it = begin(), last = end(); it != last; next(it)) + for (Dart it = begin(), last = end(); it != last; next(it)) { if (!f(it)) break; @@ -923,73 +782,38 @@ class MapBase : public MapBaseData * @tparam FUNC type of the callable * @param f a callable */ - template + template inline void foreach_cell(const FUNC& f) const { - foreach_cell(f, [this] (Dart d) { return !this->is_boundary(d); }); - } - - template - inline void foreach_cell_nomask(const FUNC& f) const - { - foreach_cell(f, [this] (Dart) { return true; }); - } - - template - inline void foreach_boundary_cell(const FUNC& f) const - { - foreach_cell(f, [this] (Dart d) { return this->is_boundary(d); }); - } - - template - inline void foreach_cell(const FUNC& f, const MASK& mask) const - { - static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); - static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); - using CellType = typename function_traits::template arg<0>::type; static const Orbit ORBIT = CellType::ORBIT; switch (STRATEGY) { case FORCE_DART_MARKING : - foreach_cell_dart_marking(f, mask); + foreach_cell_dart_marking(f); break; case FORCE_CELL_MARKING : - foreach_cell_cell_marking(f, mask); + foreach_cell_cell_marking(f); break; case FORCE_TOPO_CACHE : - foreach_cell_topo_cache(f, mask); + foreach_cell_topo_cache(f); break; case AUTO : if (is_topo_cache_enabled()) - foreach_cell_topo_cache(f, mask); + foreach_cell_topo_cache(f); else if (this->template is_embedded()) - foreach_cell_cell_marking(f, mask); + foreach_cell_cell_marking(f); else - foreach_cell_dart_marking(f, mask); + foreach_cell_dart_marking(f); break; } } - template + template inline void parallel_foreach_cell(const FUNC& f) const - { - parallel_foreach_cell(f, [this] (Dart d) { return !this->is_boundary(d); }); - } - - template - inline void parallel_foreach_boundary_cell(const FUNC& f) const - { - parallel_foreach_cell(f, [this] (Dart d) { return this->is_boundary(d); }); - } - - template - inline void parallel_foreach_cell(const FUNC& f, const MASK& mask) const { static_assert(check_func_ith_parameter_type(FUNC, 1, unsigned int), "Wrong function second parameter type"); - static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); - static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); using CellType = typename function_traits::template arg<0>::type; static const Orbit ORBIT = CellType::ORBIT; @@ -997,21 +821,21 @@ class MapBase : public MapBaseData switch (STRATEGY) { case FORCE_DART_MARKING : - parallel_foreach_cell_dart_marking(f, mask); + parallel_foreach_cell_dart_marking(f); break; case FORCE_CELL_MARKING : - parallel_foreach_cell_cell_marking(f, mask); + parallel_foreach_cell_cell_marking(f); break; case FORCE_TOPO_CACHE : - parallel_foreach_cell_topo_cache(f, mask); + parallel_foreach_cell_topo_cache(f); break; case AUTO : if (is_topo_cache_enabled()) - parallel_foreach_cell_topo_cache(f, mask); + parallel_foreach_cell_topo_cache(f); else if (this->template is_embedded()) - parallel_foreach_cell_cell_marking(f, mask); + parallel_foreach_cell_cell_marking(f); else - parallel_foreach_cell_dart_marking(f, mask); + parallel_foreach_cell_dart_marking(f); break; } } @@ -1021,24 +845,10 @@ class MapBase : public MapBaseData * @tparam FUNC type of the callable * @param f a callable */ - template - inline void foreach_cell_until(const FUNC& f) const - { - foreach_cell_until(f, [this] (Dart d) { return !this->is_boundary(d); }); - } - - template - inline void foreach_boundary_cell_until(const FUNC& f) const - { - foreach_cell_until(f, [this] (Dart d) { return this->is_boundary(d); }); - } - - template - void foreach_cell_until(const FUNC& f, const MASK& mask) const + template + void foreach_cell_until(const FUNC& f) const { static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); - static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); - static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); using CellType = typename function_traits::template arg<0>::type; static const Orbit ORBIT = CellType::ORBIT; @@ -1046,34 +856,34 @@ class MapBase : public MapBaseData switch (STRATEGY) { case FORCE_DART_MARKING : - foreach_cell_until_dart_marking(f, mask); + foreach_cell_until_dart_marking(f); break; case FORCE_CELL_MARKING : - foreach_cell_until_cell_marking(f, mask); + foreach_cell_until_cell_marking(f); break; case FORCE_TOPO_CACHE : - foreach_cell_until_topo_cache(f, mask); + foreach_cell_until_topo_cache(f); break; case AUTO : if (is_topo_cache_enabled()) - foreach_cell_until_topo_cache(f, mask); + foreach_cell_until_topo_cache(f); else if (this->template is_embedded()) - foreach_cell_until_cell_marking(f, mask); + foreach_cell_until_cell_marking(f); else - foreach_cell_until_dart_marking(f, mask); + foreach_cell_until_dart_marking(f); break; } } protected: - template - inline void foreach_cell_dart_marking(const FUNC& f, const MASK& mask) const + template + inline void foreach_cell_dart_marking(const FUNC& f) const { using CellType = typename function_traits::template arg<0>::type; DartMarker dm(*to_concrete()); - for (Dart it = begin(mask), last = end(); it != last; next(it, mask)) + for (Dart it = begin(), last = end(); it != last; next(it)) { if (!dm.is_marked(it)) { @@ -1084,8 +894,8 @@ class MapBase : public MapBaseData } } - template - inline void parallel_foreach_cell_dart_marking(const FUNC& f, const MASK& mask) const + template + inline void parallel_foreach_cell_dart_marking(const FUNC& f) const { using CellType = typename function_traits::template arg<0>::type; static const Orbit ORBIT = CellType::ORBIT; @@ -1106,7 +916,7 @@ class MapBase : public MapBaseData Buffers* dbuffs = cgogn::get_dart_buffers(); DartMarker dm(*to_concrete()); - Dart it = begin(mask); + Dart it = begin(); Dart last = end(); unsigned int i = 0u; // buffer id (0/1) @@ -1126,7 +936,7 @@ class MapBase : public MapBaseData cells.push_back(c); ++k; } - next(it, mask); + next(it); } //launch thread futures[i].push_back(thread_pool->enqueue([&cells, &f] (unsigned int th_id) @@ -1159,14 +969,14 @@ class MapBase : public MapBaseData dbuffs->release_cell_buffer(b); } - template - inline void foreach_cell_cell_marking(const FUNC& f, const MASK& mask) const + template + inline void foreach_cell_cell_marking(const FUNC& f) const { using CellType = typename function_traits::template arg<0>::type; static const Orbit ORBIT = CellType::ORBIT; CellMarker cm(*to_concrete()); - for (Dart it = begin(mask), last = end(); it != last; next(it, mask)) + for (Dart it = begin(), last = end(); it != last; next(it)) { CellType c(it); if (!cm.is_marked(c)) @@ -1177,8 +987,8 @@ class MapBase : public MapBaseData } } - template - inline void parallel_foreach_cell_cell_marking(const FUNC& f, const MASK& mask) const + template + inline void parallel_foreach_cell_cell_marking(const FUNC& f) const { using CellType = typename function_traits::template arg<0>::type; static const Orbit ORBIT = CellType::ORBIT; @@ -1199,7 +1009,7 @@ class MapBase : public MapBaseData Buffers* dbuffs = cgogn::get_dart_buffers(); CellMarker cm(*to_concrete()); - Dart it = begin(mask); + Dart it = begin(); Dart last = end(); unsigned int i = 0u; // buffer id (0/1) @@ -1219,7 +1029,7 @@ class MapBase : public MapBaseData cells.push_back(c); ++k; } - next(it, mask); + next(it); } // launch thread futures[i].push_back(thread_pool->enqueue([&cells, &f] (unsigned int th_id) @@ -1252,8 +1062,8 @@ class MapBase : public MapBaseData dbuffs->release_cell_buffer(b); } - template - inline void foreach_cell_topo_cache(const FUNC& f, const MASK& mask) const + template + inline void foreach_cell_topo_cache(const FUNC& f) const { using CellType = typename function_traits::template arg<0>::type; static const Orbit ORBIT = CellType::ORBIT; @@ -1264,7 +1074,7 @@ class MapBase : public MapBaseData unsigned int it = attr.begin(); const unsigned int end = attr.end(); // find first valid dart in the topo cache - while (it != end && !mask(cache[it])) + while (it != end && !is_masked(cache[it])) { attr.next(it); } @@ -1276,12 +1086,12 @@ class MapBase : public MapBaseData do { attr.next(it); - } while (it != end && !mask(cache[it])); + } while (it != end && !is_masked(cache[it])); } } - template - inline void parallel_foreach_cell_topo_cache(const FUNC& f, const MASK& mask) const + template + inline void parallel_foreach_cell_topo_cache(const FUNC& f) const { using CellType = typename function_traits::template arg<0>::type; static const Orbit ORBIT = CellType::ORBIT; @@ -1302,7 +1112,7 @@ class MapBase : public MapBaseData unsigned int it = attr.begin(); const unsigned int end = attr.end(); // find first valid dart in the topo cache - while (it != end && !mask(cache[it])) + while (it != end && !is_masked(cache[it])) { attr.next(it); } @@ -1317,11 +1127,11 @@ class MapBase : public MapBaseData unsigned int local_end = std::min(it+nbc, end); unsigned int i = 0; // used buffered futures 0/1 - unsigned int j = 0; // thread num + unsigned int j = 0; // thread num, const MASK& mask while (it != end) { - futures[i].push_back(thread_pool->enqueue([&cache, &attr, &mask, it, local_end, &f] (unsigned int th_id) + futures[i].push_back(thread_pool->enqueue([&cache, &attr, it, local_end, &f] (unsigned int th_id) { unsigned int loc_it = it; while (loc_it < local_end) @@ -1330,7 +1140,7 @@ class MapBase : public MapBaseData do { attr.next(loc_it); - } while (loc_it != local_end && !mask(cache[loc_it])); + } while (loc_it != local_end && !is_masked(cache[loc_it])); } })); it = local_end; @@ -1354,13 +1164,13 @@ class MapBase : public MapBaseData fu.wait(); } - template - inline void foreach_cell_until_dart_marking(const FUNC& f, const MASK& mask) const + template + inline void foreach_cell_until_dart_marking(const FUNC& f) const { using CellType = typename function_traits::template arg<0>::type; DartMarker dm(*to_concrete()); - for (Dart it = begin(mask), last = end(); it != last; next(it, mask)) + for (Dart it = begin(), last = end(); it != last; next(it)) { if (!dm.is_marked(it)) { @@ -1372,14 +1182,14 @@ class MapBase : public MapBaseData } } - template - inline void foreach_cell_until_cell_marking(const FUNC& f, const MASK& mask) const + template + inline void foreach_cell_until_cell_marking(const FUNC& f) const { using CellType = typename function_traits::template arg<0>::type; static const Orbit ORBIT = CellType::ORBIT; CellMarker cm(*to_concrete()); - for (Dart it = begin(mask), last = end(); it != last; next(it, mask)) + for (Dart it = begin(), last = end(); it != last; next(it)) { CellType c(it); if (!cm.is_marked(c)) @@ -1391,8 +1201,8 @@ class MapBase : public MapBaseData } } - template - inline void foreach_cell_until_topo_cache(const FUNC& f, const MASK& mask) const + template + inline void foreach_cell_until_topo_cache(const FUNC& f) const { using CellType = typename function_traits::template arg<0>::type; static const Orbit ORBIT = CellType::ORBIT; @@ -1404,7 +1214,7 @@ class MapBase : public MapBaseData const unsigned int end = attr.end(); Dart d = cache[it]; // find first valid dart in the topo cache - while (it != end && !mask.valid(d)) + while (it != end && !is_masked(d)) { attr.next(it); d = cache[it]; @@ -1419,7 +1229,7 @@ class MapBase : public MapBaseData { attr.next(it); d = cache[it]; - } while (it != end && !mask.valid(d)); + } while (it != end && !is_masked(d)); } } }; diff --git a/cgogn/core/tests/cmap/cmap2_test.cpp b/cgogn/core/tests/cmap/cmap2_test.cpp index fab9b7ec..070c6220 100644 --- a/cgogn/core/tests/cmap/cmap2_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_test.cpp @@ -133,28 +133,28 @@ class CMap2Test : public ::testing::Test } } // Close the map (remove remaining boundary) - cmap_.foreach_dart_nomask( [&] (Dart d) + cmap_.template foreach_dart( [&] (Dart d) { if (cmap_.phi2(d) == d) mbuild.close_hole_topo(d); }); // Embed the map - cmap_.foreach_dart_nomask( [&] (Dart d) + cmap_.template foreach_cell( [&] (CDart d) { - mbuild.new_orbit_embedding(CDart(d)); + mbuild.new_orbit_embedding(d); }); - cmap_.foreach_cell_nomask( [&] (Vertex v) + cmap_.template foreach_cell( [&] (Vertex v) { mbuild.new_orbit_embedding(v); }); - cmap_.foreach_cell_nomask( [&] (Edge e) + cmap_.template foreach_cell( [&] (Edge e) { mbuild.new_orbit_embedding(e); }); - cmap_.foreach_cell_nomask( [&] (Face f) + cmap_.template foreach_cell( [&] (Face f) { mbuild.new_orbit_embedding(f); }); - cmap_.foreach_cell_nomask( [&] (Volume w) + cmap_.template foreach_cell( [&] (Volume w) { mbuild.new_orbit_embedding(w); }); From 75d083b6e5e03b045f6040b5135d6b8c025ae4d9 Mon Sep 17 00:00:00 2001 From: David Cazier Date: Wed, 16 Mar 2016 16:59:04 +0100 Subject: [PATCH 335/402] typos --- cgogn/core/cmap/map_base.h | 1 + 1 file changed, 1 insertion(+) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 09e039d2..2fe96489 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -631,6 +631,7 @@ class MapBase : public MapBaseData return !this->is_boundary(d); break; default: + cgogn_assert_not_reached("Undefined MASK"); break; } } From 1edb56f0de7b08b0f996f658cbe309526838f12c Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Wed, 16 Mar 2016 19:00:24 +0100 Subject: [PATCH 336/402] rendering of 3map --- cgogn/core/cmap/cmap3.h | 2 +- cgogn/rendering/CMakeLists.txt | 6 + cgogn/rendering/examples/viewer_topo3.cpp | 63 +++- .../shaders/shader_explode_volumes.cpp | 233 ++++++++++++++ .../shaders/shader_explode_volumes.h | 88 ++++++ .../shaders/shader_explode_volumes_line.cpp | 142 +++++++++ .../shaders/shader_explode_volumes_line.h | 79 +++++ cgogn/rendering/topo_render.cpp | 2 +- cgogn/rendering/topo_render.h | 4 + cgogn/rendering/volume_render.cpp | 128 ++++++++ cgogn/rendering/volume_render.h | 297 ++++++++++++++++++ 11 files changed, 1027 insertions(+), 17 deletions(-) create mode 100644 cgogn/rendering/shaders/shader_explode_volumes.cpp create mode 100644 cgogn/rendering/shaders/shader_explode_volumes.h create mode 100644 cgogn/rendering/shaders/shader_explode_volumes_line.cpp create mode 100644 cgogn/rendering/shaders/shader_explode_volumes_line.h create mode 100644 cgogn/rendering/volume_render.cpp create mode 100644 cgogn/rendering/volume_render.h diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 3598e14e..c87bad79 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -594,7 +594,7 @@ class CMap3_T : public CMap2_T { static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); // Inherit::foreach_incident_edge(v, func); - Inherit::foreach_incident_face(v, [&func] (Edge2 e) + Inherit::foreach_incident_edge(v, [&func] (Edge2 e) { func(Edge(e.dart)); }); diff --git a/cgogn/rendering/CMakeLists.txt b/cgogn/rendering/CMakeLists.txt index c4b82ee6..521ed292 100644 --- a/cgogn/rendering/CMakeLists.txt +++ b/cgogn/rendering/CMakeLists.txt @@ -18,8 +18,11 @@ set(HEADER_FILES shaders/shader_bold_line.h shaders/shader_round_point.h shaders/shader_point_sprite.h + shaders/shader_explode_volumes.h + shaders/shader_explode_volumes_line.h drawer.h topo_render.h + volume_render.h ) set(SOURCE_FILES @@ -32,8 +35,11 @@ set(SOURCE_FILES shaders/shader_bold_line.cpp shaders/shader_round_point.cpp shaders/shader_point_sprite.cpp + shaders/shader_explode_volumes.cpp + shaders/shader_explode_volumes_line.cpp drawer.cpp topo_render.cpp + volume_render.cpp ) add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) diff --git a/cgogn/rendering/examples/viewer_topo3.cpp b/cgogn/rendering/examples/viewer_topo3.cpp index 97324b23..18fef136 100644 --- a/cgogn/rendering/examples/viewer_topo3.cpp +++ b/cgogn/rendering/examples/viewer_topo3.cpp @@ -35,9 +35,10 @@ #include #include #include -#include +//#include +//#include -#include +#include #include @@ -77,10 +78,14 @@ class Viewer : public QOGLViewer cgogn::rendering::ShaderFlat* shader_flat_; cgogn::rendering::TopoRender* topo_render; + cgogn::rendering::VolumeRender* volume_render; - bool flat_rendering_; + bool vol_rendering_; + bool edge_rendering_; bool topo_rendering_; + float expl_; + }; @@ -122,19 +127,37 @@ Viewer::Viewer() : vbo_pos_(nullptr), shader_flat_(nullptr), topo_render(nullptr), - flat_rendering_(true), - topo_rendering_(true) + vol_rendering_(true), + edge_rendering_(true), + topo_rendering_(true), + expl_(0.7) {} void Viewer::keyPressEvent(QKeyEvent *ev) { switch (ev->key()) { - case Qt::Key_F: - flat_rendering_ = !flat_rendering_; + case Qt::Key_V: + vol_rendering_ = !vol_rendering_; + break; + case Qt::Key_E: + edge_rendering_ = !edge_rendering_; break; + case Qt::Key_T: topo_rendering_ = !topo_rendering_; break; + case Qt::Key_Plus: + expl_ += 0.05; + volume_render->set_explode_volume(expl_); + topo_render->set_explode_volume(expl_); + topo_render->update_map3(map_,vertex_position_); + break; + case Qt::Key_Minus: + expl_ -= 0.05; + volume_render->set_explode_volume(expl_); + topo_render->set_explode_volume(expl_); + topo_render->update_map3(map_,vertex_position_); + break; default: break; } @@ -151,19 +174,27 @@ void Viewer::draw() camera()->getProjectionMatrix(proj); camera()->getModelViewMatrix(view); - if (flat_rendering_) + if (vol_rendering_) { glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(1.0f, 1.0f); - shader_flat_->bind(); - shader_flat_->set_matrices(proj,view); - shader_flat_->bind_vao(0); - render_->draw(cgogn::rendering::TRIANGLES); - shader_flat_->release_vao(0); - shader_flat_->release(); + +// shader_flat_->bind(); +// shader_flat_->set_matrices(proj,view); +// shader_flat_->bind_vao(0); +// render_->draw(cgogn::rendering::TRIANGLES); +// shader_flat_->release_vao(0); +// shader_flat_->release(); + + volume_render->draw_faces(proj,view); + glDisable(GL_POLYGON_OFFSET_FILL); } + if (edge_rendering_) + volume_render->draw_edges(proj,view); + + if (topo_rendering_) { topo_render->draw(proj,view); @@ -195,7 +226,9 @@ void Viewer::init() topo_render = new cgogn::rendering::TopoRender(this); topo_render->update_map3(map_,vertex_position_); - + volume_render = new cgogn::rendering::VolumeRender(this); + volume_render->update_face(map_,vertex_position_); + volume_render->update_edge(map_,vertex_position_); } int main(int argc, char** argv) diff --git a/cgogn/rendering/shaders/shader_explode_volumes.cpp b/cgogn/rendering/shaders/shader_explode_volumes.cpp new file mode 100644 index 00000000..517e08bb --- /dev/null +++ b/cgogn/rendering/shaders/shader_explode_volumes.cpp @@ -0,0 +1,233 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#define CGOGN_RENDERING_DLL_EXPORT + +#include +#include +#include +#include + +namespace cgogn +{ + +namespace rendering +{ + +const char* ShaderExplodeVolumes::vertex_shader_source_ = +"#version 150\n" +"in vec3 vertex_pos;\n" +"void main() {\n" +" gl_Position = vec4(vertex_pos,1.0);\n" +"}\n"; + +const char* ShaderExplodeVolumes::geometry_shader_source_ = +"#version 150\n" +"layout (lines_adjacency) in;\n" +"layout (triangle_strip, max_vertices=3) out;\n" +"out vec3 color_f;\n" +"uniform mat4 projection_matrix;\n" +"uniform mat4 model_view_matrix;\n" +"uniform mat3 normal_matrix;\n" +"uniform float explode_vol;\n" +"uniform vec3 light_position;\n" +"uniform vec4 color;\n" +"uniform vec4 plane_clip;\n" +"void main()\n" +"{\n" +" float d = dot(plane_clip,gl_in[0].gl_Position);\n" +" if (d<=0.0)\n" +" {\n" +" vec3 v1 = gl_in[2].gl_Position.xyz - gl_in[1].gl_Position.xyz;\n" +" vec3 v2 = gl_in[3].gl_Position.xyz - gl_in[1].gl_Position.xyz;\n" +" vec3 N = normalize(normal_matrix*cross(v1,v2));\n" +" vec4 face_center = model_view_matrix * gl_in[1].gl_Position;\n" +" vec3 L = normalize (light_position - face_center.xyz);\n" +" float lambertTerm = abs(dot(N,L));\n" +" for (int i=1; i<=3; i++)\n" +" {\n" +" vec4 Q = explode_vol * gl_in[i].gl_Position + (1.0-explode_vol) * gl_in[0].gl_Position;\n" +" gl_Position = projection_matrix * model_view_matrix * Q;\n" +" color_f = color.rgb * lambertTerm;\n" +" EmitVertex();\n" +" }\n" +" EndPrimitive();\n" +" }\n" +"}\n"; + + +const char* ShaderExplodeVolumes::fragment_shader_source_ = +"#version 150\n" +"in vec3 color_f;\n" +"out vec3 fragColor;\n" +"void main() {\n" +" fragColor = color_f;\n" +"}\n"; + +const char* ShaderExplodeVolumes::vertex_shader_source2_ = +"#version 150\n" +"in vec3 vertex_pos;\n" +"in vec3 vertex_color;\n" +"out vec3 color_v;\n" +"void main() {\n" +" color_v = vertex_color;\n" +" gl_Position = vec4(vertex_pos,1.0);\n" +"}\n"; + +const char* ShaderExplodeVolumes::geometry_shader_source2_ = +"#version 150\n" +"layout (lines_adjacency) in;\n" +"layout (triangle_strip, max_vertices=3) out;\n" +"in vec3 color_v[];\n" +"out vec3 color_f;\n" +"uniform mat4 projection_matrix;\n" +"uniform mat4 model_view_matrix;\n" +"uniform mat3 normal_matrix;\n" +"uniform float explode_vol;\n" +"uniform vec3 light_position;\n" +"uniform vec4 plane_clip;\n" +"void main()\n" +"{\n" +" float d = dot(plane_clip,gl_in[0].gl_Position);\n" +" if (d<=0.0)\n" +" {\n" +" vec3 v1 = gl_in[2].gl_Position.xyz - gl_in[1].gl_Position.xyz;\n" +" vec3 v2 = gl_in[3].gl_Position.xyz - gl_in[1].gl_Position.xyz;\n" +" vec3 N = normalize(normal_matrix*cross(v1,v2));\n" +" vec4 face_center = model_view_matrix * gl_in[1].gl_Position;\n" +" vec3 L = normalize (light_position - face_center.xyz);\n" +" float lambertTerm = abs(dot(N,L));\n" +" for (int i=1; i<=3; i++)\n" +" {\n" +" vec4 Q = explode_vol * gl_in[i].gl_Position + (1.0-explode_vol) * gl_in[0].gl_Position;\n" +" gl_Position = projection_matrix * model_view_matrix * Q;\n" +" color_f = color_v[i]*lambertTerm;\n" +" EmitVertex();\n" +" }\n" +" EndPrimitive();\n" +" }\n" +"}\n"; + + +const char* ShaderExplodeVolumes::fragment_shader_source2_ = +"#version 150\n" +"in vec3 color_f;\n" +"out vec3 fragColor;\n" +"void main() {\n" +" fragColor = color_f;\n" +"}\n"; + + +ShaderExplodeVolumes::ShaderExplodeVolumes(bool color_per_vertex) +{ + if (color_per_vertex) + { + prg_.addShaderFromSourceCode(QOpenGLShader::Vertex, vertex_shader_source2_); + prg_.addShaderFromSourceCode(QOpenGLShader::Geometry, geometry_shader_source2_); + prg_.addShaderFromSourceCode(QOpenGLShader::Fragment, fragment_shader_source2_); + prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); + prg_.bindAttributeLocation("vertex_color", ATTRIB_COLOR); + } + else + { + prg_.addShaderFromSourceCode(QOpenGLShader::Vertex, vertex_shader_source_); + prg_.addShaderFromSourceCode(QOpenGLShader::Geometry, geometry_shader_source_); + prg_.addShaderFromSourceCode(QOpenGLShader::Fragment, fragment_shader_source_); + prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); + } + prg_.link(); + get_matrices_uniforms(); + unif_expl_v_ = prg_.uniformLocation("explode_vol"); + unif_plane_clip_ = prg_.uniformLocation("plane_clip"); + unif_light_position_ = prg_.uniformLocation("light_position"); + unif_color_ = prg_.uniformLocation("color"); + + //default param + bind(); + set_light_position(QVector3D(10.0f,100.0f,1000.0f)); + set_explode_volume(0.8f); + set_color(QColor(255,0,0)); + set_plane_clip(QVector4D(0,0,0,0)); + release(); +} + +void ShaderExplodeVolumes::set_color(const QColor& rgb) +{ + if (unif_color_>=0) + prg_.setUniformValue(unif_color_,rgb); +} + +void ShaderExplodeVolumes::set_light_position(const QVector3D& l) +{ + prg_.setUniformValue(unif_light_position_,l); +} + + +void ShaderExplodeVolumes::set_explode_volume(float x) +{ + prg_.setUniformValue(unif_expl_v_, x); +} + +void ShaderExplodeVolumes::set_plane_clip(const QVector4D& plane) +{ + + prg_.setUniformValue(unif_plane_clip_, plane); +} + +bool ShaderExplodeVolumes::set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color) +{ + if (i >= vaos_.size()) + { + std::cerr << "VAO number " << i << " does not exist" << std::endl; + return false; + } + + QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); + + prg_.bind(); + vaos_[i]->bind(); + + // position vbo + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ATTRIB_POS); + ogl->glVertexAttribPointer(ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + + if (vbo_color) + { + // color vbo + vbo_color->bind(); + ogl->glEnableVertexAttribArray(ATTRIB_COLOR); + ogl->glVertexAttribPointer(ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_color->release(); + } + + vaos_[i]->release(); + prg_.release(); + + return true; +} + +} // namespace rendering + +} // namespace cgogn diff --git a/cgogn/rendering/shaders/shader_explode_volumes.h b/cgogn/rendering/shaders/shader_explode_volumes.h new file mode 100644 index 00000000..d49bd71e --- /dev/null +++ b/cgogn/rendering/shaders/shader_explode_volumes.h @@ -0,0 +1,88 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef RENDERING_SHADERS_EXPLODE_VOLUMES_H_ +#define RENDERING_SHADERS_EXPLODE_VOLUMES_H_ + +#include +#include +#include +#include +#include + +namespace cgogn +{ + +namespace rendering +{ + +class CGOGN_RENDERING_API ShaderExplodeVolumes : public ShaderProgram +{ + static const char* vertex_shader_source_; + static const char* geometry_shader_source_; + static const char* fragment_shader_source_; + + static const char* vertex_shader_source2_; + static const char* geometry_shader_source2_; + static const char* fragment_shader_source2_; + + enum + { + ATTRIB_POS = 0, + ATTRIB_COLOR + }; + + // uniform ids + int unif_expl_v_; + int unif_light_position_; + int unif_plane_clip_; + int unif_color_; + + +public: + + ShaderExplodeVolumes(bool color_per_vertex = false); + + void set_explode_volume(float x); + + void set_light_position(const QVector3D& l); + + void set_plane_clip(const QVector4D& plane); + + void set_color(const QColor& rgb); + + /** + * @brief set a vao configuration + * @param i vao id (0,1,...) + * @param vbo_pos pointer on position vbo (XYZ) + * @param vbo_color pointer on color vbo + * @return true if ok + */ + bool set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color = nullptr); +}; + +} // namespace rendering + +} // namespace cgogn + +#endif // RENDERING_SHADERS_EXPLODE_VOLUMES_H_ diff --git a/cgogn/rendering/shaders/shader_explode_volumes_line.cpp b/cgogn/rendering/shaders/shader_explode_volumes_line.cpp new file mode 100644 index 00000000..d89ff992 --- /dev/null +++ b/cgogn/rendering/shaders/shader_explode_volumes_line.cpp @@ -0,0 +1,142 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#define CGOGN_RENDERING_DLL_EXPORT + +#include +#include +#include +#include + +namespace cgogn +{ + +namespace rendering +{ + +const char* ShaderExplodeVolumesLine::vertex_shader_source_ = +"#version 150\n" +"in vec3 vertex_pos;\n" +"void main() {\n" +" gl_Position = vec4(vertex_pos,1.0);\n" +"}\n"; + +const char* ShaderExplodeVolumesLine::geometry_shader_source_ = +"#version 150\n" +"layout (triangles) in;\n" +"layout (line_strip, max_vertices=2) out;\n" +"uniform mat4 projection_matrix;\n" +"uniform mat4 model_view_matrix;\n" +"uniform float explode_vol;\n" +"uniform vec4 plane_clip;\n" +"void main()\n" +"{\n" +" float d = dot(plane_clip,gl_in[0].gl_Position);\n" +" if (d<=0.0)\n" +" {\n" +" for (int i=1; i<=2; i++)\n" +" {\n" +" vec4 Q = explode_vol * gl_in[i].gl_Position + (1.0-explode_vol) * gl_in[0].gl_Position;\n" +" gl_Position = projection_matrix * model_view_matrix * Q;\n" +" EmitVertex();\n" +" }\n" +" EndPrimitive();\n" +" }\n" +"}\n"; + + +const char* ShaderExplodeVolumesLine::fragment_shader_source_ = +"#version 150\n" +"uniform vec4 color;\n" +"out vec4 fragColor;\n" +"void main() {\n" +" fragColor = color;\n" +"}\n"; + + +ShaderExplodeVolumesLine::ShaderExplodeVolumesLine() +{ + prg_.addShaderFromSourceCode(QOpenGLShader::Vertex, vertex_shader_source_); + prg_.addShaderFromSourceCode(QOpenGLShader::Geometry, geometry_shader_source_); + prg_.addShaderFromSourceCode(QOpenGLShader::Fragment, fragment_shader_source_); + prg_.bindAttributeLocation("vertex_pos", ATTRIB_POS); + prg_.link(); + get_matrices_uniforms(); + unif_expl_v_ = prg_.uniformLocation("explode_vol"); + unif_plane_clip_ = prg_.uniformLocation("plane_clip"); + unif_color_ = prg_.uniformLocation("color"); + + //default param + bind(); + set_explode_volume(0.8f); + set_color(QColor(255,255,255)); + set_plane_clip(QVector4D(0,0,0,0)); + release(); +} + +void ShaderExplodeVolumesLine::set_color(const QColor& rgb) +{ + if (unif_color_>=0) + prg_.setUniformValue(unif_color_,rgb); +} + + +void ShaderExplodeVolumesLine::set_explode_volume(float x) +{ + prg_.setUniformValue(unif_expl_v_, x); +} + +void ShaderExplodeVolumesLine::set_plane_clip(const QVector4D& plane) +{ + + prg_.setUniformValue(unif_plane_clip_, plane); +} + +bool ShaderExplodeVolumesLine::set_vao(unsigned int i, VBO* vbo_pos) +{ + if (i >= vaos_.size()) + { + std::cerr << "VAO number " << i << " does not exist" << std::endl; + return false; + } + + QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); + + prg_.bind(); + vaos_[i]->bind(); + + // position vbo + vbo_pos->bind(); + ogl->glEnableVertexAttribArray(ATTRIB_POS); + ogl->glVertexAttribPointer(ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, 0, 0); + vbo_pos->release(); + + vaos_[i]->release(); + prg_.release(); + + return true; +} + +} // namespace rendering + +} // namespace cgogn diff --git a/cgogn/rendering/shaders/shader_explode_volumes_line.h b/cgogn/rendering/shaders/shader_explode_volumes_line.h new file mode 100644 index 00000000..d13a2dcc --- /dev/null +++ b/cgogn/rendering/shaders/shader_explode_volumes_line.h @@ -0,0 +1,79 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef RENDERING_SHADERS_EXPLODE_VOLUMES_LINE_H_ +#define RENDERING_SHADERS_EXPLODE_VOLUMES_LINE_H_ + +#include +#include +#include +#include +#include + +namespace cgogn +{ + +namespace rendering +{ + +class CGOGN_RENDERING_API ShaderExplodeVolumesLine : public ShaderProgram +{ + static const char* vertex_shader_source_; + static const char* geometry_shader_source_; + static const char* fragment_shader_source_; + + enum + { + ATTRIB_POS = 0, + }; + + // uniform ids + int unif_expl_v_; + int unif_plane_clip_; + int unif_color_; + + +public: + + ShaderExplodeVolumesLine(); + + void set_explode_volume(float x); + + void set_plane_clip(const QVector4D& plane); + + void set_color(const QColor& rgb); + + /** + * @brief set a vao configuration + * @param i vao id (0,1,...) + * @param vbo_pos pointer on position vbo (XYZ) + * @return true if ok + */ + bool set_vao(unsigned int i, VBO* vbo_pos); +}; + +} // namespace rendering + +} // namespace cgogn + +#endif // RENDERING_SHADERS_EXPLODE_VOLUMES_LINE_H_ diff --git a/cgogn/rendering/topo_render.cpp b/cgogn/rendering/topo_render.cpp index a70de2f8..c71f0154 100644 --- a/cgogn/rendering/topo_render.cpp +++ b/cgogn/rendering/topo_render.cpp @@ -48,7 +48,7 @@ TopoRender::TopoRender(QOpenGLFunctions_3_3_Core* ogl33): phi3_color_(255,255,0), shrink_v_(0.6f), shrink_f_(0.85f), - shrink_e_(0.9f) + shrink_e_(0.95f) { nb_instances_++; diff --git a/cgogn/rendering/topo_render.h b/cgogn/rendering/topo_render.h index 5d9ba4c0..9a37775b 100644 --- a/cgogn/rendering/topo_render.h +++ b/cgogn/rendering/topo_render.h @@ -83,6 +83,10 @@ class CGOGN_RENDERING_API TopoRender */ ~TopoRender(); + inline void set_explode_volume(float x) { shrink_v_ = x; } + inline void set_explode_face(float x) { shrink_f_ = x; } + inline void set_explode_edge(float x) { shrink_e_ = x; } + template void update_map2(MAP& m, const typename MAP::template VertexAttributeHandler& position); diff --git a/cgogn/rendering/volume_render.cpp b/cgogn/rendering/volume_render.cpp new file mode 100644 index 00000000..005fe56e --- /dev/null +++ b/cgogn/rendering/volume_render.cpp @@ -0,0 +1,128 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#define CGOGN_RENDERING_DLL_EXPORT + +#include + +#include +#include +#include + +namespace cgogn +{ + +namespace rendering +{ + + + +VolumeRender::VolumeRender(QOpenGLFunctions_3_3_Core* ogl33): + shader_expl_vol_(nullptr), + shader_expl_vol_line_(nullptr), + vbo_col_(nullptr), + ogl33_(ogl33), + face_color_(0,150,0), + edge_color_(0,0,0), + shrink_v_(0.6f), + shrink_f_(0.85f) +{ + vbo_pos_ = new cgogn::rendering::VBO(3); +} + +void VolumeRender::init_with_color() +{ + if ((vbo_col_!= nullptr) && (shader_expl_vol_!= nullptr)) + return; + + vbo_col_ = new cgogn::rendering::VBO(3); + + delete shader_expl_vol_; + shader_expl_vol_ = new ShaderExplodeVolumes(true); + vao1_ = shader_expl_vol_->add_vao(); + shader_expl_vol_->set_vao(vao1_,vbo_pos_,vbo_col_); +} + +void VolumeRender::init_without_color() +{ + if ((vbo_col_== nullptr) && (shader_expl_vol_!= nullptr)) + return; + + delete vbo_col_; + vbo_col_ = nullptr; + + delete shader_expl_vol_; + shader_expl_vol_ = new ShaderExplodeVolumes(false); + vao1_ = shader_expl_vol_->add_vao(); + shader_expl_vol_->set_vao(vao1_,vbo_pos_,vbo_col_); +} + +void VolumeRender::init_edge() +{ + if (shader_expl_vol_line_!= nullptr) + return; + + vbo_pos2_ = new cgogn::rendering::VBO(3); + + shader_expl_vol_line_ = new ShaderExplodeVolumesLine(); + vao2_ = shader_expl_vol_line_->add_vao(); + shader_expl_vol_line_->set_vao(vao2_,vbo_pos2_); +} + + +VolumeRender::~VolumeRender() +{ + delete vbo_pos_; + delete vbo_col_; + delete shader_expl_vol_; +} + +void VolumeRender::draw_faces(const QMatrix4x4& projection, const QMatrix4x4& modelview) +{ + shader_expl_vol_->bind(); + shader_expl_vol_->set_matrices(projection,modelview); + shader_expl_vol_->set_explode_volume(shrink_v_); + shader_expl_vol_->set_color(face_color_); + shader_expl_vol_->bind_vao(vao1_); + ogl33_->glDrawArrays(GL_LINES_ADJACENCY,0,vbo_pos_->size()); + shader_expl_vol_->release_vao(vao1_); + shader_expl_vol_->release(); +} + +void VolumeRender::draw_edges(const QMatrix4x4& projection, const QMatrix4x4& modelview) +{ + shader_expl_vol_line_->bind(); + shader_expl_vol_line_->set_matrices(projection,modelview); + shader_expl_vol_line_->set_explode_volume(shrink_v_); + shader_expl_vol_line_->set_color(edge_color_); + shader_expl_vol_line_->bind_vao(vao2_); + ogl33_->glDrawArrays(GL_TRIANGLES,0,vbo_pos2_->size()); + shader_expl_vol_line_->release_vao(vao2_); + shader_expl_vol_line_->release(); +} + + + +} // namespace rendering + +} // namespace cgogn diff --git a/cgogn/rendering/volume_render.h b/cgogn/rendering/volume_render.h new file mode 100644 index 00000000..d9f56b8a --- /dev/null +++ b/cgogn/rendering/volume_render.h @@ -0,0 +1,297 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef RENDERING_VOLUME_RENDER_H_ +#define RENDERING_VOLUME_RENDER_H_ + +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace cgogn +{ + +namespace rendering +{ + + +class CGOGN_RENDERING_API VolumeRender +{ + using Vec3f = std::array; + +protected: + + ShaderExplodeVolumes* shader_expl_vol_; + + ShaderExplodeVolumesLine* shader_expl_vol_line_; + + VBO* vbo_pos_; + VBO* vbo_col_; + unsigned int vao1_; + QColor face_color_; + + + VBO* vbo_pos2_; + unsigned int vao2_; + QColor edge_color_; + + + QOpenGLFunctions_3_3_Core* ogl33_; + + float shrink_v_; + float shrink_f_; + + void init_with_color(); + + void init_without_color(); + + void init_edge(); + +public: + + /** + * constructor, init all buffers (data and OpenGL) and shader + * @Warning need OpenGL context + */ + VolumeRender(QOpenGLFunctions_3_3_Core* ogl33); + + /** + * release buffers and shader + */ + ~VolumeRender(); + + inline void set_explode_face(float x) { shrink_f_ = x; } + + inline void set_explode_volume(float x) { shrink_v_ = x; } + + inline void set_face_color(const QColor& rgb) { face_color_= rgb; } + + inline void set_edge_color(const QColor& rgb) { edge_color_= rgb; } + + template + void update_face(MAP& m, const typename MAP::template VertexAttributeHandler& position); + + template + void update_face(MAP& m, const typename MAP::template VertexAttributeHandler& position, + const typename MAP::template VertexAttributeHandler& color); + + template + void update_edge(MAP& m, const typename MAP::template VertexAttributeHandler& position); + + void draw_faces(const QMatrix4x4& projection, const QMatrix4x4& modelview); + + void draw_edges(const QMatrix4x4& projection, const QMatrix4x4& modelview); +}; + + +template +void VolumeRender::update_face(MAP& m, const typename MAP::template VertexAttributeHandler& position) +{ + init_without_color(); + + using Vertex = typename MAP::Vertex; + using Face = typename MAP::Face; + using Volume = typename MAP::Volume; + using Scalar = typename VEC3::Scalar; + + std::vector> out_pos; + out_pos.reserve(1024*1024); + + std::vector ear_indices; + ear_indices.reserve(256); + + m.foreach_cell([&] (Volume v) + { + VEC3 CV = geometry::centroid(m,v,position); + m.foreach_incident_face(v, [&] (Face f) + { + if (m.has_degree(f,3)) + { + const VEC3& P1 = position[Vertex(f.dart)]; + const VEC3& P2 = position[Vertex(m.phi1(f.dart))]; + const VEC3& P3 = position[Vertex(m.phi1(m.phi1(f.dart)))]; + out_pos.push_back({float(CV[0]),float(CV[1]),float(CV[2])}); + out_pos.push_back({float(P1[0]),float(P1[1]),float(P1[2])}); + out_pos.push_back({float(P2[0]),float(P2[1]),float(P2[2])}); + out_pos.push_back({float(P3[0]),float(P3[1]),float(P3[2])}); + } + else + { + ear_indices.clear(); + cgogn::geometry::compute_ear_triangulation(m,f,position,ear_indices); + for(std::size_t i=0; iallocate(nbvec,3); + vbo_pos_->bind(); + vbo_pos_->copy_data(0, nbvec*12, out_pos[0].data()); + vbo_pos_->release(); + +} + +template +void VolumeRender::update_face(MAP& m, const typename MAP::template VertexAttributeHandler& position, + const typename MAP::template VertexAttributeHandler& color) +{ + init_with_color(); + + using Vertex = typename MAP::Vertex; + using Face = typename MAP::Face; + using Volume = typename MAP::Volume; + using Scalar = typename VEC3::Scalar; + + std::vector> out_pos; + out_pos.reserve(1024*1024); + + std::vector> out_color; + out_color.reserve(1024*1024); + + std::vector ear_indices; + ear_indices.reserve(256); + + m.foreach_cell([&] (Volume v) + { + VEC3 CV = geometry::centroid(m,v,position); + m.foreach_incident_face(v, [&] (Face f) + { + if (m.has_degree(f,3)) + { + Dart d = f.dart; + const VEC3& P1 = position[Vertex(d)]; + const VEC3& C1 = color[Vertex(d)]; + d = m.phi1(d); + const VEC3& P2 = position[Vertex(d)]; + const VEC3& C2 = color[Vertex(d)]; + d = m.phi1(d); + const VEC3& P3 = position[Vertex(d)]; + const VEC3& C3 = color[Vertex(d)]; + out_pos.push_back({float(CV[0]),float(CV[1]),float(CV[2])}); + out_pos.push_back({float(P1[0]),float(P1[1]),float(P1[2])}); + out_pos.push_back({float(P2[0]),float(P2[1]),float(P2[2])}); + out_pos.push_back({float(P3[0]),float(P3[1]),float(P3[2])}); + out_color.push_back({float(CV[0]),float(CV[1]),float(CV[2])}); + out_color.push_back({float(C1[0]),float(C1[1]),float(C1[2])}); + out_color.push_back({float(C2[0]),float(C2[1]),float(C2[2])}); + out_color.push_back({float(C3[0]),float(C3[1]),float(C3[2])}); + } + else + { + ear_indices.clear(); + cgogn::geometry::compute_ear_triangulation(m,f,position,ear_indices); + for(std::size_t i=0; iallocate(nbvec,3); + vbo_pos_->bind(); + vbo_pos_->copy_data(0, nbvec*12, out_pos[0].data()); + vbo_pos_->release(); + + vbo_col_->allocate(nbvec,3); + vbo_col_->bind(); + vbo_col_->copy_data(0, nbvec*12, out_color[0].data()); + vbo_col_->release(); + +} + + + +template +void VolumeRender::update_edge(MAP& m, const typename MAP::template VertexAttributeHandler& position) +{ + init_edge(); + + using Vertex = typename MAP::Vertex; + using Edge = typename MAP::Edge; + using Volume = typename MAP::Volume; + using Scalar = typename VEC3::Scalar; + + std::vector> out_pos; + out_pos.reserve(1024*1024); + + std::vector ear_indices; + ear_indices.reserve(256); + + m.foreach_cell([&] (Volume v) + { + VEC3 CV = geometry::centroid(m,v,position); + m.foreach_incident_edge(v, [&] (Edge e) + { + const VEC3& P1 = position[Vertex(e.dart)]; + const VEC3& P2 = position[Vertex(m.phi1(e.dart))]; + out_pos.push_back({float(CV[0]),float(CV[1]),float(CV[2])}); + out_pos.push_back({float(P1[0]),float(P1[1]),float(P1[2])}); + out_pos.push_back({float(P2[0]),float(P2[1]),float(P2[2])}); + }); + }); + + std::size_t nbvec = out_pos.size(); + vbo_pos2_->allocate(nbvec,3); + vbo_pos2_->bind(); + vbo_pos2_->copy_data(0, nbvec*12, out_pos[0].data()); + vbo_pos2_->release(); +} + + +} // namespace rendering + +} // namespace cgogn + +#endif // RENDERING_VOLUME_RENDER_H_ From 1b9fe91a7dba38a9bf17a4b1ce66d68c3d512406 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 16 Mar 2016 12:03:07 +0100 Subject: [PATCH 337/402] added FindCGGAL.cmake MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cmake/Modules/FindCGAL.cmake | 89 ++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 cmake/Modules/FindCGAL.cmake diff --git a/cmake/Modules/FindCGAL.cmake b/cmake/Modules/FindCGAL.cmake new file mode 100644 index 00000000..f09b28c0 --- /dev/null +++ b/cmake/Modules/FindCGAL.cmake @@ -0,0 +1,89 @@ +# +# The following module is based on FindVTK.cmake +# + +# - Find a CGAL installation or binary tree. +# The following variables are set if CGAL is found. If CGAL is not +# found, CGAL_FOUND is set to false. +# +# CGAL_FOUND - Set to true when CGAL is found. +# CGAL_USE_FILE - CMake file to use CGAL. +# + +# Construct consitent error messages for use below. +set(CGAL_DIR_DESCRIPTION "directory containing CGALConfig.cmake. This is either the binary directory where CGAL was configured or PREFIX/lib/CGAL for an installation.") +set(CGAL_DIR_MESSAGE "CGAL not found. Set the CGAL_DIR cmake variable or environment variable to the ${CGAL_DIR_DESCRIPTION}") + +if ( NOT CGAL_DIR ) + + # Get the system search path as a list. + if(UNIX) + string(REGEX MATCHALL "[^:]+" CGAL_DIR_SEARCH1 "$ENV{PATH}") + else() + string(REGEX REPLACE "\\\\" "/" CGAL_DIR_SEARCH1 "$ENV{PATH}") + endif() + + string(REGEX REPLACE "/;" ";" CGAL_DIR_SEARCH2 "${CGAL_DIR_SEARCH1}") + + # Construct a set of paths relative to the system search path. + set(CGAL_DIR_SEARCH "") + + foreach(dir ${CGAL_DIR_SEARCH2}) + + set(CGAL_DIR_SEARCH ${CGAL_DIR_SEARCH} ${dir}/../lib/CGAL ) + + endforeach() + + + # + # Look for an installation or build tree. + # + find_path(CGAL_DIR CGALConfig.cmake + + # Look for an environment variable CGAL_DIR. + $ENV{CGAL_DIR} + + # Look in places relative to the system executable search path. + ${CGAL_DIR_SEARCH} + + # Look in standard UNIX install locations. + /usr/local/lib/CGAL + /usr/lib/CGAL + + # Read from the CMakeSetup registry entries. It is likely that + # CGAL will have been recently built. + [HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild1] + [HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild2] + [HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild3] + [HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild4] + [HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild5] + [HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild6] + [HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild7] + [HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild8] + [HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild9] + [HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild10] + + # Help the user find it if we cannot. + DOC "The ${CGAL_DIR_DESCRIPTION}" + ) + +endif() + +if ( CGAL_DIR ) + + if ( EXISTS "${CGAL_DIR}/CGALConfig.cmake" ) + include( "${CGAL_DIR}/CGALConfig.cmake" ) + set( CGAL_FOUND TRUE ) + endif() + +endif() + +if( NOT CGAL_FOUND) + if(CGAL_FIND_REQUIRED) + MESSAGE(FATAL_ERROR ${CGAL_DIR_MESSAGE}) + else() + if(NOT CGAL_FIND_QUIETLY) + MESSAGE(STATUS ${CGAL_DIR_MESSAGE}) + endif() + endif() +endif() From 4910f615f7b5c2dc5eb82a7440ba17ae9ab9e062 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 16 Mar 2016 19:51:10 +0100 Subject: [PATCH 338/402] plugging to CGAL for mesh generation and importing the result. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/CMakeLists.txt | 1 + cgogn/io/mesh_generation/CMakeLists.txt | 30 ++++ cgogn/io/mesh_generation/c3t3_io.cpp | 38 +++++ cgogn/io/mesh_generation/c3t3_io.h | 125 ++++++++++++++++ .../mesh_generation/examples/CMakeLists.txt | 15 ++ .../examples/map3_from_image.cpp | 119 +++++++++++++++ .../examples/program_options.cpp | 140 ++++++++++++++++++ .../examples/program_options.h | 85 +++++++++++ cgogn/io/mesh_generation/map3_from_image.h | 50 +++++++ cgogn/io/mesh_io_gen.cpp | 1 + .../CGAL_GeneratorSpecificSettings.cmake | 56 +++++++ cmake/Modules/FindGMP.cmake | 63 ++++++++ cmake/Modules/FindMPFR.cmake | 62 ++++++++ data/images/liver.inr.gz | Bin 0 -> 299891 bytes 14 files changed, 785 insertions(+) create mode 100644 cgogn/io/mesh_generation/CMakeLists.txt create mode 100644 cgogn/io/mesh_generation/c3t3_io.cpp create mode 100644 cgogn/io/mesh_generation/c3t3_io.h create mode 100644 cgogn/io/mesh_generation/examples/CMakeLists.txt create mode 100644 cgogn/io/mesh_generation/examples/map3_from_image.cpp create mode 100644 cgogn/io/mesh_generation/examples/program_options.cpp create mode 100644 cgogn/io/mesh_generation/examples/program_options.h create mode 100644 cgogn/io/mesh_generation/map3_from_image.h create mode 100644 cmake/Modules/CGAL_GeneratorSpecificSettings.cmake create mode 100644 cmake/Modules/FindGMP.cmake create mode 100644 cmake/Modules/FindMPFR.cmake create mode 100644 data/images/liver.inr.gz diff --git a/cgogn/io/CMakeLists.txt b/cgogn/io/CMakeLists.txt index 1db1c0c6..45ff8a0a 100644 --- a/cgogn/io/CMakeLists.txt +++ b/cgogn/io/CMakeLists.txt @@ -63,4 +63,5 @@ install(TARGETS ${PROJECT_NAME} ARCHIVE DESTINATION lib ) +add_subdirectory(mesh_generation) add_subdirectory(examples) diff --git a/cgogn/io/mesh_generation/CMakeLists.txt b/cgogn/io/mesh_generation/CMakeLists.txt new file mode 100644 index 00000000..587a7b13 --- /dev/null +++ b/cgogn/io/mesh_generation/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 3.0 FATAL_ERROR) + +find_package(CGAL) +find_package(Boost QUIET COMPONENTS thread) +project(cgogn_io_mesh_generation + LANGUAGES CXX +) + +set(HEADER_FILES + map3_from_image.h + c3t3_io.h +) + +set(SOURCE_FILES + c3t3_io.cpp +) + +if (${CGAL_FOUND} AND ${Boost_FOUND}) + find_package(MPFR REQUIRED) + find_package(GMP REQUIRED) + add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) + + target_include_directories(${PROJECT_NAME} PUBLIC + $ + $ + ) + target_link_libraries(${PROJECT_NAME} cgogn_core cgogn_io CGAL CGAL_ImageIO ${Boost_LIBRARIES} ${GMP_LIBRARIES} ${MPFR_LIBRARIES}) + + add_subdirectory(examples) +endif() diff --git a/cgogn/io/mesh_generation/c3t3_io.cpp b/cgogn/io/mesh_generation/c3t3_io.cpp new file mode 100644 index 00000000..624c1756 --- /dev/null +++ b/cgogn/io/mesh_generation/c3t3_io.cpp @@ -0,0 +1,38 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#define CGOGN_IO_DLL_EXPORT +#define IO_C3T3_IO_CPP_ + +#include + +namespace cgogn +{ + +namespace io +{ + +template class CGOGN_IO_API C3T3VolumeImport; + +} // namespace io +} // namespace cgogn diff --git a/cgogn/io/mesh_generation/c3t3_io.h b/cgogn/io/mesh_generation/c3t3_io.h new file mode 100644 index 00000000..24a96e47 --- /dev/null +++ b/cgogn/io/mesh_generation/c3t3_io.h @@ -0,0 +1,125 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef IO_C3T3_IO_H_ +#define IO_C3T3_IO_H_ + +#include +#include + +#include +#include +#include +#include +#include +#include +namespace cgogn +{ + +namespace io +{ + +struct VolumeMeshFromImageCGALTraits +{ + using Image = CGAL::Image_3; + using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel; + using Domain = CGAL::Labeled_image_mesh_domain_3; + using Triangulation = typename CGAL::Mesh_triangulation_3::type; + using Criteria = CGAL::Mesh_criteria_3; + using C3T3 = typename CGAL::Mesh_complex_3_in_triangulation_3; +}; + + +template +class C3T3VolumeImport : public VolumeImport +{ +public: + using Inherit = VolumeImport; + using Self = C3T3VolumeImport; + + using Scalar = typename geometry::vector_traits::Scalar; + template + using ChunkArray = typename Inherit::template ChunkArray; + + using Triangulation = typename C3T3::Triangulation; + using Vertex_handle = typename Triangulation::Vertex_handle; + + C3T3VolumeImport() = delete; + C3T3VolumeImport(const Self&) = delete; + C3T3VolumeImport(Self&&) = delete; + Self& operator=(const Self&) = delete; + Self& operator=(Self&&) = delete; + + inline C3T3VolumeImport(const C3T3& cpx) : Inherit(), + cpx_(cpx) + {} + +protected: + virtual bool import_file_impl(const std::string& /*filename*/) override + { + const Triangulation& triangulation = cpx_.triangulation(); + std::map vertices_indices; + ChunkArray* position = this->vertex_attributes_.template add_attribute("position"); + + const unsigned int num_vertices = triangulation.number_of_vertices(); + const unsigned int num_cells = cpx_.number_of_cells_in_complex(); + + this->volumes_nb_vertices_.reserve(num_cells); + this->volumes_vertex_indices_.reserve(4u*num_cells); + this->nb_vertices_ = num_vertices; + this->nb_volumes_ = num_cells; + + for (auto vit = triangulation.finite_vertices_begin(), vend = triangulation.finite_vertices_end(); vit != vend; ++vit) + { + const auto& P = vit->point(); + const unsigned id = this->vertex_attributes_.template insert_lines<1>(); + vertices_indices[vit] = id; + position->operator [](id) = VEC3(Scalar(P.x()), Scalar(P.y()), Scalar(P.z())); + } + + for (auto cit = cpx_.cells_in_complex_begin(), cend = cpx_.cells_in_complex_end(); cit != cend; ++cit) + this->add_tetra(*position, vertices_indices[cit->vertex(0)], vertices_indices[cit->vertex(1)], vertices_indices[cit->vertex(2)], vertices_indices[cit->vertex(3)], true); + + ChunkArray* subdomain_indices = this->volume_attributes_.template add_attribute("subdomain index"); + for (auto cit = cpx_.cells_in_complex_begin(), cend = cpx_.cells_in_complex_end(); cit != cend; ++cit) + { + const unsigned id = this->volume_attributes_.template insert_lines<1>(); + subdomain_indices->operator [](id) = cpx_.subdomain_index(cit); + } + + return true; + } +private: + C3T3 cpx_; +}; + +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_C3T3_IO_CPP_)) +extern template class CGOGN_IO_API C3T3VolumeImport; +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_C3T3_IO_CPP_)) + +} // namespace io +} // namespace cgogn + + + +#endif // IO_C3T3_IO_H_ diff --git a/cgogn/io/mesh_generation/examples/CMakeLists.txt b/cgogn/io/mesh_generation/examples/CMakeLists.txt new file mode 100644 index 00000000..057059e7 --- /dev/null +++ b/cgogn/io/mesh_generation/examples/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.0 FATAL_ERROR) + +project(cgogn_io_mesh_gen_examples + LANGUAGES CXX +) + +set(CGOGN_TEST_PREFIX "test_") +set(CGOGN_TEST_IMAGES_PATH "${CMAKE_SOURCE_DIR}/data/images/") +add_definitions("-DCGOGN_TEST_IMAGES_PATH=${CGOGN_TEST_IMAGES_PATH}") + +if(NOT ${CGOGN_USE_GLIBCXX_DEBUG}) + find_package(Boost QUIET REQUIRED COMPONENTS program_options) + add_executable(map3_from_image map3_from_image.cpp program_options.h program_options.cpp) + target_link_libraries(map3_from_image cgogn_core cgogn_io_mesh_generation ${Boost_LIBRARIES} boost_filesystem) +endif() diff --git a/cgogn/io/mesh_generation/examples/map3_from_image.cpp b/cgogn/io/mesh_generation/examples/map3_from_image.cpp new file mode 100644 index 00000000..55bb3a5a --- /dev/null +++ b/cgogn/io/mesh_generation/examples/map3_from_image.cpp @@ -0,0 +1,119 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#include +#include + +#include +#include +#include "program_options.h" + +#define DEFAULT_IMAGE_PATH CGOGN_STR(CGOGN_TEST_IMAGES_PATH) + + +using Map3 = cgogn::CMap3; + +using Vec3 = Eigen::Vector3d; + +template +using VertexAttributeHandler = Map3::VertexAttributeHandler; +template +using FaceAttributeHandler = Map3::FaceAttributeHandler; + +namespace cp = CGAL::parameters; + +int main(int argc, char** argv) +{ + cgogn::io::ProgramOptions po(argc,argv); + std::string image_path; + if (argc < 2) + { + image_path = std::string(DEFAULT_IMAGE_PATH) + std::string("liver.inr"); + std::cout << "Using default image : " << image_path << std::endl; + } + else + image_path = po.input_file_; + + Map3 map; + + cgogn::io::VolumeMeshFromImageCGALTraits::Criteria criteria(cp::facet_angle = po.facet_angle_, + cp::facet_size = po.facet_size_, + cp::facet_distance = po.facet_distance_, + cp::cell_radius_edge_ratio = po.cell_radius_, + cp::cell_size = po.cell_size_ + ); + cgogn::io::create_map3_from_image(map, image_path, criteria); + + std::chrono::time_point start, end; + start = std::chrono::system_clock::now(); + + VertexAttributeHandler vertex_position = map.get_attribute("position"); + + map.enable_topo_cache(); + map.enable_topo_cache(); + map.enable_topo_cache(); + map.enable_topo_cache(); + + unsigned int nbw = 0u; + map.foreach_cell([&nbw] (Map3::Volume) + { + ++nbw; + }); + + unsigned int nbf = 0u; + map.foreach_cell([&] (Map3::Face f) + { + ++nbf; + Vec3 v1 = vertex_position[Map3::Vertex(map.phi1(f.dart))] - vertex_position[Map3::Vertex(f.dart)]; + Vec3 v2 = vertex_position[Map3::Vertex(map.phi_1(f.dart))] - vertex_position[Map3::Vertex(f.dart)]; + }); + + unsigned int nbv = 0; + map.foreach_cell([&] (Map3::Vertex v) + { + ++nbv; + unsigned int nb_incident = 0; + map.foreach_incident_face(v, [&] (Map3::Face /*f*/) + { + ++nb_incident; + }); + }); + + unsigned int nbe = 0; + map.foreach_cell([&nbe] (Map3::Edge) + { + ++nbe; + }); + + std::cout << "nb vertices -> " << nbv << std::endl; + std::cout << "nb edges -> " << nbe << std::endl; + std::cout << "nb faces -> " << nbf << std::endl; + std::cout << "nb volumes -> " << nbw << std::endl; + + end = std::chrono::system_clock::now(); + std::chrono::duration elapsed_seconds = end - start; + std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n"; + + + return 0; +} diff --git a/cgogn/io/mesh_generation/examples/program_options.cpp b/cgogn/io/mesh_generation/examples/program_options.cpp new file mode 100644 index 00000000..f41bd5a5 --- /dev/null +++ b/cgogn/io/mesh_generation/examples/program_options.cpp @@ -0,0 +1,140 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#include "program_options.h" +#include + + +namespace cgogn +{ + +namespace io +{ + +namespace po = boost::program_options; + +ProgramOptions::ProgramOptions(int argc, char **argv) +{ + desc_.add_options() + ("help,h","Produce this help message.") + ("input,i", po::value< std::string >(&input_file_), "The input file : a .vtk StructuredPoints file, or a *.inr.gz file.") + ("fa", po::value(&facet_angle_)->default_value(30.0), "Facet angle, a lower bound for the angles (in degrees) of the surface mesh facets.") + ("fs", po::value(&facet_size_)->default_value(15.0), "Facet size, a scalar field (resp. a constant) describing a space varying (resp. a uniform) upper-bound or for the radii of the surface Delaunay balls.") + ("fd", po::value(&facet_distance_)->default_value(10.0), "Facet distance, scalar field (resp. a constant) describing a space varying (resp. a uniform) upper bound for the same distance.") + ("cr", po::value(&cell_radius_)->default_value(3.0), "Cell radius edge ratio, an upper bound for the radius-edge ratio of the mesh tetrahedra.") + ("cs", po::value(&cell_size_)->default_value(8.0), "Cell size, a scalar field (resp. a constant) describing a space varying (resp. a uniform) upper-bound for the circumradii of the mesh tetrahedra.") + ("lloyd",po::value< bool >(&lloyd_)->default_value(true ),"Optimization parameter : Lloyd smoothing.") + ("lloyd_freeze",po::value< bool >(&lloyd_freeze_)->default_value(true )," Completes the freeze_bound parameter. If it is set to true (default value), frozen vertices will not move anymore in next iterations. Otherwise, at each iteration, any vertex that moves, unfreezes all its incident vertices.") + ("lloyd_freeze_bound",po::value< double >(&lloyd_freeze_bound_)->default_value(0.01 ),"Designed to reduce running time of each optimization iteration. Any vertex that has a displacement less than a given percentage of the length of its shortest incident edge, is frozen (i.e. is not relocated). The parameter freeze_bound gives the threshold ratio. At each iteration, any vertex that moves, unfreezes all its incident vertices.") //Freeze vertices which move less than VALUE*shortest_incident_edge_length + ("lloyd_convergence",po::value< double >(&lloyd_convergence_)->default_value(0.02 ),"Stopping criterion based on convergence: the optimization process is stopped, when at the last iteration, the displacement of any vertex is less than a given percentage of the length of the shortest edge incident to that vertex. The parameter convergence gives the threshold ratio.") + ("lloyd_max_iterations",po::value< std::size_t >(&lloyd_max_iterations_)->default_value(0),"Sets a limit on the number of performed iterations. The default value of 0 means that there is no limit on the number of performed iteration.") + ("odt",po::value< bool >(&odt_)->default_value(true),"Optimization parameter : odt-smoother.") + ("odt_freeze",po::value< bool >(&odt_freeze_)->default_value(true),"Completes the freeze_bound parameter. If it is set to true (default value), frozen vertices will not move anymore in next iterations. Otherwise, at each iteration, any vertex that moves, unfreezes all its incident vertices.") + ("odt_freeze_bound",po::value< double >(&odt_freeze_bound_)->default_value(0.01 ),"Designed to reduce running time of each optimization iteration. Any vertex that has a displacement less than a given percentage of the length of its shortest incident edge, is frozen (i.e. is not relocated). The parameter freeze_bound gives the threshold ratio. At each iteration, any vertex that moves, unfreezes the neighboring vertices.") + ("odt_convergence",po::value< double >(&odt_convergence_)->default_value(0.02 ),"Stopping criterion based on convergence: the optimization process is stopped, when at the last iteration, the displacement of any vertex is less than a given percentage of the length the shortest edge incident to that vertex. The parameter convergence gives the threshold ratio.") + ("odt_max_iterations",po::value< std::size_t >(&odt_max_iterations_)->default_value(0),"Sets a limit on the number of performed iterations. The default value of 0 means that there is no limit on the number of performed iterations.") + ("perturb",po::value< bool >(&perturb_)->default_value(true),"Optimization parameter : perturber.") + ("perturb_sliver_bound",po::value< double >(&perturb_sliver_bound_)->default_value(0 ),"sliver_bound, is designed to give, in degree, a targeted lower bound on dihedral angles of mesh cells. The function perturb_mesh_3 runs as long as steps are successful and step number sliver_bound (after which the worst tetrahedron in the mesh has a smallest angle larger than sliver_bound degrees) has not been reached. The default value is 0 and means that there is no targeted bound: the perturber then runs as long as steps are successful.") + ("exude",po::value< bool >(&exude_)->default_value(true),"Optimization parameter : exuder.") + ("exude_sliver_bound",po::value< double >(&exude_sliver_bound_)->default_value(0 ),"designed to give, in degree, a targeted lower bound on dihedral angles of mesh cells. The exudation process considers in turn all the mesh cells that have a smallest dihedral angle less than sliver_bound and tries to make them disappear by weighting their vertices. The optimization process stops when every cell in the mesh achieves this quality. The default value is 0 and means that there is no targeted bound : the exuder then runs as long as it can improve the smallest dihedral angles of the set of cells incident to some vertices..") + ; + po::store(po::parse_command_line(argc,argv,desc_), variable_map_); + po::notify(variable_map_); + this->optionsHandler(); +} + +ProgramOptions::~ProgramOptions() +{} + + + +bool ProgramOptions::optionsHandler() +{ + + if (variable_map_.count("help")) { + std::cout << desc_ << std::endl; + exit(0); + } + + if (variable_map_.count("fa")) { + std::cout << "Facet angle set to : " + << variable_map_["fa"].as() + << std::endl; + } + if (variable_map_.count("fs")) { + std::cout << "Facet size set to : " + << variable_map_["fs"].as() + << std::endl; + } + + if (variable_map_.count("fd")) { + std::cout << "Facet distance set to : " + << variable_map_["fd"].as() + << std::endl; + } + + if (variable_map_.count("cr")) { + std::cout << "Cell radius edge ratio set to : " + << variable_map_["cr"].as() + << std::endl; + } + + if (variable_map_.count("cs")) { + std::cout << "Cell size set to : " + << variable_map_["cs"].as() + << std::endl; + } + + if (variable_map_.count("lloyd")) { + std::cout << "Lloyed smoother : " + << std::boolalpha + << variable_map_["lloyd"].as() + << std::endl; + } + + if (variable_map_.count("odt")) { + std::cout << "Odt smoother : " + << std::boolalpha + << variable_map_["odt"].as() + << std::endl; + } + + if (variable_map_.count("perturb")) { + std::cout << "Perturber : " + << std::boolalpha + << variable_map_["perturb"].as() + << std::endl; + } + + if (variable_map_.count("exude")) { + std::cout << "Exuder : " + << std::boolalpha + << variable_map_["exude"].as() + << std::endl; + } + + return true; +} + +} // namespace io +} // namespace cgogn diff --git a/cgogn/io/mesh_generation/examples/program_options.h b/cgogn/io/mesh_generation/examples/program_options.h new file mode 100644 index 00000000..1e328e88 --- /dev/null +++ b/cgogn/io/mesh_generation/examples/program_options.h @@ -0,0 +1,85 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef PROGRAM_OPTIONS_H +#define PROGRAM_OPTIONS_H + +#include +#include + +#include + + +namespace cgogn +{ + +namespace io +{ + +class ProgramOptions { +private: + bool optionsHandler(); +public: + explicit ProgramOptions(int argc, char **argv); + ProgramOptions() = delete; + ProgramOptions(const ProgramOptions & ) = delete; + ProgramOptions(ProgramOptions && ) = delete; + ProgramOptions& operator=(const ProgramOptions & ) = delete; + ProgramOptions& operator=(ProgramOptions && ) = delete; + ~ProgramOptions(); + + std::string input_file_; + + double facet_angle_; + double facet_size_; + double facet_distance_; + double cell_radius_; + double cell_size_; + + bool lloyd_; + double lloyd_freeze_bound_; + double lloyd_convergence_; + std::size_t lloyd_max_iterations_; + bool lloyd_freeze_; + + bool odt_; + double odt_freeze_bound_ ; + double odt_convergence_; + std::size_t odt_max_iterations_; + bool odt_freeze_; + + bool perturb_; + double perturb_sliver_bound_; + + bool exude_; + double exude_sliver_bound_; + +private: + boost::program_options::options_description desc_; + boost::program_options::variables_map variable_map_; +}; + +} // namespace io +} // namespace cgogn + +#endif // PROGRAM_OPTIONS_H diff --git a/cgogn/io/mesh_generation/map3_from_image.h b/cgogn/io/mesh_generation/map3_from_image.h new file mode 100644 index 00000000..93f82c7f --- /dev/null +++ b/cgogn/io/mesh_generation/map3_from_image.h @@ -0,0 +1,50 @@ +#ifndef MAP3_GEN_H +#define MAP3_GEN_H + +#include +#include + +#include +#include + +#include + +namespace cgogn +{ + +namespace io +{ + +template +inline void create_map3_from_image(CMap3& map3, const std::string& image_path, const VolumeMeshFromImageCGALTraits::Criteria& criteria = VolumeMeshFromImageCGALTraits::Criteria()) +{ + + using Image = VolumeMeshFromImageCGALTraits::Image; + using Kernel = VolumeMeshFromImageCGALTraits::Kernel; + using Domain = VolumeMeshFromImageCGALTraits::Domain; + using Triangulation = VolumeMeshFromImageCGALTraits::Triangulation; + using Criteria = VolumeMeshFromImageCGALTraits::Criteria; + using C3T3 = VolumeMeshFromImageCGALTraits::C3T3; + + cgogn_assert(get_extension(image_path) == "inr"); + Image inrimage; + inrimage.read(image_path.c_str()); + + Domain domain(inrimage); + + C3T3 complex = CGAL::make_mesh_3(domain, + criteria, + CGAL::parameters::no_features(), + CGAL::parameters::no_odt(), + CGAL::parameters::no_lloyd(), + CGAL::parameters::no_perturb(), + CGAL::parameters::no_exude() + ); + C3T3VolumeImport volume_import(complex); + volume_import.import_file(""); + volume_import.create_map(map3); +} + +} // namespace io +} // namespace cgogn +#endif // MAP3_GEN_H diff --git a/cgogn/io/mesh_io_gen.cpp b/cgogn/io/mesh_io_gen.cpp index 42301d8b..4ea1e712 100644 --- a/cgogn/io/mesh_io_gen.cpp +++ b/cgogn/io/mesh_io_gen.cpp @@ -41,6 +41,7 @@ bool MeshImportGen::import_file(const std::string& filename) this->clear(); Scoped_C_Locale loc; + if (!filename.empty()) { // test if file exist std::ifstream fp(filename.c_str(), std::ios::in); diff --git a/cmake/Modules/CGAL_GeneratorSpecificSettings.cmake b/cmake/Modules/CGAL_GeneratorSpecificSettings.cmake new file mode 100644 index 00000000..9aaed8dd --- /dev/null +++ b/cmake/Modules/CGAL_GeneratorSpecificSettings.cmake @@ -0,0 +1,56 @@ +if ( NOT CGAL_GENERATOR_SPECIFIC_SETTINGS_FILE_INCLUDED ) + set( CGAL_GENERATOR_SPECIFIC_SETTINGS_FILE_INCLUDED 1 ) + + message( STATUS "Targetting ${CMAKE_GENERATOR}") + + if ( MSVC ) + message( STATUS "Target build enviroment supports auto-linking" ) + set(CGAL_AUTO_LINK_ENABLED TRUE) + endif() + + if ( MSVC15 ) + set(CGAL_TOOLSET "vc150") + message( STATUS "Using VC15 compiler." ) + elseif ( MSVC14 ) + set(CGAL_TOOLSET "vc140") + message( STATUS "Using VC14 compiler." ) + elseif ( MSVC12 ) + set(CGAL_TOOLSET "vc120") + message( STATUS "Using VC12 compiler." ) + elseif ( MSVC11 ) + set(CGAL_TOOLSET "vc110") + message( STATUS "Using VC11 compiler." ) + elseif ( MSVC10 ) + set(CGAL_TOOLSET "vc100") + message( STATUS "Using VC10 compiler." ) + elseif ( MSVC90 ) + set(CGAL_TOOLSET "vc90") + message( STATUS "Using VC90 compiler." ) + elseif ( MSVC80 ) + set(CGAL_TOOLSET "vc80") + message( STATUS "Using VC80 compiler." ) + elseif ( MSVC71 ) + set(CGAL_TOOLSET "vc71") + message( STATUS "Using VC71 compiler." ) + else() + message( STATUS "Using ${CMAKE_CXX_COMPILER} compiler." ) + endif() + + + # From james Bigler, in the cmake users list. + IF (APPLE) + exec_program(uname ARGS -v OUTPUT_VARIABLE DARWIN_VERSION) + string(REGEX MATCH "[0-9]+" DARWIN_VERSION ${DARWIN_VERSION}) + message(STATUS "DARWIN_VERSION=${DARWIN_VERSION}") + if (DARWIN_VERSION GREATER 8) + message(STATUS "Mac Leopard detected") + set(CGAL_APPLE_LEOPARD 1) + endif() + endif() + + if ( NOT "${CMAKE_CFG_INTDIR}" STREQUAL "." ) + set(HAS_CFG_INTDIR TRUE CACHE INTERNAL "Generator uses intermediate configuration directory" ) + message( STATUS "Generator uses intermediate configuration directory: ${CMAKE_CFG_INTDIR}" ) + endif() + +endif() diff --git a/cmake/Modules/FindGMP.cmake b/cmake/Modules/FindGMP.cmake new file mode 100644 index 00000000..74f5bcdd --- /dev/null +++ b/cmake/Modules/FindGMP.cmake @@ -0,0 +1,63 @@ +# - Try to find the GMP libraries +# This module defines: +# GMP_FOUND - system has GMP lib +# GMP_INCLUDE_DIR - the GMP include directory +# GMP_LIBRARIES_DIR - directory where the GMP libraries are located +# GMP_LIBRARIES - Link these to use GMP +# GMP_IN_CGAL_AUXILIARY - TRUE if the GMP found is the one distributed with CGAL in the auxiliary folder + +# TODO: support MacOSX + +include(FindPackageHandleStandardArgs) +include(CGAL_GeneratorSpecificSettings) + + +if(GMP_INCLUDE_DIR) + set(GMP_in_cache TRUE) +else() + set(GMP_in_cache FALSE) +endif() +if(NOT GMP_LIBRARIES) + set(GMP_in_cache FALSE) +endif() + +# Is it already configured? +if (GMP_in_cache) + + set(GMP_FOUND TRUE) + +else() + + find_path(GMP_INCLUDE_DIR + NAMES gmp.h + HINTS ENV GMP_INC_DIR + ENV GMP_DIR + ${CGAL_INSTALLATION_PACKAGE_DIR}/auxiliary/gmp/include + PATH_SUFFIXES include + DOC "The directory containing the GMP header files" + ) + + if ( GMP_INCLUDE_DIR STREQUAL "${CGAL_INSTALLATION_PACKAGE_DIR}/auxiliary/gmp/include" ) + cache_set( GMP_IN_CGAL_AUXILIARY TRUE ) + endif() + + find_library(GMP_LIBRARIES NAMES gmp libgmp-10 + HINTS ENV GMP_LIB_DIR + ENV GMP_DIR + ${CGAL_INSTALLATION_PACKAGE_DIR}/auxiliary/gmp/lib + PATH_SUFFIXES lib + DOC "Path to the GMP library" + ) + + if ( GMP_LIBRARIES ) + get_filename_component(GMP_LIBRARIES_DIR ${GMP_LIBRARIES} PATH CACHE ) + endif() + + # Attempt to load a user-defined configuration for GMP if couldn't be found + if ( NOT GMP_INCLUDE_DIR OR NOT GMP_LIBRARIES_DIR ) + include( GMPConfig OPTIONAL ) + endif() + + find_package_handle_standard_args(GMP "DEFAULT_MSG" GMP_LIBRARIES GMP_INCLUDE_DIR) + +endif() diff --git a/cmake/Modules/FindMPFR.cmake b/cmake/Modules/FindMPFR.cmake new file mode 100644 index 00000000..7ae23a4b --- /dev/null +++ b/cmake/Modules/FindMPFR.cmake @@ -0,0 +1,62 @@ +# Try to find the MPFR libraries +# MPFR_FOUND - system has MPFR lib +# MPFR_INCLUDE_DIR - the MPFR include directory +# MPFR_LIBRARIES_DIR - Directory where the MPFR libraries are located +# MPFR_LIBRARIES - the MPFR libraries +# MPFR_IN_CGAL_AUXILIARY - TRUE if the MPFR found is the one distributed with CGAL in the auxiliary folder + +# TODO: support MacOSX + +include(FindPackageHandleStandardArgs) +include(CGAL_GeneratorSpecificSettings) + +if(MPFR_INCLUDE_DIR) + set(MPFR_in_cache TRUE) +else() + set(MPFR_in_cache FALSE) +endif() +if(NOT MPFR_LIBRARIES) + set(MPFR_in_cache FALSE) +endif() + +# Is it already configured? +if (MPFR_in_cache) + + set(MPFR_FOUND TRUE) + +else() + + find_path(MPFR_INCLUDE_DIR + NAMES mpfr.h + HINTS ENV MPFR_INC_DIR + ENV MPFR_DIR + ${CGAL_INSTALLATION_PACKAGE_DIR}/auxiliary/gmp/include + PATH_SUFFIXES include + DOC "The directory containing the MPFR header files" + ) + + if ( MPFR_INCLUDE_DIR STREQUAL "${CGAL_INSTALLATION_PACKAGE_DIR}/auxiliary/gmp/include" ) + cache_set( MPFR_IN_CGAL_AUXILIARY TRUE ) + endif() + + find_library(MPFR_LIBRARIES NAMES mpfr libmpfr-4 libmpfr-1 + HINTS ENV MPFR_LIB_DIR + ENV MPFR_DIR + ${CGAL_INSTALLATION_PACKAGE_DIR}/auxiliary/gmp/lib + PATH_SUFFIXES lib + DOC "Path to the MPFR library" + ) + + if ( MPFR_LIBRARIES ) + get_filename_component(MPFR_LIBRARIES_DIR ${MPFR_LIBRARIES} PATH CACHE ) + endif() + + # Attempt to load a user-defined configuration for MPFR if couldn't be found + if ( NOT MPFR_INCLUDE_DIR OR NOT MPFR_LIBRARIES_DIR ) + include( MPFRConfig OPTIONAL ) + endif() + + find_package_handle_standard_args(MPFR "DEFAULT_MSG" MPFR_LIBRARIES MPFR_INCLUDE_DIR) + +endif() + diff --git a/data/images/liver.inr.gz b/data/images/liver.inr.gz new file mode 100644 index 0000000000000000000000000000000000000000..2ad18d7faed4559e567a66e1109c718cdfdf2264 GIT binary patch literal 299891 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 UP(%7rhOsa=XBbd_fh=5)6_LD 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�rabKqU22C^hYGbr*vXvQk*blN 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

1ZOXT(D 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 T*WH1>FFt)EF@!hr<#zuE>n>!0 literal 0 HcmV?d00001 From 0deebf198d5910e429cd2ea98367ee7aeb49a206 Mon Sep 17 00:00:00 2001 From: thery Date: Thu, 17 Mar 2016 11:02:55 +0100 Subject: [PATCH 339/402] finish topo & explod_vol render of map3 --- cgogn/rendering/examples/picking_viewer.cpp | 6 + cgogn/rendering/examples/viewer_topo3.cpp | 146 ++++++----- cgogn/rendering/map_render.h | 259 -------------------- cgogn/rendering/topo_render.h | 4 +- cgogn/rendering/volume_render.h | 4 +- 5 files changed, 98 insertions(+), 321 deletions(-) diff --git a/cgogn/rendering/examples/picking_viewer.cpp b/cgogn/rendering/examples/picking_viewer.cpp index f502674a..68587936 100644 --- a/cgogn/rendering/examples/picking_viewer.cpp +++ b/cgogn/rendering/examples/picking_viewer.cpp @@ -300,6 +300,12 @@ void Viewer::mousePressEvent(QMouseEvent* event) } break; } + drawer_->line_width(4.0); + drawer_->begin(GL_LINES); + drawer_->color3f(1.0, 0.0, 1.0); + drawer_->vertex3fv(A); + drawer_->vertex3fv(B); + drawer_->end(); drawer_->end_list(); } diff --git a/cgogn/rendering/examples/viewer_topo3.cpp b/cgogn/rendering/examples/viewer_topo3.cpp index 18fef136..a061410c 100644 --- a/cgogn/rendering/examples/viewer_topo3.cpp +++ b/cgogn/rendering/examples/viewer_topo3.cpp @@ -28,19 +28,16 @@ #include #include - #include #include - -#include #include -#include -//#include -//#include - +#include +#include #include - #include +#include + + #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) @@ -61,24 +58,27 @@ class Viewer : public QOGLViewer virtual void draw(); virtual void init(); + virtual void keyPressEvent(QKeyEvent*); + virtual void mousePressEvent(QMouseEvent*); - virtual void keyPressEvent(QKeyEvent *); void import(const std::string& volumeMesh); virtual ~Viewer(); virtual void closeEvent(QCloseEvent *e); private: + void rayClick(QMouseEvent* event, qoglviewer::Vec& P, qoglviewer::Vec& Q); + Map3 map_; VertexAttributeHandler vertex_position_; cgogn::geometry::BoundingBox bb_; - cgogn::rendering::MapRender* render_; cgogn::rendering::VBO* vbo_pos_; - cgogn::rendering::ShaderFlat* shader_flat_; - cgogn::rendering::TopoRender* topo_render; - cgogn::rendering::VolumeRender* volume_render; + cgogn::rendering::TopoRender* topo_render_; + cgogn::rendering::VolumeRender* volume_render_; + + cgogn::rendering::Drawer* drawer_; bool vol_rendering_; bool edge_rendering_; @@ -92,6 +92,11 @@ class Viewer : public QOGLViewer // // IMPLEMENTATION // +void Viewer::rayClick(QMouseEvent* event, qoglviewer::Vec& P, qoglviewer::Vec& Q) +{ + P = camera()->unprojectedCoordinatesOf(qoglviewer::Vec(event->x(), event->y(), 0.0)); + Q = camera()->unprojectedCoordinatesOf(qoglviewer::Vec(event->x(), event->y(), 1.0)); +} void Viewer::import(const std::string& volumeMesh) @@ -113,24 +118,24 @@ Viewer::~Viewer() void Viewer::closeEvent(QCloseEvent*) { - delete render_; delete vbo_pos_; - delete shader_flat_; - delete topo_render; + delete topo_render_; + delete volume_render_; + delete drawer_; } Viewer::Viewer() : map_(), vertex_position_(), bb_(), - render_(nullptr), vbo_pos_(nullptr), - shader_flat_(nullptr), - topo_render(nullptr), + topo_render_(nullptr), + volume_render_(nullptr), + drawer_(nullptr), vol_rendering_(true), edge_rendering_(true), topo_rendering_(true), - expl_(0.7) + expl_(0.7f) {} void Viewer::keyPressEvent(QKeyEvent *ev) @@ -147,16 +152,16 @@ void Viewer::keyPressEvent(QKeyEvent *ev) topo_rendering_ = !topo_rendering_; break; case Qt::Key_Plus: - expl_ += 0.05; - volume_render->set_explode_volume(expl_); - topo_render->set_explode_volume(expl_); - topo_render->update_map3(map_,vertex_position_); + expl_ += 0.05f; + volume_render_->set_explode_volume(expl_); + topo_render_->set_explode_volume(expl_); + topo_render_->update_map3(map_,vertex_position_); break; case Qt::Key_Minus: - expl_ -= 0.05; - volume_render->set_explode_volume(expl_); - topo_render->set_explode_volume(expl_); - topo_render->update_map3(map_,vertex_position_); + expl_ -= 0.05f; + volume_render_->set_explode_volume(expl_); + topo_render_->set_explode_volume(expl_); + topo_render_->update_map3(map_,vertex_position_); break; default: break; @@ -167,6 +172,50 @@ void Viewer::keyPressEvent(QKeyEvent *ev) update(); } +void Viewer::mousePressEvent(QMouseEvent* event) +{ + if (event->modifiers() & Qt::ShiftModifier) + { + qoglviewer::Vec P; + qoglviewer::Vec Q; + rayClick(event, P, Q); + + Vec3 A(P[0], P[1], P[2]); + Vec3 B(Q[0], Q[1], Q[2]); + + drawer_->new_list(); + + std::vector selected; + cgogn::geometry::picking_volume(map_, vertex_position_, A, B, selected); + std::cout << "Selected volumes: " << selected.size() << std::endl; + if (!selected.empty()) + { + drawer_->line_width(2.0); + drawer_->begin(GL_LINES); + // closest vol in red + drawer_->color3f(1.0, 0.0, 0.0); + cgogn::rendering::add_volume_to_drawer(map_, selected[0], vertex_position_, drawer_); + // others in yellow + drawer_->color3f(1.0, 1.0, 0.0); + for (unsigned int i = 1u; i(map_, selected[i], vertex_position_, drawer_); + drawer_->end(); + } + drawer_->line_width(4.0); + drawer_->begin(GL_LINES); + drawer_->color3f(1.0, 0.0, 1.0); + drawer_->vertex3fv(A); + drawer_->vertex3fv(B); + drawer_->end(); + + drawer_->end_list(); + } + + + QOGLViewer::mousePressEvent(event); +} + + void Viewer::draw() { QMatrix4x4 proj; @@ -179,26 +228,19 @@ void Viewer::draw() glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(1.0f, 1.0f); -// shader_flat_->bind(); -// shader_flat_->set_matrices(proj,view); -// shader_flat_->bind_vao(0); -// render_->draw(cgogn::rendering::TRIANGLES); -// shader_flat_->release_vao(0); -// shader_flat_->release(); - - volume_render->draw_faces(proj,view); + volume_render_->draw_faces(proj,view); glDisable(GL_POLYGON_OFFSET_FILL); } if (edge_rendering_) - volume_render->draw_edges(proj,view); + volume_render_->draw_edges(proj,view); if (topo_rendering_) - { - topo_render->draw(proj,view); - } + topo_render_->draw(proj,view); + + drawer_->call_list(proj, view); } @@ -209,26 +251,14 @@ void Viewer::init() vbo_pos_ = new cgogn::rendering::VBO(3); cgogn::rendering::update_vbo(vertex_position_, *vbo_pos_); + topo_render_ = new cgogn::rendering::TopoRender(this); + topo_render_->update_map3(map_,vertex_position_); + volume_render_ = new cgogn::rendering::VolumeRender(this); + volume_render_->update_face(map_,vertex_position_); + volume_render_->update_edge(map_,vertex_position_); - render_ = new cgogn::rendering::MapRender(); - render_->init_primitives(map_, cgogn::rendering::TRIANGLES, vertex_position_); - - shader_flat_ = new cgogn::rendering::ShaderFlat; - shader_flat_->add_vao(); - shader_flat_->set_vao(0, vbo_pos_); - shader_flat_->bind(); - shader_flat_->set_front_color(QColor(0,150,0)); - shader_flat_->set_back_color(QColor(0,150,0)); - shader_flat_->set_ambiant_color(QColor(5,5,5)); - shader_flat_->release(); - - topo_render = new cgogn::rendering::TopoRender(this); - topo_render->update_map3(map_,vertex_position_); - - volume_render = new cgogn::rendering::VolumeRender(this); - volume_render->update_face(map_,vertex_position_); - volume_render->update_edge(map_,vertex_position_); + drawer_ = new cgogn::rendering::Drawer(this); } int main(int argc, char** argv) diff --git a/cgogn/rendering/map_render.h b/cgogn/rendering/map_render.h index 0757cfa9..06f5069a 100644 --- a/cgogn/rendering/map_render.h +++ b/cgogn/rendering/map_render.h @@ -223,86 +223,6 @@ void create_indices_vertices_faces(MAP& m, const typename MAP::template VertexAt }); } -/** - * @brief create topologie rendering in a Drawer - * @param m the map - * @param position vertices positions - * @param dr output drawer - */ -template -void create_drawer_topo2(MAP& m, const typename MAP::template VertexAttributeHandler& position, - Drawer& dr) -{ - using Vertex = typename MAP::Vertex; - using Face = typename MAP::Face; - using Scalar = typename VEC3::Scalar; - - const Scalar expl1 = 0.95; - const Scalar expl2 = 0.85; - - const Scalar opp_expl1 = 1.0 -expl1; - const Scalar opp_expl2 = 1.0 - expl2; - - - std::vector local_vertices; - local_vertices.reserve(256); - - dr.new_list(); - - m.foreach_cell([&] (Face f) - { - local_vertices.clear(); - VEC3 center; - center.setZero(); - unsigned int count = 0u; - m.foreach_incident_vertex(f, [&] (Vertex v) - { - local_vertices.push_back(position[v]); - center += position[v]; - count++; - }); - center /= Scalar(count); - - // phi2 mid-edge: N -> 2N-1 - for (unsigned int i=0; i N-1 - for (unsigned int i=0; i 3N-1 - for (unsigned int i=0; i 4N-1 - for (unsigned int i=0; i void add_edge_to_drawer(MAP& m, typename MAP::Edge e, const typename MAP::template VertexAttributeHandler& position, Drawer* dr) @@ -338,185 +258,6 @@ void add_volume_to_drawer(MAP& m, typename MAP::Volume vo, const typename MAP::t } -template -class Topo2Render -{ - VBO& vbo_topo_; - -}; - -template -void create_topo2(MAP& m, const typename MAP::template VertexAttributeHandler& position, VBO& vbo_topo) -{ - using Vertex = typename MAP::Vertex; - using Face = typename MAP::Face; - using Scalar = typename VEC3::Scalar; - - const Scalar expl1 = 0.95; - const Scalar expl2 = 0.85; - - const Scalar opp_expl1 = 1.0 -expl1; - const Scalar opp_expl2 = 1.0 - expl2; - - std::vector> out_pos; - out_pos.reserve(1024*1024); - - std::vector> out_pos2; - out_pos2.reserve(1024*1024); - - - std::vector local_vertices; - local_vertices.reserve(256); - - m.foreach_cell([&] (Face f) - { - local_vertices.clear(); - VEC3 center; - center.setZero(); - unsigned int count = 0u; - m.foreach_incident_vertex(f, [&] (Vertex v) - { - local_vertices.push_back(position[v]); - center += position[v]; - count++; - }); - center /= Scalar(count); - - // phi2 mid-edge: N -> 2N-1 - for (unsigned int i=0; i N-1 - for (unsigned int i=0; i 3N-1 - for (unsigned int i=0; i 4N-1 - for (unsigned int i=0; i -//void create_topo2(MAP& m, const typename MAP::template VertexAttributeHandler& position, VBO& vbo_topo) -//{ -// using Vertex = typename MAP::Vertex; -// using Face = typename MAP::Face; -// using Scalar = typename VEC3::Scalar; - -// const Scalar expl1 = 0.95; -// const Scalar expl2 = 0.85; - -// const Scalar opp_expl1 = 1.0 -expl1; -// const Scalar opp_expl2 = 1.0 - expl2; - -// using BufferVBO = std::vector>; - -// std::vector out_pos; -// out_pos.resize(cgogn::get_nb_threads()-1); -// for(auto& b: out_pos) -// b.reserve(1024*1024); - -// std::vector out_pos2; -// out_pos2.resize(cgogn::get_nb_threads()-1); -// for(auto& b: out_pos2) -// b.reserve(1024*1024); - - -// std::vector> thr_local_vertices; -// thr_local_vertices.resize(cgogn::get_nb_threads()-1); -// for(auto& b: thr_local_vertices) -// b.reserve(256); - -// m.parallel_foreach_cell([&] (Face f, unsigned int thr) -// { -// std::vector& local_vertices = thr_local_vertices[thr]; -// local_vertices.clear(); -// VEC3 center; -// center.setZero(); -// unsigned int count = 0u; -// m.foreach_incident_vertex(f, [&] (Vertex v) -// { -// local_vertices.push_back(position[v]); -// center += position[v]; -// count++; -// }); -// center /= Scalar(count); - -// // phi2 mid-edge: N -> 2N-1 -// for (unsigned int i=0; i N-1 -// for (unsigned int i=0; i 3N-1 -// for (unsigned int i=0; i 4N-1 -// for (unsigned int i=0; iallocate(nbvec,3); vbo_darts_->bind(); vbo_darts_->copy_data(0, nbvec*12, out_pos[0].data()); @@ -258,7 +258,7 @@ void TopoRender::update_map3(MAP& m, const typename MAP::template VertexAttribut }); - std::size_t nbvec = out_pos.size(); + unsigned int nbvec = std::uint32_t(out_pos.size()); vbo_darts_->allocate(nbvec,3); vbo_darts_->bind(); vbo_darts_->copy_data(0, nbvec*12, out_pos[0].data()); diff --git a/cgogn/rendering/volume_render.h b/cgogn/rendering/volume_render.h index d9f56b8a..9579064b 100644 --- a/cgogn/rendering/volume_render.h +++ b/cgogn/rendering/volume_render.h @@ -159,7 +159,7 @@ void VolumeRender::update_face(MAP& m, const typename MAP::template VertexAttrib }); }); - std::size_t nbvec = out_pos.size(); + unsigned int nbvec = std::uint32_t(out_pos.size()); vbo_pos_->allocate(nbvec,3); vbo_pos_->bind(); vbo_pos_->copy_data(0, nbvec*12, out_pos[0].data()); @@ -282,7 +282,7 @@ void VolumeRender::update_edge(MAP& m, const typename MAP::template VertexAttrib }); }); - std::size_t nbvec = out_pos.size(); + unsigned int nbvec = std::uint32_t(out_pos.size()); vbo_pos2_->allocate(nbvec,3); vbo_pos2_->bind(); vbo_pos2_->copy_data(0, nbvec*12, out_pos[0].data()); From ab2f334173089a90a7c96e300dd4d7d7d8521956 Mon Sep 17 00:00:00 2001 From: thery Date: Thu, 17 Mar 2016 11:12:12 +0100 Subject: [PATCH 340/402] VS warnings --- thirdparty/lm6/libmesh6.c | 3 +++ thirdparty/lm6/transmesh.c | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/thirdparty/lm6/libmesh6.c b/thirdparty/lm6/libmesh6.c index 7a21624e..ba2d6ce0 100644 --- a/thirdparty/lm6/libmesh6.c +++ b/thirdparty/lm6/libmesh6.c @@ -17,6 +17,9 @@ /*----------------------------------------------------------*/ /* Includes */ /*----------------------------------------------------------*/ +#ifdef _MSC_VER +#define _CRT_SECURE_NO_WARNINGS +#endif #include #include diff --git a/thirdparty/lm6/transmesh.c b/thirdparty/lm6/transmesh.c index b3e9d6c0..1a621a61 100644 --- a/thirdparty/lm6/transmesh.c +++ b/thirdparty/lm6/transmesh.c @@ -34,8 +34,8 @@ int main(int argc, char **argv) { int i, j, NmbTyp, SolSiz, TypTab[ GmfMaxTyp ], InpIdx, OutIdx, FilVer=0, InpVer, OutVer=1, dim; long NmbLin; - float f; - double d; +// float f; +// double d; char *InpNam, *OutNam, *VerNam; switch(argc) From e9ab430b20feb3f24e1d24298e8f1f9c7e3d2201 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Thu, 17 Mar 2016 13:52:07 +0100 Subject: [PATCH 341/402] aded a CGOGN_WITH_CGAL_EXAMPLES option (OFF by default). Removed the function create_map3_from_image from the io_mesh_generation lib. Signed-off-by: Etienne Schmitt --- CMakeLists.txt | 20 +++++++++++------- cgogn/io/CMakeLists.txt | 2 +- cgogn/io/mesh_generation/CMakeLists.txt | 11 +++++----- cgogn/io/mesh_generation/c3t3_io.h | 2 ++ .../mesh_generation/examples/CMakeLists.txt | 21 ++++++++++++++----- .../examples/map3_from_image.cpp | 4 ++-- .../{ => examples}/map3_from_image.h | 6 +++--- .../examples/program_options.h | 6 +++--- 8 files changed, 44 insertions(+), 28 deletions(-) rename cgogn/io/mesh_generation/{ => examples}/map3_from_image.h (93%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 72fc6457..b38111ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,7 +58,11 @@ if (${CGOGN_USE_PARALLEL_GLIBCXX}) set(CGOGN_USE_OPENMP "ON") endif() option(CGOGN_USE_QT "use Qt (5.4 min) for interface & rendering" ON) - +option(CGOGN_WITH_CGAL_EXAMPLES "Build the examples using cgal for mesh generation." OFF) +if ((NOT MSVC) AND CGOGN_WITH_CGAL_EXAMPLES) + set(CGOGN_USE_GLIBCXX_DEBUG OFF) + set(CGOGN_USE_GLIBCXX_DEBUG_PEDANTIC OFF) +endif() #### Continuous integration options option(CGOGN_WITH_GPROF "Builds the project for performance analysis with gprof" OFF) @@ -136,10 +140,10 @@ endif(${CGOGN_BUILD_BENCHS}) ENABLE_COVERAGE_REPORT(TARGETS ${CGOGN_SOURCE_DIR}) # --- CPPCheck --- -GENERATE_CPPCHECK( SOURCES ${CGOGN_SOURCE_DIR} - ENABLE_IDS all - INCLUDES ${CGOGN_SOURCE_DIR} - PLATFORM_FLAGS "-UNDEBUG -UWIN32 -U__func__ -U__FUNCTION__ -U__GNUG__ -U__clang__ -U_MSC_VER" - SYSTEM_INCLUDE_WARNING_SUPPRESSION - INLINE_SUPPRESSION - HTML_REPORT) +GENERATE_CPPCHECK( SOURCES ${CGOGN_SOURCE_DIR} + ENABLE_IDS all + INCLUDES ${CGOGN_SOURCE_DIR} + PLATFORM_FLAGS "-UNDEBUG -UWIN32 -U__func__ -U__FUNCTION__ -U__GNUG__ -U__clang__ -U_MSC_VER" + SYSTEM_INCLUDE_WARNING_SUPPRESSION + INLINE_SUPPRESSION + HTML_REPORT) diff --git a/cgogn/io/CMakeLists.txt b/cgogn/io/CMakeLists.txt index 45ff8a0a..6cd3d67c 100644 --- a/cgogn/io/CMakeLists.txt +++ b/cgogn/io/CMakeLists.txt @@ -3,7 +3,7 @@ project(cgogn_io ) find_package(ZLIB) -if (${ZLIB_FOUND}) +if (ZLIB_FOUND) add_definitions("-DZLIB_CONST") add_definitions("-DCGOGN_WITH_ZLIB") endif() diff --git a/cgogn/io/mesh_generation/CMakeLists.txt b/cgogn/io/mesh_generation/CMakeLists.txt index 587a7b13..1af9a7e0 100644 --- a/cgogn/io/mesh_generation/CMakeLists.txt +++ b/cgogn/io/mesh_generation/CMakeLists.txt @@ -1,13 +1,12 @@ cmake_minimum_required(VERSION 3.0 FATAL_ERROR) find_package(CGAL) -find_package(Boost QUIET COMPONENTS thread) + project(cgogn_io_mesh_generation LANGUAGES CXX ) set(HEADER_FILES - map3_from_image.h c3t3_io.h ) @@ -15,16 +14,16 @@ set(SOURCE_FILES c3t3_io.cpp ) -if (${CGAL_FOUND} AND ${Boost_FOUND}) - find_package(MPFR REQUIRED) - find_package(GMP REQUIRED) +if (CGAL_FOUND) add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) target_include_directories(${PROJECT_NAME} PUBLIC $ $ ) - target_link_libraries(${PROJECT_NAME} cgogn_core cgogn_io CGAL CGAL_ImageIO ${Boost_LIBRARIES} ${GMP_LIBRARIES} ${MPFR_LIBRARIES}) + target_link_libraries(${PROJECT_NAME} cgogn_core cgogn_io) +endif() +if (CGOGN_WITH_CGAL_EXAMPLES) add_subdirectory(examples) endif() diff --git a/cgogn/io/mesh_generation/c3t3_io.h b/cgogn/io/mesh_generation/c3t3_io.h index 24a96e47..4530ef03 100644 --- a/cgogn/io/mesh_generation/c3t3_io.h +++ b/cgogn/io/mesh_generation/c3t3_io.h @@ -33,6 +33,8 @@ #include #include #include + + namespace cgogn { diff --git a/cgogn/io/mesh_generation/examples/CMakeLists.txt b/cgogn/io/mesh_generation/examples/CMakeLists.txt index 057059e7..a1b4b684 100644 --- a/cgogn/io/mesh_generation/examples/CMakeLists.txt +++ b/cgogn/io/mesh_generation/examples/CMakeLists.txt @@ -4,12 +4,23 @@ project(cgogn_io_mesh_gen_examples LANGUAGES CXX ) +set(HEADER_FILES + program_options.h + map3_from_image.h +) + +set(SOURCE_FILES + map3_from_image.cpp + program_options.cpp +) + +find_package(MPFR REQUIRED) +find_package(GMP REQUIRED) +find_package(Boost QUIET REQUIRED COMPONENTS thread program_options) + set(CGOGN_TEST_PREFIX "test_") set(CGOGN_TEST_IMAGES_PATH "${CMAKE_SOURCE_DIR}/data/images/") add_definitions("-DCGOGN_TEST_IMAGES_PATH=${CGOGN_TEST_IMAGES_PATH}") -if(NOT ${CGOGN_USE_GLIBCXX_DEBUG}) - find_package(Boost QUIET REQUIRED COMPONENTS program_options) - add_executable(map3_from_image map3_from_image.cpp program_options.h program_options.cpp) - target_link_libraries(map3_from_image cgogn_core cgogn_io_mesh_generation ${Boost_LIBRARIES} boost_filesystem) -endif() +add_executable(map3_from_image ${HEADER_FILES} ${SOURCE_FILES}) +target_link_libraries(map3_from_image cgogn_core cgogn_io_mesh_generation ${Boost_LIBRARIES} ${GMP_LIBRARIES} ${MPFR_LIBRARIES} CGAL CGAL_ImageIO) diff --git a/cgogn/io/mesh_generation/examples/map3_from_image.cpp b/cgogn/io/mesh_generation/examples/map3_from_image.cpp index 55bb3a5a..65af9a19 100644 --- a/cgogn/io/mesh_generation/examples/map3_from_image.cpp +++ b/cgogn/io/mesh_generation/examples/map3_from_image.cpp @@ -25,7 +25,7 @@ #include #include -#include +#include "map3_from_image.h" #include "program_options.h" #define DEFAULT_IMAGE_PATH CGOGN_STR(CGOGN_TEST_IMAGES_PATH) @@ -48,7 +48,7 @@ int main(int argc, char** argv) std::string image_path; if (argc < 2) { - image_path = std::string(DEFAULT_IMAGE_PATH) + std::string("liver.inr"); + image_path = std::string(DEFAULT_IMAGE_PATH) + std::string("liver.inr.gz"); std::cout << "Using default image : " << image_path << std::endl; } else diff --git a/cgogn/io/mesh_generation/map3_from_image.h b/cgogn/io/mesh_generation/examples/map3_from_image.h similarity index 93% rename from cgogn/io/mesh_generation/map3_from_image.h rename to cgogn/io/mesh_generation/examples/map3_from_image.h index 93f82c7f..692d23c1 100644 --- a/cgogn/io/mesh_generation/map3_from_image.h +++ b/cgogn/io/mesh_generation/examples/map3_from_image.h @@ -1,5 +1,5 @@ -#ifndef MAP3_GEN_H -#define MAP3_GEN_H +#ifndef IO_MAP3_FROM_IMAGE_H +#define IO_MAP3_FROM_IMAGE_H #include #include @@ -47,4 +47,4 @@ inline void create_map3_from_image(CMap3& map3, const std::string& i } // namespace io } // namespace cgogn -#endif // MAP3_GEN_H +#endif // IO_MAP3_FROM_IMAGE_H diff --git a/cgogn/io/mesh_generation/examples/program_options.h b/cgogn/io/mesh_generation/examples/program_options.h index 1e328e88..95036921 100644 --- a/cgogn/io/mesh_generation/examples/program_options.h +++ b/cgogn/io/mesh_generation/examples/program_options.h @@ -21,8 +21,8 @@ * * *******************************************************************************/ -#ifndef PROGRAM_OPTIONS_H -#define PROGRAM_OPTIONS_H +#ifndef IO_PROGRAM_OPTIONS_H +#define IO_PROGRAM_OPTIONS_H #include #include @@ -82,4 +82,4 @@ class ProgramOptions { } // namespace io } // namespace cgogn -#endif // PROGRAM_OPTIONS_H +#endif // IO_PROGRAM_OPTIONS_H From 0f51db1c43be3568dad04bf6102109b7c2265d00 Mon Sep 17 00:00:00 2001 From: thery Date: Thu, 17 Mar 2016 13:56:57 +0100 Subject: [PATCH 342/402] VS_2015 void* warning + DartMarkerStore in picking --- cgogn/geometry/algos/picking.h | 4 ++-- cgogn/rendering/shaders/shader_program.h | 7 +++++++ cgogn/rendering/shaders/shader_round_point.cpp | 4 ++-- cgogn/rendering/shaders/shader_simple_color.cpp | 5 ++++- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/cgogn/geometry/algos/picking.h b/cgogn/geometry/algos/picking.h index cb956ea6..1597c806 100644 --- a/cgogn/geometry/algos/picking.h +++ b/cgogn/geometry/algos/picking.h @@ -132,7 +132,7 @@ bool picking_vertex(MAP& m, const typename MAP::template VertexAttributeHandler< typename std::vector> sel; picking_internal_face(m,position,A,B,sel); - DartMarker dm(m); + DartMarkerStore dm(m); selected.clear(); for (auto fs: sel) { @@ -174,7 +174,7 @@ bool picking_edge(MAP& m, const typename MAP::template VertexAttributeHandler> sel; picking_internal_face(m,position,A,B,sel); - DartMarker dm(m); + DartMarkerStore dm(m); selected.clear(); for (auto fs: sel) { diff --git a/cgogn/rendering/shaders/shader_program.h b/cgogn/rendering/shaders/shader_program.h index 8e426015..01ff8508 100644 --- a/cgogn/rendering/shaders/shader_program.h +++ b/cgogn/rendering/shaders/shader_program.h @@ -36,6 +36,13 @@ namespace cgogn namespace rendering { +//convenient conversion function +inline void* void_ptr(unsigned int x) +{ + return reinterpret_cast(std::uint64_t(x)); +} + + class CGOGN_RENDERING_API ShaderProgram : protected QOpenGLFunctions_3_3_Core { protected: diff --git a/cgogn/rendering/shaders/shader_round_point.cpp b/cgogn/rendering/shaders/shader_round_point.cpp index b9a18359..4ea0f482 100644 --- a/cgogn/rendering/shaders/shader_round_point.cpp +++ b/cgogn/rendering/shaders/shader_round_point.cpp @@ -200,7 +200,7 @@ bool ShaderRoundPoint::set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color, uns // position vbo vbo_pos->bind(); ogl->glEnableVertexAttribArray(ATTRIB_POS); - ogl->glVertexAttribPointer(ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, stride*vbo_pos->vector_dimension()*4, reinterpret_cast(first*vbo_pos->vector_dimension()*4)); + ogl->glVertexAttribPointer(ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, stride*vbo_pos->vector_dimension()*4, void_ptr(first*vbo_pos->vector_dimension()*4)); vbo_pos->release(); if (vbo_color) @@ -208,7 +208,7 @@ bool ShaderRoundPoint::set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color, uns // color vbo vbo_color->bind(); ogl->glEnableVertexAttribArray(ATTRIB_COLOR); - ogl->glVertexAttribPointer(ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, stride*vbo_pos->vector_dimension()*4, reinterpret_cast(first*vbo_pos->vector_dimension()*4)); + ogl->glVertexAttribPointer(ATTRIB_COLOR, vbo_color->vector_dimension(), GL_FLOAT, GL_FALSE, stride*vbo_pos->vector_dimension()*4, void_ptr(first*vbo_pos->vector_dimension()*4)); vbo_color->release(); } diff --git a/cgogn/rendering/shaders/shader_simple_color.cpp b/cgogn/rendering/shaders/shader_simple_color.cpp index 1d0c06e0..f162e600 100644 --- a/cgogn/rendering/shaders/shader_simple_color.cpp +++ b/cgogn/rendering/shaders/shader_simple_color.cpp @@ -72,6 +72,7 @@ void ShaderSimpleColor::set_color(const QColor& rgb) prg_.setUniformValue(unif_color_, rgb); } + bool ShaderSimpleColor::set_vao(unsigned int i, VBO* vbo_pos, unsigned int stride, unsigned first) { if (i >= vaos_.size()) @@ -88,7 +89,9 @@ bool ShaderSimpleColor::set_vao(unsigned int i, VBO* vbo_pos, unsigned int strid // position vbo vbo_pos->bind(); ogl->glEnableVertexAttribArray(ATTRIB_POS); - ogl->glVertexAttribPointer(ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE,stride*vbo_pos->vector_dimension()*4, reinterpret_cast(first*vbo_pos->vector_dimension()*4)); + + ogl->glVertexAttribPointer(ATTRIB_POS, vbo_pos->vector_dimension(), GL_FLOAT, GL_FALSE, stride*vbo_pos->vector_dimension() * 4, + void_ptr(first*vbo_pos->vector_dimension() * 4)); vbo_pos->release(); vaos_[i]->release(); From c5eaa131caead923bec79769332ab863dc5ce37b Mon Sep 17 00:00:00 2001 From: thery Date: Thu, 17 Mar 2016 14:16:26 +0100 Subject: [PATCH 343/402] schmitt const& optim proposition --- cgogn/geometry/functions/distance.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cgogn/geometry/functions/distance.h b/cgogn/geometry/functions/distance.h index 7981b745..e10b5cc1 100644 --- a/cgogn/geometry/functions/distance.h +++ b/cgogn/geometry/functions/distance.h @@ -43,8 +43,9 @@ namespace geometry template inline typename VEC3_T::Scalar squared_distance_normalized_line_point(const VEC3_T& A, const VEC3_T& AB_norm, const VEC3_T& P) { - VEC3_T V = A - P ; - VEC3_T W = V.cross(AB_norm) ; + // here use const & ? Strange Schmitt optimization proposition ;) + const VEC3_T& V = A - P ; + const VEC3_T& W = V.cross(AB_norm) ; return W.squaredNorm() ; } From 432bfdd6ecc8acb38e8fbda361f557e7500d4f04 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Thu, 17 Mar 2016 14:41:15 +0100 Subject: [PATCH 344/402] Revert "typos" This reverts commit 75d083b6e5e03b045f6040b5135d6b8c025ae4d9. --- cgogn/core/cmap/map_base.h | 1 - 1 file changed, 1 deletion(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 2fe96489..09e039d2 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -631,7 +631,6 @@ class MapBase : public MapBaseData return !this->is_boundary(d); break; default: - cgogn_assert_not_reached("Undefined MASK"); break; } } From b59e7c41868d2a13d34b712a4dec2ba1ae604d18 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Thu, 17 Mar 2016 14:41:34 +0100 Subject: [PATCH 345/402] Revert "Trying another template approach ..." This reverts commit 8da6184a70de727819c84d720a670b4771ba0c22. --- cgogn/core/cmap/cmap2_builder.h | 2 +- cgogn/core/cmap/cmap3_builder.h | 2 +- cgogn/core/cmap/map_base.h | 412 +++++++++++++++++++-------- cgogn/core/tests/cmap/cmap2_test.cpp | 14 +- 4 files changed, 310 insertions(+), 120 deletions(-) diff --git a/cgogn/core/cmap/cmap2_builder.h b/cgogn/core/cmap/cmap2_builder.h index bccad9cd..59c165c9 100644 --- a/cgogn/core/cmap/cmap2_builder.h +++ b/cgogn/core/cmap/cmap2_builder.h @@ -200,7 +200,7 @@ class CMap2Builder_T inline void close_map() { std::vector fix_point_darts; - map_.template foreach_dart( [&] (Dart d) + map_.foreach_dart_nomask( [&] (Dart d) { if (map_.phi2(d) == d) fix_point_darts.push_back(d); diff --git a/cgogn/core/cmap/cmap3_builder.h b/cgogn/core/cmap/cmap3_builder.h index 641ad922..97473843 100644 --- a/cgogn/core/cmap/cmap3_builder.h +++ b/cgogn/core/cmap/cmap3_builder.h @@ -185,7 +185,7 @@ class CMap3Builder_T { // Search the map for topological holes (fix points of phi3) std::vector fix_point_darts; - map_.template foreach_dart( [&] (Dart d) + map_.foreach_dart_nomask( [&] (Dart d) { if (map_.phi3(d) == d) fix_point_darts.push_back(d); diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 09e039d2..551f1f98 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -339,12 +339,16 @@ class MapBase : public MapBaseData this->embeddings_[ORBIT] = ca; // initialize all darts indices to EMBNULL for this ORBIT - foreach_dart( - [this, ca] (Dart d) { (*ca)[d.index] = EMBNULL; }); + foreach_dart( + [this, ca] (Dart d) { (*ca)[d.index] = EMBNULL; }, + [] (Dart) { return true; } + ); // initialize the indices of the existing orbits - foreach_cell( - [this] (Cell c) { new_orbit_embedding(c); }); + foreach_cell( + [this] (Cell c) { new_orbit_embedding(c); }, + [] (Dart) { return true; } + ); cgogn_assert(check_map_integrity()); } @@ -413,7 +417,8 @@ class MapBase : public MapBaseData counter[i] = 0; // Check that the indexation of cells is correct - foreach_cell_until_dart_marking( [&] (CellType c) + foreach_cell_until_dart_marking( + [&] (CellType c) { unsigned int idx = this->get_embedding(c); // check used indices are valid @@ -442,7 +447,9 @@ class MapBase : public MapBaseData }); return result; - }); + }, + [] (Dart) { return true; } + ); // check that all cells present in the attribute handler are used if (result) { @@ -609,32 +616,6 @@ class MapBase : public MapBaseData * Traversals *******************************************************************************/ -public: - - enum Mask: unsigned int - { - NOMASK = 0, - BOUNDARY, - NOBOUNDARY - }; - - template - inline bool is_masked(Dart d) const { - switch (MASK) { - case NOMASK: - return true; - break; - case BOUNDARY: - return this->is_boundary(d); - break; - case NOBOUNDARY: - return !this->is_boundary(d); - break; - default: - break; - } - } - protected: /*! @@ -642,31 +623,26 @@ class MapBase : public MapBaseData * A MASK is an functor that determine if a dart should be traversed or skipped. * It return false when a dart should be skipped, true in other cases. */ - template - inline Dart begin() const + template + inline Dart begin(const MASK& mask) const { Dart d = Dart(this->topology_.begin()); + Dart end = Dart(this->topology_.end()); - if (MASK != NOMASK) { - Dart end = Dart(this->topology_.end()); - - while (d != end && !is_masked(d)) - this->topology_.next(d.index); - } + while (d != end && !mask(d)) + this->topology_.next(d.index); return d; } - template - inline void next(Dart& d) const + template + inline void next(Dart& d, const MASK& mask) const { - this->topology_.next(d.index); + Dart end = Dart(this->topology_.end()); - if (MASK != NOMASK) { - Dart end = Dart(this->topology_.end()); - while (d != end && !is_masked(d)) - this->topology_.next(d.index); - } + do { + this->topology_.next(d.index); + } while (d != end && !mask(d)); } inline Dart end() const @@ -674,6 +650,32 @@ class MapBase : public MapBaseData return Dart(this->topology_.end()); } + /*! + * \Brief Specialized methods to iterate over all darts. + * All darts are traversed without any MASK filtering. + */ + inline Dart begin(const bool&) const + { + Dart d = Dart(this->topology_.begin()); + + return d; + } + + inline void next(Dart& d, const bool&) const + { + this->topology_.next(d.index); + } + +// inline Dart begin() const +// { +// return Dart(this->topology_.begin()); +// } + +// inline void next(Dart& d) const +// { +// this->topology_.next(d.index); +// } + public: /** @@ -681,20 +683,63 @@ class MapBase : public MapBaseData * @tparam FUNC type of the callable * @param f a callable */ - template + template inline void foreach_dart(const FUNC& f) const + { + foreach_dart(f, [this] (Dart d) { return !this->is_boundary(d); }); + } + + template + inline void foreach_boundary_dart(const FUNC& f) const + { + foreach_dart(f, [this] (Dart d) { return this->is_boundary(d); }); + } + + template + inline void foreach_dart_nomask(const FUNC& f) const + { + foreach_dart(f, true); + } + + template + inline void foreach_dart(const FUNC& f, const MASK& mask) const { static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); +// static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); +// static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); - for (Dart it = begin(), last = end(); it != last; next(it)) + for (Dart it = begin(mask), last = end(); it != last; next(it, mask)) f(it); } - template +// template +// inline void foreach_dart_nomask(const FUNC& f) const +// { +// static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); + +// for (Dart it = begin(), last = end(); it != last; next(it)) +// f(it); +// } + + template inline void parallel_foreach_dart(const FUNC& f) const + { + parallel_foreach_dart(f, [this] (Dart d) { return !this->is_boundary(d); }); + } + + template + inline void parallel_foreach_boundary_dart(const FUNC& f) const + { + parallel_foreach_dart(f, [this] (Dart d) { return this->is_boundary(d); }); + } + + template + inline void parallel_foreach_dart(const FUNC& f, const MASK& mask) const { static_assert(check_func_ith_parameter_type(FUNC, 0, Dart), "Wrong function first parameter type"); static_assert(check_func_ith_parameter_type(FUNC, 1, unsigned int), "Wrong function second parameter type"); + static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); + static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); using Future = std::future::type>; using VecDarts = std::vector; @@ -711,7 +756,7 @@ class MapBase : public MapBaseData Buffers* dbuffs = cgogn::get_dart_buffers(); - Dart it = begin(); + Dart it = begin(mask); Dart last = end(); while (it != last) @@ -727,7 +772,76 @@ class MapBase : public MapBaseData for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != last; ++k) { darts.push_back(it); - next(it); + next(it, mask); + } + + futures[i].push_back(thread_pool->enqueue([&darts, &f] (unsigned int th_id) + { + for (auto d : darts) + f(d, th_id); + })); + } + + const unsigned int id = (i+1u) % 2u; + + for (auto& fu : futures[id]) + fu.wait(); + for (auto& b : dart_buffers[id]) + dbuffs->release_cell_buffer(b); + + futures[id].clear(); + dart_buffers[id].clear(); + + // if we reach the end of the map while filling buffers from the second set we need to clean them too. + if (it == last && i == 1u) + { + for (auto& fu : futures[1u]) + fu.wait(); + for (auto &b : dart_buffers[1u]) + dbuffs->release_buffer(b); + } + } + } + } + + template + inline void parallel_foreach_dart_nomask(const FUNC& f) const + { + static_assert(check_func_ith_parameter_type(FUNC, 0, Dart), "Wrong function first parameter type"); + static_assert(check_func_ith_parameter_type(FUNC, 1, unsigned int), "Wrong function second parameter type"); + + using Future = std::future::type>; + using VecDarts = std::vector; + + ThreadPool* thread_pool = cgogn::get_thread_pool(); + const std::size_t nb_threads_pool = thread_pool->get_nb_threads(); + + std::array, 2> dart_buffers; + std::array, 2> futures; + dart_buffers[0].reserve(nb_threads_pool); + dart_buffers[1].reserve(nb_threads_pool); + futures[0].reserve(nb_threads_pool); + futures[1].reserve(nb_threads_pool); + + Buffers* dbuffs = cgogn::get_dart_buffers(); + + Dart it = begin(); + Dart last = end(); + + while (it != last) + { + for (unsigned int i = 0u; i < 2u; ++i) + { + for (unsigned int j = 0u; j < nb_threads_pool && it != last; ++j) + { + dart_buffers[i].push_back(dbuffs->get_buffer()); + cgogn_assert(dart_buffers[i].size() <= nb_threads_pool); + std::vector& darts = *dart_buffers[i].back(); + darts.reserve(PARALLEL_BUFFER_SIZE); + for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != last; ++k) + { + darts.push_back(it); + next(it); } futures[i].push_back(thread_pool->enqueue([&darts, &f] (unsigned int th_id) @@ -764,13 +878,40 @@ class MapBase : public MapBaseData * @tparam FUNC type of the callable * @param f a callable */ - template + template inline void foreach_dart_until(const FUNC& f) const + { + foreach_dart_until(f, [this] (Dart d) { return !this->is_boundary(d); }); + } + + template + inline void foreach_boundary_dart_until(const FUNC& f) const + { + foreach_dart_until(f, [this] (Dart d) { return this->is_boundary(d); }); + } + + template + inline void foreach_dart_until(const FUNC& f, const MASK& mask) const + { + static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); + static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); + static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); + static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); + + for (Dart it = begin(mask), last = end(); it != last; next(it, mask)) + { + if (!f(it)) + break; + } + } + + template + inline void foreach_dart_until_nomask(const FUNC& f) const { static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); - for (Dart it = begin(), last = end(); it != last; next(it)) + for (Dart it = begin(), last = end(); it != last; next(it)) { if (!f(it)) break; @@ -782,38 +923,73 @@ class MapBase : public MapBaseData * @tparam FUNC type of the callable * @param f a callable */ - template + template inline void foreach_cell(const FUNC& f) const { + foreach_cell(f, [this] (Dart d) { return !this->is_boundary(d); }); + } + + template + inline void foreach_cell_nomask(const FUNC& f) const + { + foreach_cell(f, [this] (Dart) { return true; }); + } + + template + inline void foreach_boundary_cell(const FUNC& f) const + { + foreach_cell(f, [this] (Dart d) { return this->is_boundary(d); }); + } + + template + inline void foreach_cell(const FUNC& f, const MASK& mask) const + { + static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); + static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); + using CellType = typename function_traits::template arg<0>::type; static const Orbit ORBIT = CellType::ORBIT; switch (STRATEGY) { case FORCE_DART_MARKING : - foreach_cell_dart_marking(f); + foreach_cell_dart_marking(f, mask); break; case FORCE_CELL_MARKING : - foreach_cell_cell_marking(f); + foreach_cell_cell_marking(f, mask); break; case FORCE_TOPO_CACHE : - foreach_cell_topo_cache(f); + foreach_cell_topo_cache(f, mask); break; case AUTO : if (is_topo_cache_enabled()) - foreach_cell_topo_cache(f); + foreach_cell_topo_cache(f, mask); else if (this->template is_embedded()) - foreach_cell_cell_marking(f); + foreach_cell_cell_marking(f, mask); else - foreach_cell_dart_marking(f); + foreach_cell_dart_marking(f, mask); break; } } - template + template inline void parallel_foreach_cell(const FUNC& f) const + { + parallel_foreach_cell(f, [this] (Dart d) { return !this->is_boundary(d); }); + } + + template + inline void parallel_foreach_boundary_cell(const FUNC& f) const + { + parallel_foreach_cell(f, [this] (Dart d) { return this->is_boundary(d); }); + } + + template + inline void parallel_foreach_cell(const FUNC& f, const MASK& mask) const { static_assert(check_func_ith_parameter_type(FUNC, 1, unsigned int), "Wrong function second parameter type"); + static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); + static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); using CellType = typename function_traits::template arg<0>::type; static const Orbit ORBIT = CellType::ORBIT; @@ -821,21 +997,21 @@ class MapBase : public MapBaseData switch (STRATEGY) { case FORCE_DART_MARKING : - parallel_foreach_cell_dart_marking(f); + parallel_foreach_cell_dart_marking(f, mask); break; case FORCE_CELL_MARKING : - parallel_foreach_cell_cell_marking(f); + parallel_foreach_cell_cell_marking(f, mask); break; case FORCE_TOPO_CACHE : - parallel_foreach_cell_topo_cache(f); + parallel_foreach_cell_topo_cache(f, mask); break; case AUTO : if (is_topo_cache_enabled()) - parallel_foreach_cell_topo_cache(f); + parallel_foreach_cell_topo_cache(f, mask); else if (this->template is_embedded()) - parallel_foreach_cell_cell_marking(f); + parallel_foreach_cell_cell_marking(f, mask); else - parallel_foreach_cell_dart_marking(f); + parallel_foreach_cell_dart_marking(f, mask); break; } } @@ -845,10 +1021,24 @@ class MapBase : public MapBaseData * @tparam FUNC type of the callable * @param f a callable */ - template - void foreach_cell_until(const FUNC& f) const + template + inline void foreach_cell_until(const FUNC& f) const + { + foreach_cell_until(f, [this] (Dart d) { return !this->is_boundary(d); }); + } + + template + inline void foreach_boundary_cell_until(const FUNC& f) const + { + foreach_cell_until(f, [this] (Dart d) { return this->is_boundary(d); }); + } + + template + void foreach_cell_until(const FUNC& f, const MASK& mask) const { static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); + static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); + static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); using CellType = typename function_traits::template arg<0>::type; static const Orbit ORBIT = CellType::ORBIT; @@ -856,34 +1046,34 @@ class MapBase : public MapBaseData switch (STRATEGY) { case FORCE_DART_MARKING : - foreach_cell_until_dart_marking(f); + foreach_cell_until_dart_marking(f, mask); break; case FORCE_CELL_MARKING : - foreach_cell_until_cell_marking(f); + foreach_cell_until_cell_marking(f, mask); break; case FORCE_TOPO_CACHE : - foreach_cell_until_topo_cache(f); + foreach_cell_until_topo_cache(f, mask); break; case AUTO : if (is_topo_cache_enabled()) - foreach_cell_until_topo_cache(f); + foreach_cell_until_topo_cache(f, mask); else if (this->template is_embedded()) - foreach_cell_until_cell_marking(f); + foreach_cell_until_cell_marking(f, mask); else - foreach_cell_until_dart_marking(f); + foreach_cell_until_dart_marking(f, mask); break; } } protected: - template - inline void foreach_cell_dart_marking(const FUNC& f) const + template + inline void foreach_cell_dart_marking(const FUNC& f, const MASK& mask) const { using CellType = typename function_traits::template arg<0>::type; DartMarker dm(*to_concrete()); - for (Dart it = begin(), last = end(); it != last; next(it)) + for (Dart it = begin(mask), last = end(); it != last; next(it, mask)) { if (!dm.is_marked(it)) { @@ -894,8 +1084,8 @@ class MapBase : public MapBaseData } } - template - inline void parallel_foreach_cell_dart_marking(const FUNC& f) const + template + inline void parallel_foreach_cell_dart_marking(const FUNC& f, const MASK& mask) const { using CellType = typename function_traits::template arg<0>::type; static const Orbit ORBIT = CellType::ORBIT; @@ -916,7 +1106,7 @@ class MapBase : public MapBaseData Buffers* dbuffs = cgogn::get_dart_buffers(); DartMarker dm(*to_concrete()); - Dart it = begin(); + Dart it = begin(mask); Dart last = end(); unsigned int i = 0u; // buffer id (0/1) @@ -936,7 +1126,7 @@ class MapBase : public MapBaseData cells.push_back(c); ++k; } - next(it); + next(it, mask); } //launch thread futures[i].push_back(thread_pool->enqueue([&cells, &f] (unsigned int th_id) @@ -969,14 +1159,14 @@ class MapBase : public MapBaseData dbuffs->release_cell_buffer(b); } - template - inline void foreach_cell_cell_marking(const FUNC& f) const + template + inline void foreach_cell_cell_marking(const FUNC& f, const MASK& mask) const { using CellType = typename function_traits::template arg<0>::type; static const Orbit ORBIT = CellType::ORBIT; CellMarker cm(*to_concrete()); - for (Dart it = begin(), last = end(); it != last; next(it)) + for (Dart it = begin(mask), last = end(); it != last; next(it, mask)) { CellType c(it); if (!cm.is_marked(c)) @@ -987,8 +1177,8 @@ class MapBase : public MapBaseData } } - template - inline void parallel_foreach_cell_cell_marking(const FUNC& f) const + template + inline void parallel_foreach_cell_cell_marking(const FUNC& f, const MASK& mask) const { using CellType = typename function_traits::template arg<0>::type; static const Orbit ORBIT = CellType::ORBIT; @@ -1009,7 +1199,7 @@ class MapBase : public MapBaseData Buffers* dbuffs = cgogn::get_dart_buffers(); CellMarker cm(*to_concrete()); - Dart it = begin(); + Dart it = begin(mask); Dart last = end(); unsigned int i = 0u; // buffer id (0/1) @@ -1029,7 +1219,7 @@ class MapBase : public MapBaseData cells.push_back(c); ++k; } - next(it); + next(it, mask); } // launch thread futures[i].push_back(thread_pool->enqueue([&cells, &f] (unsigned int th_id) @@ -1062,8 +1252,8 @@ class MapBase : public MapBaseData dbuffs->release_cell_buffer(b); } - template - inline void foreach_cell_topo_cache(const FUNC& f) const + template + inline void foreach_cell_topo_cache(const FUNC& f, const MASK& mask) const { using CellType = typename function_traits::template arg<0>::type; static const Orbit ORBIT = CellType::ORBIT; @@ -1074,7 +1264,7 @@ class MapBase : public MapBaseData unsigned int it = attr.begin(); const unsigned int end = attr.end(); // find first valid dart in the topo cache - while (it != end && !is_masked(cache[it])) + while (it != end && !mask(cache[it])) { attr.next(it); } @@ -1086,12 +1276,12 @@ class MapBase : public MapBaseData do { attr.next(it); - } while (it != end && !is_masked(cache[it])); + } while (it != end && !mask(cache[it])); } } - template - inline void parallel_foreach_cell_topo_cache(const FUNC& f) const + template + inline void parallel_foreach_cell_topo_cache(const FUNC& f, const MASK& mask) const { using CellType = typename function_traits::template arg<0>::type; static const Orbit ORBIT = CellType::ORBIT; @@ -1112,7 +1302,7 @@ class MapBase : public MapBaseData unsigned int it = attr.begin(); const unsigned int end = attr.end(); // find first valid dart in the topo cache - while (it != end && !is_masked(cache[it])) + while (it != end && !mask(cache[it])) { attr.next(it); } @@ -1127,11 +1317,11 @@ class MapBase : public MapBaseData unsigned int local_end = std::min(it+nbc, end); unsigned int i = 0; // used buffered futures 0/1 - unsigned int j = 0; // thread num, const MASK& mask + unsigned int j = 0; // thread num while (it != end) { - futures[i].push_back(thread_pool->enqueue([&cache, &attr, it, local_end, &f] (unsigned int th_id) + futures[i].push_back(thread_pool->enqueue([&cache, &attr, &mask, it, local_end, &f] (unsigned int th_id) { unsigned int loc_it = it; while (loc_it < local_end) @@ -1140,7 +1330,7 @@ class MapBase : public MapBaseData do { attr.next(loc_it); - } while (loc_it != local_end && !is_masked(cache[loc_it])); + } while (loc_it != local_end && !mask(cache[loc_it])); } })); it = local_end; @@ -1164,13 +1354,13 @@ class MapBase : public MapBaseData fu.wait(); } - template - inline void foreach_cell_until_dart_marking(const FUNC& f) const + template + inline void foreach_cell_until_dart_marking(const FUNC& f, const MASK& mask) const { using CellType = typename function_traits::template arg<0>::type; DartMarker dm(*to_concrete()); - for (Dart it = begin(), last = end(); it != last; next(it)) + for (Dart it = begin(mask), last = end(); it != last; next(it, mask)) { if (!dm.is_marked(it)) { @@ -1182,14 +1372,14 @@ class MapBase : public MapBaseData } } - template - inline void foreach_cell_until_cell_marking(const FUNC& f) const + template + inline void foreach_cell_until_cell_marking(const FUNC& f, const MASK& mask) const { using CellType = typename function_traits::template arg<0>::type; static const Orbit ORBIT = CellType::ORBIT; CellMarker cm(*to_concrete()); - for (Dart it = begin(), last = end(); it != last; next(it)) + for (Dart it = begin(mask), last = end(); it != last; next(it, mask)) { CellType c(it); if (!cm.is_marked(c)) @@ -1201,8 +1391,8 @@ class MapBase : public MapBaseData } } - template - inline void foreach_cell_until_topo_cache(const FUNC& f) const + template + inline void foreach_cell_until_topo_cache(const FUNC& f, const MASK& mask) const { using CellType = typename function_traits::template arg<0>::type; static const Orbit ORBIT = CellType::ORBIT; @@ -1214,7 +1404,7 @@ class MapBase : public MapBaseData const unsigned int end = attr.end(); Dart d = cache[it]; // find first valid dart in the topo cache - while (it != end && !is_masked(d)) + while (it != end && !mask.valid(d)) { attr.next(it); d = cache[it]; @@ -1229,7 +1419,7 @@ class MapBase : public MapBaseData { attr.next(it); d = cache[it]; - } while (it != end && !is_masked(d)); + } while (it != end && !mask.valid(d)); } } }; diff --git a/cgogn/core/tests/cmap/cmap2_test.cpp b/cgogn/core/tests/cmap/cmap2_test.cpp index 070c6220..fab9b7ec 100644 --- a/cgogn/core/tests/cmap/cmap2_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_test.cpp @@ -133,28 +133,28 @@ class CMap2Test : public ::testing::Test } } // Close the map (remove remaining boundary) - cmap_.template foreach_dart( [&] (Dart d) + cmap_.foreach_dart_nomask( [&] (Dart d) { if (cmap_.phi2(d) == d) mbuild.close_hole_topo(d); }); // Embed the map - cmap_.template foreach_cell( [&] (CDart d) + cmap_.foreach_dart_nomask( [&] (Dart d) { - mbuild.new_orbit_embedding(d); + mbuild.new_orbit_embedding(CDart(d)); }); - cmap_.template foreach_cell( [&] (Vertex v) + cmap_.foreach_cell_nomask( [&] (Vertex v) { mbuild.new_orbit_embedding(v); }); - cmap_.template foreach_cell( [&] (Edge e) + cmap_.foreach_cell_nomask( [&] (Edge e) { mbuild.new_orbit_embedding(e); }); - cmap_.template foreach_cell( [&] (Face f) + cmap_.foreach_cell_nomask( [&] (Face f) { mbuild.new_orbit_embedding(f); }); - cmap_.template foreach_cell( [&] (Volume w) + cmap_.foreach_cell_nomask( [&] (Volume w) { mbuild.new_orbit_embedding(w); }); From 543aaafc161495c2886289b3fcb5363e02c5b22d Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Thu, 17 Mar 2016 14:50:56 +0100 Subject: [PATCH 346/402] zero warning on mac --- thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt | 7 ++++++- thirdparty/libQGLViewer/QOGLViewer/qoglviewer.cpp | 10 +++++----- thirdparty/lm6/transmesh.c | 10 +++++----- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt b/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt index 8945ea81..1f535efb 100644 --- a/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt +++ b/thirdparty/libQGLViewer/QOGLViewer/CMakeLists.txt @@ -48,7 +48,12 @@ if(WIN32) else() target_compile_options(${PROJECT_NAME} PUBLIC "-std=c++11") ADD_DEFINITIONS(-fPIC) -endif() +endif() + +# for glu warning on mac +if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + add_flags(CMAKE_CXX_FLAGS "-Wno-deprecated-declarations") +endif() diff --git a/thirdparty/libQGLViewer/QOGLViewer/qoglviewer.cpp b/thirdparty/libQGLViewer/QOGLViewer/qoglviewer.cpp index b5288e02..8d6464ee 100644 --- a/thirdparty/libQGLViewer/QOGLViewer/qoglviewer.cpp +++ b/thirdparty/libQGLViewer/QOGLViewer/qoglviewer.cpp @@ -1972,17 +1972,17 @@ void QOGLViewer::handleKeyboardAction(KeyboardAction id) { switch (id) { -// case DRAW_AXIS : toggleAxisIsDrawn(); break; -// case DRAW_GRID : toggleGridIsDrawn(); break; -// case DISPLAY_FPS : toggleFPSIsDisplayed(); break; -// case ENABLE_TEXT : toggleTextIsEnabled(); break; + case DRAW_AXIS : /*toggleAxisIsDrawn();*/ break; + case DRAW_GRID : /*toggleGridIsDrawn();*/ break; + case DISPLAY_FPS : /*toggleFPSIsDisplayed();*/ break; + case ENABLE_TEXT : /*toggleTextIsEnabled();*/ break; case EXIT_VIEWER : qApp->closeAllWindows(); break; case SAVE_SCREENSHOT : saveSnapshot(false, false); break; case FULL_SCREEN : toggleFullScreen(); break; case STEREO : toggleStereoDisplay(); break; case ANIMATION : toggleAnimation(); break; case HELP : help(); break; -// case EDIT_CAMERA : toggleCameraIsEdited(); break; + case EDIT_CAMERA : /*toggleCameraIsEdited();*/ break; case SNAPSHOT_TO_CLIPBOARD : snapshotToClipboard(); break; case CAMERA_MODE : toggleCameraMode(); diff --git a/thirdparty/lm6/transmesh.c b/thirdparty/lm6/transmesh.c index 1a621a61..1f115e09 100644 --- a/thirdparty/lm6/transmesh.c +++ b/thirdparty/lm6/transmesh.c @@ -111,27 +111,27 @@ int main(int argc, char **argv) if(strcmp("i", GmfKwdFmt[i][2])) { - if(NmbLin = GmfStatKwd(InpIdx, i)) + if((NmbLin = GmfStatKwd(InpIdx, i))) GmfSetKwd(OutIdx, i); else continue; } - else if(strcmp("sr", GmfKwdFmt[i][3])) + else if((strcmp("sr", GmfKwdFmt[i][3]))) { - if(NmbLin = GmfStatKwd(InpIdx, i)) + if((NmbLin = GmfStatKwd(InpIdx, i))) GmfSetKwd(OutIdx, i, NmbLin); else continue; } else { - if(NmbLin = GmfStatKwd(InpIdx, i, &NmbTyp, &SolSiz, TypTab)) + if((NmbLin = GmfStatKwd(InpIdx, i, &NmbTyp, &SolSiz, TypTab))) GmfSetKwd(OutIdx, i, NmbLin, NmbTyp, TypTab); else continue; } - printf("Parsing %s : %d item\n", GmfKwdFmt[i][0], NmbLin); + printf("Parsing %s : %ld item\n", GmfKwdFmt[i][0], NmbLin); for(j=1;j<=NmbLin;j++) GmfCpyLin(InpIdx, OutIdx, i); From 4c3b85e7ccbb2b19b1d64e010b0ee0a0a1c18dfc Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Thu, 17 Mar 2016 16:43:12 +0100 Subject: [PATCH 347/402] mark boundary as boundary in close_hole --- cgogn/core/cmap/cmap2_builder.h | 7 +++++++ cgogn/core/cmap/cmap3_builder.h | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/cgogn/core/cmap/cmap2_builder.h b/cgogn/core/cmap/cmap2_builder.h index 47676628..145aa04d 100644 --- a/cgogn/core/cmap/cmap2_builder.h +++ b/cgogn/core/cmap/cmap2_builder.h @@ -201,10 +201,17 @@ class CMap2Builder_T }, [] (Dart) { return true; } ); + for (Dart d : fix_point_darts) { if (map_.phi2(d) == d) + { close_hole(d); + map_.foreach_dart_of_orbit(Face(map_.phi2(d)), [&] (Dart db) + { + map_.set_boundary(db,true); + }); + } } } diff --git a/cgogn/core/cmap/cmap3_builder.h b/cgogn/core/cmap/cmap3_builder.h index 2a2e7fe0..484414b0 100644 --- a/cgogn/core/cmap/cmap3_builder.h +++ b/cgogn/core/cmap/cmap3_builder.h @@ -210,6 +210,10 @@ class CMap3Builder_T { ++nb; close_hole_topo(d); + map_.foreach_dart_of_orbit(Volume(map_.phi3(d)), [&] (Dart db) + { + map_.set_boundary(db,true); + }); const Volume new_volume(map_.phi3(d)); if (map_.template is_embedded()) From 0a988fbdc4d55aad08b6806a7ad755ee014c383b Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Thu, 17 Mar 2016 16:45:25 +0100 Subject: [PATCH 348/402] fix volume picking bug in map3 --- cgogn/geometry/algos/picking.h | 46 +++++++++++---------- cgogn/rendering/examples/picking_viewer.cpp | 8 ++-- cgogn/rendering/examples/viewer_topo3.cpp | 4 +- 3 files changed, 30 insertions(+), 28 deletions(-) diff --git a/cgogn/geometry/algos/picking.h b/cgogn/geometry/algos/picking.h index 1597c806..6d64c35e 100644 --- a/cgogn/geometry/algos/picking.h +++ b/cgogn/geometry/algos/picking.h @@ -44,8 +44,8 @@ namespace geometry { -template -inline void picking_internal_face(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector>& selected ) +template +inline void picking_internal_face(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector>& selected ) { using Vertex = typename MAP::Vertex; using Face = typename MAP::Face; @@ -57,11 +57,11 @@ inline void picking_internal_face(MAP& m, const typename MAP::template VertexAtt // thread data - using Triplet = typename std::vector>; + using Triplet = typename std::vector>; std::vector selected_th(cgogn::get_nb_threads()); std::vector> ear_indices_th(cgogn::get_nb_threads()); - m.parallel_foreach_cell([&] (Face f, unsigned int th) + m.parallel_foreach_cell([&] (CELL_FACE f, unsigned int th) { VEC3 inter; if (m.has_degree(f,3)) @@ -76,7 +76,7 @@ inline void picking_internal_face(MAP& m, const typename MAP::template VertexAtt { std::vector& ear_indices = ear_indices_th[th]; ear_indices.clear(); - cgogn::geometry::compute_ear_triangulation(m,f,position,ear_indices); + cgogn::geometry::compute_ear_triangulation(m,Face(f.dart),position,ear_indices); for(std::size_t i=0; i& f1, const std::tuple& f2) -> bool + auto dist_sort = [] (const std::tuple& f1, const std::tuple& f2) -> bool { return std::get<2>(f1) < std::get<2>(f2); }; @@ -109,28 +109,31 @@ inline void picking_internal_face(MAP& m, const typename MAP::template VertexAtt } template -bool picking_face(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector& selected) +bool picking_faces(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector& selected) { typename std::vector> sel; - picking_internal_face(m,position,A,B,sel); + picking_internal_face(m,position,A,B,sel); + DartMarkerStore dm(m); selected.clear(); for (auto fs: sel) + { selected.push_back(std::get<0>(fs)); + } return !selected.empty(); } template -bool picking_vertex(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector& selected) +bool picking_vertices(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector& selected) { using Vertex = typename MAP::Vertex; using Face = typename MAP::Face; using Scalar = typename VEC3::Scalar; - typename std::vector> sel; - picking_internal_face(m,position,A,B,sel); + typename std::vector> sel; + picking_internal_face(m,position,A,B,sel); DartMarkerStore dm(m); selected.clear(); @@ -164,15 +167,15 @@ bool picking_vertex(MAP& m, const typename MAP::template VertexAttributeHandler< template -bool picking_edge(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector& selected) +bool picking_edges(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector& selected) { using Vertex = typename MAP::Vertex; using Edge = typename MAP::Edge; using Face = typename MAP::Face; using Scalar = typename VEC3::Scalar; - typename std::vector> sel; - picking_internal_face(m,position,A,B,sel); + typename std::vector> sel; + picking_internal_face(m,position,A,B,sel); DartMarkerStore dm(m); selected.clear(); @@ -206,22 +209,21 @@ bool picking_edge(MAP& m, const typename MAP::template VertexAttributeHandler -bool picking_volume(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector& selected) +bool picking_volumes(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector& selected) { - using Vertex = typename MAP::Vertex; - using Edge = typename MAP::Edge; - using Face = typename MAP::Face; + //here used Face2 for selecting the 2 volumes incident to selected faces + + using Face2 = Cell; using Volume = typename MAP::Volume; - using Scalar = typename VEC3::Scalar; - typename std::vector> sel; - picking_internal_face(m,position,A,B,sel); + typename std::vector> sel; + picking_internal_face(m,position,A,B,sel); selected.clear(); DartMarker dm(m); for (auto fs: sel) { - Face f = std::get<0>(fs); + Face2 f = std::get<0>(fs); Volume vo = Volume(f.dart); if (!dm.is_marked(vo.dart)) { diff --git a/cgogn/rendering/examples/picking_viewer.cpp b/cgogn/rendering/examples/picking_viewer.cpp index 68587936..bd0ae989 100644 --- a/cgogn/rendering/examples/picking_viewer.cpp +++ b/cgogn/rendering/examples/picking_viewer.cpp @@ -222,7 +222,7 @@ void Viewer::mousePressEvent(QMouseEvent* event) case 0: { std::vector selected; - cgogn::geometry::picking_vertex(map_,vertex_position_,A,B,selected); + cgogn::geometry::picking_vertices(map_,vertex_position_,A,B,selected); std::cout<< "Selected vertices: "<< selected.size()< selected; - cgogn::geometry::picking_edge(map_,vertex_position_,A,B,selected); + cgogn::geometry::picking_edges(map_,vertex_position_,A,B,selected); std::cout<< "Selected edges: "<< selected.size()< selected; - cgogn::geometry::picking_face(map_,vertex_position_,A,B,selected); + cgogn::geometry::picking_faces(map_,vertex_position_,A,B,selected); std::cout<< "Selected faces: "<< selected.size()< selected; - cgogn::geometry::picking_volume(map_,vertex_position_,A,B,selected); + cgogn::geometry::picking_volumes(map_,vertex_position_,A,B,selected); std::cout<< "Selected volumes: "<< selected.size()<new_list(); - + std::vector selected; - cgogn::geometry::picking_volume(map_, vertex_position_, A, B, selected); + cgogn::geometry::picking_volumes(map_, vertex_position_, A, B, selected); std::cout << "Selected volumes: " << selected.size() << std::endl; if (!selected.empty()) { From 614b4754b3b96f33aeecc8ce774f251818e3a32d Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Thu, 17 Mar 2016 16:51:37 +0100 Subject: [PATCH 349/402] remove commented lines --- cgogn/core/cmap/cmap3.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index dd2943a8..5fa0546a 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -602,7 +602,6 @@ class CMap3_T : public CMap2_T inline void foreach_incident_vertex(Volume v, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); -// Inherit::foreach_incident_vertex(v, func); Inherit::foreach_incident_vertex(v, [&func] (Vertex2 ve) { func(Vertex(ve.dart)); @@ -613,7 +612,6 @@ class CMap3_T : public CMap2_T inline void foreach_incident_edge(Volume v, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); -// Inherit::foreach_incident_edge(v, func); Inherit::foreach_incident_edge(v, [&func] (Edge2 e) { func(Edge(e.dart)); @@ -624,7 +622,6 @@ class CMap3_T : public CMap2_T inline void foreach_incident_face(Volume v, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); -// Inherit::foreach_incident_face(v, func); Inherit::foreach_incident_face(v, [&func] (Face2 f) { func(Face(f.dart)); @@ -926,8 +923,6 @@ class CMap3_T : public CMap2_T } }; - - template struct CMap3Type { From 313baacaeb7883dc4d751e02d577605f6d6ec62c Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Thu, 17 Mar 2016 18:14:13 +0100 Subject: [PATCH 350/402] Back to the mask :) --- cgogn/core/cmap/cmap2_builder.h | 8 +- cgogn/core/cmap/map_base.h | 160 +++++++++++--------------------- cgogn/core/utils/assert.h | 5 +- 3 files changed, 60 insertions(+), 113 deletions(-) diff --git a/cgogn/core/cmap/cmap2_builder.h b/cgogn/core/cmap/cmap2_builder.h index 59c165c9..25f10522 100644 --- a/cgogn/core/cmap/cmap2_builder.h +++ b/cgogn/core/cmap/cmap2_builder.h @@ -199,17 +199,11 @@ class CMap2Builder_T */ inline void close_map() { - std::vector fix_point_darts; map_.foreach_dart_nomask( [&] (Dart d) { if (map_.phi2(d) == d) - fix_point_darts.push_back(d); + close_hole(d); }); - for (Dart d : fix_point_darts) - { - if (map_.phi2(d) == d) - close_hole(d); - } } private: diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 551f1f98..44eb39ff 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -626,23 +626,39 @@ class MapBase : public MapBaseData template inline Dart begin(const MASK& mask) const { - Dart d = Dart(this->topology_.begin()); - Dart end = Dart(this->topology_.end()); + if (check_func_return_void(MASK)) { + return Dart(this->topology_.begin()); + } + else { + static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); + static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); - while (d != end && !mask(d)) - this->topology_.next(d.index); + Dart d = Dart(this->topology_.begin()); + Dart end = Dart(this->topology_.end()); - return d; + while (d != end && !mask(d)) + this->topology_.next(d.index); + + return d; + } } template inline void next(Dart& d, const MASK& mask) const { - Dart end = Dart(this->topology_.end()); - - do { + if (check_func_return_void(MASK)) { this->topology_.next(d.index); - } while (d != end && !mask(d)); + } + else { + static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); + static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); + + Dart end = Dart(this->topology_.end()); + + do { + this->topology_.next(d.index); + } while (d != end && !mask(d)); + } } inline Dart end() const @@ -654,17 +670,21 @@ class MapBase : public MapBaseData * \Brief Specialized methods to iterate over all darts. * All darts are traversed without any MASK filtering. */ - inline Dart begin(const bool&) const - { - Dart d = Dart(this->topology_.begin()); +// std::function nomask = [] () { return true; }; - return d; - } +// template <> +// inline Dart begin(const std::function& mask) const +// { +// Dart d = Dart(this->topology_.begin()); - inline void next(Dart& d, const bool&) const - { - this->topology_.next(d.index); - } +// return d; +// } + +// template<> +// inline void next(Dart& d, const std::function&) const +// { +// this->topology_.next(d.index); +// } // inline Dart begin() const // { @@ -684,43 +704,38 @@ class MapBase : public MapBaseData * @param f a callable */ template - inline void foreach_dart(const FUNC& f) const + inline void foreach_dart_nomask(const FUNC& f) const { - foreach_dart(f, [this] (Dart d) { return !this->is_boundary(d); }); +// static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); + +// for (Dart it = begin(), last = end(); it != last; next(it)) +// f(it); + + foreach_dart(f, [] (Dart) { return true; } ); +// foreach_dart(f, [] (Dart) -> void {} ); } template - inline void foreach_boundary_dart(const FUNC& f) const + inline void foreach_dart(const FUNC& f) const { - foreach_dart(f, [this] (Dart d) { return this->is_boundary(d); }); + foreach_dart(f, [this] (Dart d) { return !this->is_boundary(d); }); } template - inline void foreach_dart_nomask(const FUNC& f) const + inline void foreach_boundary_dart(const FUNC& f) const { - foreach_dart(f, true); + foreach_dart(f, [this] (Dart d) { return this->is_boundary(d); }); } template inline void foreach_dart(const FUNC& f, const MASK& mask) const { static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); -// static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); -// static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); for (Dart it = begin(mask), last = end(); it != last; next(it, mask)) f(it); } -// template -// inline void foreach_dart_nomask(const FUNC& f) const -// { -// static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); - -// for (Dart it = begin(), last = end(); it != last; next(it)) -// f(it); -// } - template inline void parallel_foreach_dart(const FUNC& f) const { @@ -733,6 +748,12 @@ class MapBase : public MapBaseData parallel_foreach_dart(f, [this] (Dart d) { return this->is_boundary(d); }); } + template + inline void parallel_foreach_dart_nomask(const FUNC& f) const + { + parallel_foreach_dart(f, [] (Dart) { return true;} ); + } + template inline void parallel_foreach_dart(const FUNC& f, const MASK& mask) const { @@ -804,75 +825,6 @@ class MapBase : public MapBaseData } } - template - inline void parallel_foreach_dart_nomask(const FUNC& f) const - { - static_assert(check_func_ith_parameter_type(FUNC, 0, Dart), "Wrong function first parameter type"); - static_assert(check_func_ith_parameter_type(FUNC, 1, unsigned int), "Wrong function second parameter type"); - - using Future = std::future::type>; - using VecDarts = std::vector; - - ThreadPool* thread_pool = cgogn::get_thread_pool(); - const std::size_t nb_threads_pool = thread_pool->get_nb_threads(); - - std::array, 2> dart_buffers; - std::array, 2> futures; - dart_buffers[0].reserve(nb_threads_pool); - dart_buffers[1].reserve(nb_threads_pool); - futures[0].reserve(nb_threads_pool); - futures[1].reserve(nb_threads_pool); - - Buffers* dbuffs = cgogn::get_dart_buffers(); - - Dart it = begin(); - Dart last = end(); - - while (it != last) - { - for (unsigned int i = 0u; i < 2u; ++i) - { - for (unsigned int j = 0u; j < nb_threads_pool && it != last; ++j) - { - dart_buffers[i].push_back(dbuffs->get_buffer()); - cgogn_assert(dart_buffers[i].size() <= nb_threads_pool); - std::vector& darts = *dart_buffers[i].back(); - darts.reserve(PARALLEL_BUFFER_SIZE); - for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != last; ++k) - { - darts.push_back(it); - next(it); - } - - futures[i].push_back(thread_pool->enqueue([&darts, &f] (unsigned int th_id) - { - for (auto d : darts) - f(d, th_id); - })); - } - - const unsigned int id = (i+1u) % 2u; - - for (auto& fu : futures[id]) - fu.wait(); - for (auto& b : dart_buffers[id]) - dbuffs->release_cell_buffer(b); - - futures[id].clear(); - dart_buffers[id].clear(); - - // if we reach the end of the map while filling buffers from the second set we need to clean them too. - if (it == last && i == 1u) - { - for (auto& fu : futures[1u]) - fu.wait(); - for (auto &b : dart_buffers[1u]) - dbuffs->release_buffer(b); - } - } - } - } - /** * \brief apply a function on each dart of the map and stops when the function returns false * @tparam FUNC type of the callable diff --git a/cgogn/core/utils/assert.h b/cgogn/core/utils/assert.h index 4196f64b..2054e16c 100644 --- a/cgogn/core/utils/assert.h +++ b/cgogn/core/utils/assert.h @@ -64,8 +64,8 @@ CGOGN_CORE_API CGOGN_NORETURN void assertion_failed( /** * Prints an unreachable location failure. * This function is called when execution reaches a point that - * should not be reached. It prints an error message and - * terminates the program. + * should not be reached. It prints an error message and + * terminates the program. * \param[in] message string information message to print out. * \param[in] file_name file where the assertion failed. * \param[in] function_name function where the assertion failed. @@ -235,6 +235,7 @@ struct function_traits #define check_func_parameter_type(F, T) std::is_same::template arg<0>::type , T>::value #define check_func_ith_parameter_type(F, i, T) std::is_same::template arg::type , T>::value +#define check_func_return_void(F) std::is_void::result_type>::value #define check_func_return_type(F, T) std::is_same::result_type , T>::value #define inside_type(ATTR) typename std::remove_cv< typename std::remove_reference::type >::type From 00819fe21b371cff6e93669c6b7d7f75c8324fa7 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Thu, 17 Mar 2016 18:33:34 +0100 Subject: [PATCH 351/402] use foreach_incident_volume in picking --- cgogn/core/cmap/cmap2.h | 21 ++++++++++++ cgogn/core/cmap/cmap3.h | 21 +++++++++++- cgogn/geometry/algos/picking.h | 39 ++++++++++++----------- cgogn/rendering/examples/viewer_topo3.cpp | 4 ++- 4 files changed, 65 insertions(+), 20 deletions(-) diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 475d93bc..ad0212b6 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -694,6 +694,27 @@ class CMap2_T : public CMap1_T }); } + template + inline void foreach_incident_volume(Face f, const FUNC& func) const + { + static_assert(check_func_parameter_type(FUNC, Volume), "Wrong function cell parameter type"); + func(Volume(f.dart)); + } + + template + inline void foreach_incident_volume(Edge e, const FUNC& func) const + { + static_assert(check_func_parameter_type(FUNC, Volume), "Wrong function cell parameter type"); + func(Volume(e.dart)); + } + + template + inline void foreach_incident_volume(Vertex v, const FUNC& func) const + { + static_assert(check_func_parameter_type(FUNC, Volume), "Wrong function cell parameter type"); + func(Volume(v.dart)); + } + /******************************************************************************* * Adjacence traversal *******************************************************************************/ diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 5fa0546a..7a3d5ceb 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -594,7 +594,7 @@ class CMap3_T : public CMap2_T inline void foreach_incident_volume(Face f, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Volume), "Wrong function cell parameter type"); - func(Volume(f)); + func(Volume(f.dart)); func(Volume(phi3(f.dart))); } @@ -666,6 +666,25 @@ class CMap3_T : public CMap2_T Inherit::foreach_incident_edge(f,func); } + template + inline void foreach_incident_volume(Face2 f, const FUNC& func) const + { + Inherit::foreach_incident_volume(f,func); + } + + template + inline void foreach_incident_volume(Edge2 e, const FUNC& func) const + { + Inherit::foreach_incident_volume(e,func); + } + + template + inline void foreach_incident_volume(Vertex2 v, const FUNC& func) const + { + Inherit::foreach_incident_volume(v,func); + } + + /******************************************************************************* * Adjacence traversal *******************************************************************************/ diff --git a/cgogn/geometry/algos/picking.h b/cgogn/geometry/algos/picking.h index 6d64c35e..0e5132db 100644 --- a/cgogn/geometry/algos/picking.h +++ b/cgogn/geometry/algos/picking.h @@ -44,8 +44,8 @@ namespace geometry { -template -inline void picking_internal_face(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector>& selected ) +template +inline void picking_internal_face(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector>& selected ) { using Vertex = typename MAP::Vertex; using Face = typename MAP::Face; @@ -57,11 +57,11 @@ inline void picking_internal_face(MAP& m, const typename MAP::template VertexAtt // thread data - using Triplet = typename std::vector>; + using Triplet = typename std::vector>; std::vector selected_th(cgogn::get_nb_threads()); std::vector> ear_indices_th(cgogn::get_nb_threads()); - m.parallel_foreach_cell([&] (CELL_FACE f, unsigned int th) + m.parallel_foreach_cell([&] (Face f, unsigned int th) { VEC3 inter; if (m.has_degree(f,3)) @@ -76,7 +76,7 @@ inline void picking_internal_face(MAP& m, const typename MAP::template VertexAtt { std::vector& ear_indices = ear_indices_th[th]; ear_indices.clear(); - cgogn::geometry::compute_ear_triangulation(m,Face(f.dart),position,ear_indices); + cgogn::geometry::compute_ear_triangulation(m,f,position,ear_indices); for(std::size_t i=0; i& f1, const std::tuple& f2) -> bool + auto dist_sort = [] (const std::tuple& f1, const std::tuple& f2) -> bool { return std::get<2>(f1) < std::get<2>(f2); }; @@ -112,7 +112,7 @@ template bool picking_faces(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector& selected) { typename std::vector> sel; - picking_internal_face(m,position,A,B,sel); + picking_internal_face(m,position,A,B,sel); DartMarkerStore dm(m); selected.clear(); @@ -133,7 +133,7 @@ bool picking_vertices(MAP& m, const typename MAP::template VertexAttributeHandle using Scalar = typename VEC3::Scalar; typename std::vector> sel; - picking_internal_face(m,position,A,B,sel); + picking_internal_face(m,position,A,B,sel); DartMarkerStore dm(m); selected.clear(); @@ -175,7 +175,7 @@ bool picking_edges(MAP& m, const typename MAP::template VertexAttributeHandler> sel; - picking_internal_face(m,position,A,B,sel); + picking_internal_face(m,position,A,B,sel); DartMarkerStore dm(m); selected.clear(); @@ -213,23 +213,26 @@ bool picking_volumes(MAP& m, const typename MAP::template VertexAttributeHandler { //here used Face2 for selecting the 2 volumes incident to selected faces - using Face2 = Cell; + using Face = typename MAP::Face; using Volume = typename MAP::Volume; - typename std::vector> sel; - picking_internal_face(m,position,A,B,sel); + typename std::vector> sel; + picking_internal_face(m,position,A,B,sel); selected.clear(); DartMarker dm(m); for (auto fs: sel) { - Face2 f = std::get<0>(fs); - Volume vo = Volume(f.dart); - if (!dm.is_marked(vo.dart)) + Face f = std::get<0>(fs); + m.foreach_incident_volume(f, [&] (Volume vo) { - dm.mark_orbit(vo); - selected.push_back(vo); - } + if ((!dm.is_marked(vo.dart)) && (!m.is_boundary(vo.dart))) + { + dm.mark_orbit(vo); + selected.push_back(vo); + } + + }); } return !selected.empty(); } diff --git a/cgogn/rendering/examples/viewer_topo3.cpp b/cgogn/rendering/examples/viewer_topo3.cpp index 15ea5d5c..d3eb8c9b 100644 --- a/cgogn/rendering/examples/viewer_topo3.cpp +++ b/cgogn/rendering/examples/viewer_topo3.cpp @@ -135,7 +135,7 @@ Viewer::Viewer() : vol_rendering_(true), edge_rendering_(true), topo_rendering_(true), - expl_(0.7f) + expl_(0.8f) {} void Viewer::keyPressEvent(QKeyEvent *ev) @@ -252,9 +252,11 @@ void Viewer::init() cgogn::rendering::update_vbo(vertex_position_, *vbo_pos_); topo_render_ = new cgogn::rendering::TopoRender(this); + topo_render_->set_explode_volume(expl_); topo_render_->update_map3(map_,vertex_position_); volume_render_ = new cgogn::rendering::VolumeRender(this); + volume_render_->set_explode_volume(expl_); volume_render_->update_face(map_,vertex_position_); volume_render_->update_edge(map_,vertex_position_); From 985186d486dfa75ebd39b18aa8f53a3922c18280 Mon Sep 17 00:00:00 2001 From: thery Date: Thu, 17 Mar 2016 18:39:43 +0100 Subject: [PATCH 352/402] pb compil --- cgogn/rendering/shaders/shader_program.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cgogn/rendering/shaders/shader_program.h b/cgogn/rendering/shaders/shader_program.h index 01ff8508..11028cfc 100644 --- a/cgogn/rendering/shaders/shader_program.h +++ b/cgogn/rendering/shaders/shader_program.h @@ -29,6 +29,7 @@ #include #include + #include namespace cgogn @@ -39,7 +40,7 @@ namespace rendering //convenient conversion function inline void* void_ptr(unsigned int x) { - return reinterpret_cast(std::uint64_t(x)); + return reinterpret_cast(uint64_t(x)); } From 9ff361434e69fc0cc95e7573887efed6a1737c4d Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Thu, 17 Mar 2016 18:22:15 +0100 Subject: [PATCH 353/402] added tetgen_io and examples. Signed-off-by: Etienne Schmitt --- cgogn/io/mesh_generation/CMakeLists.txt | 30 +- .../mesh_generation/examples/CMakeLists.txt | 22 +- .../examples/map3_from_surface.cpp | 125 ++++++ cgogn/io/mesh_generation/tetgen_io.cpp | 38 ++ cgogn/io/mesh_generation/tetgen_io.h | 420 ++++++++++++++++++ data/meshes/pyramid.vtk | Bin 0 -> 249 bytes 6 files changed, 617 insertions(+), 18 deletions(-) create mode 100644 cgogn/io/mesh_generation/examples/map3_from_surface.cpp create mode 100644 cgogn/io/mesh_generation/tetgen_io.cpp create mode 100644 cgogn/io/mesh_generation/tetgen_io.h create mode 100644 data/meshes/pyramid.vtk diff --git a/cgogn/io/mesh_generation/CMakeLists.txt b/cgogn/io/mesh_generation/CMakeLists.txt index 1af9a7e0..0adb430e 100644 --- a/cgogn/io/mesh_generation/CMakeLists.txt +++ b/cgogn/io/mesh_generation/CMakeLists.txt @@ -7,23 +7,33 @@ project(cgogn_io_mesh_generation ) set(HEADER_FILES - c3t3_io.h + tetgen_io.h ) set(SOURCE_FILES - c3t3_io.cpp + tetgen_io.cpp ) if (CGAL_FOUND) - add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) + set( HEADER_FILES + ${HEADER_FILES} + c3t3_io.h + ) - target_include_directories(${PROJECT_NAME} PUBLIC - $ - $ + set( SOURCE_FILES + ${SOURCE_FILES} + c3t3_io.cpp ) - target_link_libraries(${PROJECT_NAME} cgogn_core cgogn_io) endif() -if (CGOGN_WITH_CGAL_EXAMPLES) - add_subdirectory(examples) -endif() + +add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) + +target_include_directories(${PROJECT_NAME} PUBLIC + $ + $ +) +target_link_libraries(${PROJECT_NAME} cgogn_core cgogn_io tet) + + +add_subdirectory(examples) diff --git a/cgogn/io/mesh_generation/examples/CMakeLists.txt b/cgogn/io/mesh_generation/examples/CMakeLists.txt index a1b4b684..08558b35 100644 --- a/cgogn/io/mesh_generation/examples/CMakeLists.txt +++ b/cgogn/io/mesh_generation/examples/CMakeLists.txt @@ -14,13 +14,19 @@ set(SOURCE_FILES program_options.cpp ) -find_package(MPFR REQUIRED) -find_package(GMP REQUIRED) -find_package(Boost QUIET REQUIRED COMPONENTS thread program_options) +if (CGOGN_WITH_CGAL_EXAMPLES) + find_package(MPFR REQUIRED) + find_package(GMP REQUIRED) + find_package(Boost QUIET REQUIRED COMPONENTS thread program_options) -set(CGOGN_TEST_PREFIX "test_") -set(CGOGN_TEST_IMAGES_PATH "${CMAKE_SOURCE_DIR}/data/images/") -add_definitions("-DCGOGN_TEST_IMAGES_PATH=${CGOGN_TEST_IMAGES_PATH}") + set(CGOGN_TEST_PREFIX "test_") + set(CGOGN_TEST_IMAGES_PATH "${CMAKE_SOURCE_DIR}/data/images/") + add_definitions("-DCGOGN_TEST_IMAGES_PATH=${CGOGN_TEST_IMAGES_PATH}") + add_executable(map3_from_image ${HEADER_FILES} ${SOURCE_FILES}) + target_link_libraries(map3_from_image cgogn_core cgogn_io_mesh_generation ${Boost_LIBRARIES} ${GMP_LIBRARIES} ${MPFR_LIBRARIES} CGAL CGAL_ImageIO) -add_executable(map3_from_image ${HEADER_FILES} ${SOURCE_FILES}) -target_link_libraries(map3_from_image cgogn_core cgogn_io_mesh_generation ${Boost_LIBRARIES} ${GMP_LIBRARIES} ${MPFR_LIBRARIES} CGAL CGAL_ImageIO) + +endif() + +add_executable(map3_from_surface map3_from_surface.cpp) +target_link_libraries(map3_from_surface cgogn_core cgogn_io cgogn_io_mesh_generation tet CGAL gmp) diff --git a/cgogn/io/mesh_generation/examples/map3_from_surface.cpp b/cgogn/io/mesh_generation/examples/map3_from_surface.cpp new file mode 100644 index 00000000..f473dda6 --- /dev/null +++ b/cgogn/io/mesh_generation/examples/map3_from_surface.cpp @@ -0,0 +1,125 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#include +#include + +#include +#include +#include + +using MapTraits = cgogn::DefaultMapTraits; +using Map3 = cgogn::CMap3; +using Map2 = cgogn::CMap2; +using Vec3 = Eigen::Vector3d; + + +int main(int argc, char** argv) +{ + std::string surface_path; + std::string tetgen_arg; + if (argc < 3) + { + std::cout << "argc < 3" << std::endl; + std::exit(EXIT_FAILURE); + } + else + { + surface_path = std::string(argv[1]); + tetgen_arg = std::string(argv[2]); + } + + Map2 map2; + std::unique_ptr tetgen_input; + { + cgogn::io::import_surface(map2, surface_path); + Map2::VertexAttributeHandler vertex_position = map2.get_attribute("position"); + tetgen_input = cgogn::io::export_tetgen(map2, vertex_position); + } + + Map3 map3; + { + tetgenio tetgen_output; + char *arg = new char[tetgen_arg.length() + 1]; + strcpy(arg, tetgen_arg.c_str()); + tetrahedralize(arg, tetgen_input.get(), &tetgen_output) ; + cgogn::io::TetgenVolumeImport tetgen_import(&tetgen_output); + tetgen_import.import_file(""); + tetgen_import.create_map(map3); + delete[] arg; + } + + + std::chrono::time_point start, end; + start = std::chrono::system_clock::now(); + + Map3::VertexAttributeHandler vertex_position = map3.get_attribute("position"); + + map3.enable_topo_cache(); + map3.enable_topo_cache(); + map3.enable_topo_cache(); + map3.enable_topo_cache(); + + unsigned int nbw = 0u; + map3.foreach_cell([&nbw] (Map3::Volume) + { + ++nbw; + }); + + unsigned int nbf = 0u; + map3.foreach_cell([&] (Map3::Face f) + { + ++nbf; + Vec3 v1 = vertex_position[Map3::Vertex(map3.phi1(f.dart))] - vertex_position[Map3::Vertex(f.dart)]; + Vec3 v2 = vertex_position[Map3::Vertex(map3.phi_1(f.dart))] - vertex_position[Map3::Vertex(f.dart)]; + }); + + unsigned int nbv = 0; + map3.foreach_cell([&] (Map3::Vertex v) + { + ++nbv; + unsigned int nb_incident = 0; + map3.foreach_incident_face(v, [&] (Map3::Face /*f*/) + { + ++nb_incident; + }); + }); + + unsigned int nbe = 0; + map3.foreach_cell([&nbe] (Map3::Edge) + { + ++nbe; + }); + + std::cout << "nb vertices -> " << nbv << std::endl; + std::cout << "nb edges -> " << nbe << std::endl; + std::cout << "nb faces -> " << nbf << std::endl; + std::cout << "nb volumes -> " << nbw << std::endl; + + end = std::chrono::system_clock::now(); + std::chrono::duration elapsed_seconds = end - start; + std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n"; + + + return 0; +} diff --git a/cgogn/io/mesh_generation/tetgen_io.cpp b/cgogn/io/mesh_generation/tetgen_io.cpp new file mode 100644 index 00000000..c7ae8293 --- /dev/null +++ b/cgogn/io/mesh_generation/tetgen_io.cpp @@ -0,0 +1,38 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#define CGOGN_IO_DLL_EXPORT +#define IO_TETGEN_IO_CPP + +#include + +namespace cgogn +{ + +namespace io +{ + +template class CGOGN_IO_API TetgenVolumeImport; + +} // namespace io +} // namespace cgogn diff --git a/cgogn/io/mesh_generation/tetgen_io.h b/cgogn/io/mesh_generation/tetgen_io.h new file mode 100644 index 00000000..de7d54ef --- /dev/null +++ b/cgogn/io/mesh_generation/tetgen_io.h @@ -0,0 +1,420 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef IO_TETGEN_IO_H +#define IO_TETGEN_IO_H + +#include +#include +#include + +#include +//template +//bool tetrahedralize(const typename PFP::MAP2& map2, const VertexAttribute position2, +// typename PFP::MAP3& map3, VertexAttribute position3, +// bool add_steiner_points_on_exterior_boundary, bool add_steiner_points_on_interior_boundary, double max_volume, double max_shape) +//{ +// // +// // 1. map to tetgen +// // + +// tetgenio surface; + +// // memory initialization +// surface.initialize(); + +// // 0-based indexing +// surface.firstnumber = 0; + +// // input vertices +// surface.numberofpoints = map2.nbOrbits(); +// surface.pointlist = new REAL[surface.numberofpoints * 3]; + +// //for each vertex +// unsigned int i = 0; +// TraversorV tv(map2); +// for(Dart it = tv.begin() ; it != tv.end() ; it = tv.next()) +// { +// surface.pointlist[i] = position2[it][0] ; i++ ; //x +// surface.pointlist[i] = position2[it][1] ; i++ ; //y +// surface.pointlist[i] = position2[it][2] ; i++ ; //z +// } + +// tetgenio::facet* f ; +// tetgenio::polygon* p ; +// surface.numberoffacets = map2.nbOrbits(); +// surface.facetlist = new tetgenio::facet[surface.numberoffacets] ; + + +// //for each facet +// i = 0; +// TraversorF tf(map2); +// for(Dart it = tf.begin() ; it != tf.end() ; it = tf.next()) +// { +// f = &(surface.facetlist[i]) ; +// f->numberofpolygons = 1 ; +// f->polygonlist = new tetgenio::polygon[f->numberofpolygons] ; +// p = f->polygonlist ; +// p->numberofvertices = map2.faceDegree(it); +// p->vertexlist = new int[p->numberofvertices] ; + +// unsigned int j = 0; +// Dart dit = it; +// do +// { +// p->vertexlist[j] = map2.getEmbedding(dit); +// dit = map.phi1(dit); +// j++; +// }while(dit != it); + +// f->numberofholes = 0 ; +// f->holelist = nil ; +// i++ ; +// } + +// // +// // 2. tetgen argument list +// // +// std::ostringstream s ; + +// // Q: Quiet: No terminal output except errors +// // p: PLC : input data is surfacic +// // n: output tet neighbors + +// // q: desired quality +// if(max_volume > 0 && max_shape > 0.0) +// { +// s << "Qpna" << max_volume << "q"<< max_shape; +// } +// else if(max_volume > 0.0) +// { +// s << "Qpna" << max_volume ; +// } +// else if(max_shape > 0.0) +// { +// s << "Qpnq" << max_shape ; +// } +// else +// { +// s << "Qpn"; +// } + +// // YY: prohibit steiner points on boundaries +// // (first Y for exterior boundary, second Y for the +// // other ones). + +// if( add_steiner_points_on_exterior_boundary && !add_steiner_points_on_interior_boundary) +// { +// //Invalid combination of flags (do not preserve exterior boundary and preserve interior ones) - preserving exterior boundary as well +// add_steiner_points_on_exterior_boundary = false ; +// } + +// if(!add_steiner_points_on_exterior_boundary) +// { +// s << "Y" ; +// } + +// if(!add_steiner_points_on_interior_boundary) +// { +// s << "Y" ; +// } +// std::string params = s.str() ; + +// // +// // 3. tetrahedralization +// // +// tetgenio volume; +// ::tetrahedralize(params.c_str(), &surface, &volume) ; + + +// // +// // 4. tetgen to map +// // + +// //create vertices +// double* p = volume_->pointlist ; +// std::vector verticesID; +// verticesID.reserve(volume_->numberofpoints); +// AttributeContainer& container = map3.template getAttributeContainer() ; + +// for(unsigned int i = 0; i < volume_->numberofpoints; i++) +// { +// typename PFP::VEC3 pos(p[0], p[1], p[2]); +// unsigned int id = container.insertLine(); + +// position3[id] = pos; +// verticesID.push_back(id); + +// p += 3 ; +// } + +// //create tetrahedrons +// int* t = volume_->tetrahedronlist ; +// for(unsigned int i = 0; i < volume_->numberoftetrahedra; i++) +// { +// Dart d = Algo::Surface::Modelisation::createTetrahedron(map3, false); + +// for(unsigned int j = 0; j < 3; j++) +// { +// FunctorSetEmb fsetemb(map, verticesID[t[j] - volume_->firstnumber]); +// map.template foreach_dart_of_orbit(d, fsetemb); + +//// //store darts per vertices to optimize reconstruction +//// Dart dd = d; +//// do +//// { +//// m.mark(dd) ; +//// vecDartsPerVertex[pt[2-j]].push_back(dd); +//// dd = map.phi1(map.phi2(dd)); +//// } while(dd != d); + +// d = map.phi1(d); + +// set_cell_vertex(d, j, verticesID[t[j] - volume_->firstnumber]) ; +// } + +// t += 4 ; +// } + +// //create adjacency +// int* pn = volume_->neighborlist ; +// for(unsigned int i = 0; i < volume_->numberoftetrahedra; i++) +// { +// for(int j=0; j<4; j++) +// { +// int adjacent = pn[j] ; + +// if(adjacent >= 0) +// { +// set_cell_adjacent( cells[i], j, cells[adjacent - volume_->firstnumber] +// ) ; +// } +// } +// pn += 4 ; +// } +//} +namespace cgogn +{ + +namespace io +{ + + +// // +// // 2. tetgen argument list +// // +// std::ostringstream s ; + +// // Q: Quiet: No terminal output except errors +// // p: PLC : input data is surfacic +// // n: output tet neighbors + +// // q: desired quality +// if(max_volume > 0 && max_shape > 0.0) +// { +// s << "Qpna" << max_volume << "q"<< max_shape; +// } +// else if(max_volume > 0.0) +// { +// s << "Qpna" << max_volume ; +// } +// else if(max_shape > 0.0) +// { +// s << "Qpnq" << max_shape ; +// } +// else +// { +// s << "Qpn"; +// } + +// // YY: prohibit steiner points on boundaries +// // (first Y for exterior boundary, second Y for the +// // other ones). + +// if( add_steiner_points_on_exterior_boundary && !add_steiner_points_on_interior_boundary) +// { +// //Invalid combination of flags (do not preserve exterior boundary and preserve interior ones) - preserving exterior boundary as well +// add_steiner_points_on_exterior_boundary = false ; +// } + +// if(!add_steiner_points_on_exterior_boundary) +// { +// s << "Y" ; +// } + +// if(!add_steiner_points_on_interior_boundary) +// { +// s << "Y" ; +// } + +// // +// // 3. tetrahedralization +// // +// tetgenio volume; +// ::tetrahedralize(s.str().c_str(), &output, &volume) ; + + +template +class TetgenVolumeImport : public VolumeImport +{ +public: + using Inherit = VolumeImport; + using Self = TetgenVolumeImport; + + using Scalar = typename geometry::vector_traits::Scalar; + template + using ChunkArray = typename Inherit::template ChunkArray; + + TetgenVolumeImport() = delete; + TetgenVolumeImport(const Self&) = delete; + TetgenVolumeImport(Self&&) = delete; + Self& operator=(const Self&) = delete; + Self& operator=(Self&&) = delete; + + explicit inline TetgenVolumeImport(tetgenio * tetgen_output) + { + volume_ = tetgen_output; + } + +protected: + virtual bool import_file_impl(const std::string& /*filename*/) override + { + + this->nb_vertices_ = volume_->numberofpoints; + this->nb_volumes_ = volume_->numberoftetrahedra; + this->volumes_nb_vertices_.reserve(this->nb_volumes_); + this->volumes_vertex_indices_.reserve(4u*this->nb_volumes_); + + if (this->nb_vertices_ == 0u || this->nb_volumes_ == 0u) + { + this->clear(); + return false; + } + + ChunkArray* position = this->vertex_attributes_.template add_attribute("position"); + + //create vertices + std::vector vertices_indices; + double* p = volume_->pointlist ; + vertices_indices.reserve(this->nb_vertices_); + + for(unsigned int i = 0u; i < this->nb_vertices_; ++i) + { + const unsigned id = this->vertex_attributes_.template insert_lines<1>(); + position->operator [](id) = VEC3(Scalar(p[0]), Scalar(p[1]), Scalar(p[2])); + vertices_indices.push_back(id); + p += 3 ; + } + + //create tetrahedrons + int* t = volume_->tetrahedronlist ; + for(unsigned int i = 0u; i < this->nb_volumes_; ++i) + { + this->volumes_nb_vertices_.push_back(4u); + for(unsigned int j = 0u; j < 3u; j++) + this->volumes_vertex_indices_.push_back(vertices_indices[t[j] - volume_->firstnumber]); + + t += 4 ; + } + + return true; + } +private: + tetgenio* volume_; +}; + +template +std::unique_ptr export_tetgen(CMap2& map, const typename CMap2::template VertexAttributeHandler& pos) +{ + using Map = CMap2; + using Vertex = typename Map::Vertex; + using Face = typename Map::Face; + + using TetgenReal = REAL; + std::unique_ptr output = make_unique(); + + // memory initialization + output->initialize(); + + // 0-based indexing + output->firstnumber = 0; + + // input vertices + output->numberofpoints = map.template nb_cells(); + output->pointlist = new TetgenReal[output->numberofpoints * 3]; + + //for each vertex + unsigned int i = 0u; + map.foreach_cell([&output,&i,&pos](Vertex v) + { + const VEC3& vec = pos[v]; + output->pointlist[i++] = vec[0]; + output->pointlist[i++] = vec[1]; + output->pointlist[i++] = vec[2]; + }, [](Dart) {return true;}); + + + tetgenio::facet* f ; + tetgenio::polygon* p ; + + output->numberoffacets = map.template nb_cells(); + output->facetlist = new tetgenio::facet[output->numberoffacets] ; + + + //for each facet + i = 0u; + map.foreach_cell([&f,&output,&p,&i,&map](Face face) + { + f = &(output->facetlist[i]); + f->numberofpolygons = 1; + f->polygonlist = new tetgenio::polygon[f->numberofpolygons]; + p = f->polygonlist; + p->numberofvertices = map.degree(face); + p->vertexlist = new int[p->numberofvertices]; + + unsigned int j = 0u; + Dart dit = face; + do + { + p->vertexlist[j] = map.get_embedding(Vertex(dit)); + dit = map.phi1(dit); + ++j; + }while(dit != face.dart); + + f->numberofholes = 0; + f->holelist = nullptr; + ++i; + }, [](Dart) {return true;}); + + + return output; +} + +#if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_TETGEN_IO_CPP)) +extern template class CGOGN_IO_API TetgenVolumeImport; +#endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(IO_TETGEN_IO_CPP)) + +} // namespace io +} // namespace cgogn + +#endif // IO_TETGEN_IO_H diff --git a/data/meshes/pyramid.vtk b/data/meshes/pyramid.vtk new file mode 100644 index 0000000000000000000000000000000000000000..61fb76708d64f60be76c8a9b0aeb8936216b41b2 GIT binary patch literal 249 zcmY#ZC@aZUa7iplbj!?1RR~KhD$dN$Q!vpp-~vhHmzETimT)1n97qjJ4kQNSgTz35kU20mh-Tsf00|f&Q2+n{ literal 0 HcmV?d00001 From 1ab16e374fa193b89f9a3f790d5ded519f374d11 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Thu, 17 Mar 2016 18:21:25 +0100 Subject: [PATCH 354/402] added tetgen Signed-off-by: Etienne Schmitt --- thirdparty/CMakeLists.txt | 1 + thirdparty/tetgen/CMakeLists.txt | 15 + thirdparty/tetgen/LICENSE | 666 + thirdparty/tetgen/README | 25 + thirdparty/tetgen/example.poly | 84 + thirdparty/tetgen/predicates.cxx | 4706 +++++ thirdparty/tetgen/tetgen.cxx | 31244 +++++++++++++++++++++++++++++ thirdparty/tetgen/tetgen.h | 3334 +++ 8 files changed, 40075 insertions(+) create mode 100644 thirdparty/tetgen/CMakeLists.txt create mode 100644 thirdparty/tetgen/LICENSE create mode 100644 thirdparty/tetgen/README create mode 100644 thirdparty/tetgen/example.poly create mode 100644 thirdparty/tetgen/predicates.cxx create mode 100644 thirdparty/tetgen/tetgen.cxx create mode 100644 thirdparty/tetgen/tetgen.h diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index c1ba8283..8a404c95 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -21,3 +21,4 @@ endif(CGOGN_BUILD_BENCHS) add_subdirectory(ply) add_subdirectory(OffBinConverter) add_subdirectory(lm6) +add_subdirectory(tetgen) diff --git a/thirdparty/tetgen/CMakeLists.txt b/thirdparty/tetgen/CMakeLists.txt new file mode 100644 index 00000000..a805e504 --- /dev/null +++ b/thirdparty/tetgen/CMakeLists.txt @@ -0,0 +1,15 @@ +set(CGOGN_THIRDPARTY_TETGEN_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE PATH "Tetgen include directory.") +# Set the minimum required version of cmake for a project. +cmake_minimum_required(VERSION 3.0) + +# Add an executable to the project using the specified source files. +# add_executable(tetgen tetgen.cxx predicates.cxx) + +#Add a library to the project using the specified source files. +# In Linux/Unix, it will creates the libtet.a +add_library(tet SHARED tetgen.cxx predicates.cxx) + +#Set properties on a target. +#We use this here to set -DTETLIBRARY for when compiling the +#library +set_target_properties(tet PROPERTIES "COMPILE_DEFINITIONS" TETLIBRARY) diff --git a/thirdparty/tetgen/LICENSE b/thirdparty/tetgen/LICENSE new file mode 100644 index 00000000..e253c3d9 --- /dev/null +++ b/thirdparty/tetgen/LICENSE @@ -0,0 +1,666 @@ +TetGen License +-------------- + +TetGen is distributed under a dual licensing scheme. You can +redistribute it and/or modify it under the terms of the GNU Affero +General Public License as published by the Free Software Foundation, +either version 3 of the License, or (at your option) any later +version. A copy of the GNU Affero General Public License is reproduced +below. + +If the terms and conditions of the AGPL v.3. would prevent you from +using TetGen, please consider the option to obtain a commercial +license for a fee. These licenses are offered by the Weierstrass +Institute for Applied Analysis and Stochastics (WIAS). As a rule, +licenses are provided "as-is", unlimited in time for a one time +fee. Please send corresponding requests to: +tetgen@wias-berlin.de. Please do not forget to include some +description of your company and the realm of its activities. + +===================================================================== +GNU AFFERO GENERAL PUBLIC LICENSE + +Version 3, 19 November 2007 + +Copyright © 2007 Free Software Foundation, Inc. +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + +Preamble + +The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + +The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains +free software for all its users. + +When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + +Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + +A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come +about. The GNU General Public License permits making a modified +version and letting the public access it on a server without ever +releasing its source code to the public. + +The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + +An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing +under this license. + +The precise terms and conditions for copying, distribution and +modification follow. + +TERMS AND CONDITIONS + +0. Definitions. + +"This License" refers to version 3 of the GNU Affero General Public +License. + +"Copyright" also means copyright-like laws that apply to other kinds +of works, such as semiconductor masks. + +"The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + +To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of +an exact copy. The resulting work is called a "modified version" of +the earlier work or a work "based on" the earlier work. + +A "covered work" means either the unmodified Program or a work based +on the Program. + +To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + +To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user +through a computer network, with no transfer of a copy, is not +conveying. + +An interactive user interface displays "Appropriate Legal Notices" to +the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + +1. Source Code. + +The "source code" for a work means the preferred form of the work for +making modifications to it. "Object code" means any non-source form of +a work. + +A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + +The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + +The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + +The Corresponding Source need not include anything that users can +regenerate automatically from other parts of the Corresponding Source. + +The Corresponding Source for a work in source code form is that same +work. + +2. Basic Permissions. + +All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + +You may make, run and propagate covered works that you do not convey, +without conditions so long as your license otherwise remains in +force. You may convey covered works to others for the sole purpose of +having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under the +conditions stated below. Sublicensing is not allowed; section 10 makes +it unnecessary. + +3. Protecting Users' Legal Rights From Anti-Circumvention Law. + +No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + +When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such +circumvention is effected by exercising rights under this License with +respect to the covered work, and you disclaim any intention to limit +operation or modification of the work as a means of enforcing, against +the work's users, your or third parties' legal rights to forbid +circumvention of technological measures. + +4. Conveying Verbatim Copies. + +You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + +5. Conveying Modified Source Versions. + +You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these +conditions: + +a) The work must carry prominent notices stating that you modified it, +and giving a relevant date. b) The work must carry prominent notices +stating that it is released under this License and any conditions +added under section 7. This requirement modifies the requirement in +section 4 to "keep intact all notices". c) You must license the +entire work, as a whole, under this License to anyone who comes into +possession of a copy. This License will therefore apply, along with +any applicable section 7 additional terms, to the whole of the work, +and all its parts, regardless of how they are packaged. This License +gives no permission to license the work in any other way, but it does +not invalidate such permission if you have separately received it. d) +If the work has interactive user interfaces, each must display +Appropriate Legal Notices; however, if the Program has interactive +interfaces that do not display Appropriate Legal Notices, your work +need not make them do so. A compilation of a covered work with other +separate and independent works, which are not by their nature +extensions of the covered work, and which are not combined with it +such as to form a larger program, in or on a volume of a storage or +distribution medium, is called an "aggregate" if the compilation and +its resulting copyright are not used to limit the access or legal +rights of the compilation's users beyond what the individual works +permit. Inclusion of a covered work in an aggregate does not cause +this License to apply to the other parts of the aggregate. + +6. Conveying Non-Source Forms. + +You may convey a covered work in object code form under the terms of +sections 4 and 5, provided that you also convey the machine-readable +Corresponding Source under the terms of this License, in one of these +ways: + +a) Convey the object code in, or embodied in, a physical product +(including a physical distribution medium), accompanied by the +Corresponding Source fixed on a durable physical medium customarily +used for software interchange. b) Convey the object code in, or +embodied in, a physical product (including a physical distribution +medium), accompanied by a written offer, valid for at least three +years and valid for as long as you offer spare parts or customer +support for that product model, to give anyone who possesses the +object code either (1) a copy of the Corresponding Source for all the +software in the product that is covered by this License, on a durable +physical medium customarily used for software interchange, for a price +no more than your reasonable cost of physically performing this +conveying of source, or (2) access to copy the Corresponding Source +from a network server at no charge. c) Convey individual copies of +the object code with a copy of the written offer to provide the +Corresponding Source. This alternative is allowed only occasionally +and noncommercially, and only if you received the object code with +such an offer, in accord with subsection 6b. d) Convey the object +code by offering access from a designated place (gratis or for a +charge), and offer equivalent access to the Corresponding Source in +the same way through the same place at no further charge. You need not +require recipients to copy the Corresponding Source along with the +object code. If the place to copy the object code is a network server, +the Corresponding Source may be on a different server (operated by you +or a third party) that supports equivalent copying facilities, +provided you maintain clear directions next to the object code saying +where to find the Corresponding Source. Regardless of what server +hosts the Corresponding Source, you remain obligated to ensure that it +is available for as long as needed to satisfy these requirements. e) +Convey the object code using peer-to-peer transmission, provided you +inform other peers where the object code and Corresponding Source of +the work are being offered to the general public at no charge under +subsection 6d. A separable portion of the object code, whose source +code is excluded from the Corresponding Source as a System Library, +need not be included in conveying the object code work. + +A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, +family, or household purposes, or (2) anything designed or sold for +incorporation into a dwelling. In determining whether a product is a +consumer product, doubtful cases shall be resolved in favor of +coverage. For a particular product received by a particular user, +"normally used" refers to a typical or common use of that class of +product, regardless of the status of the particular user or of the way +in which the particular user actually uses, or expects or is expected +to use, the product. A product is a consumer product regardless of +whether the product has substantial commercial, industrial or +non-consumer uses, unless such uses represent the only significant +mode of use of the product. + +"Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to +install and execute modified versions of a covered work in that User +Product from a modified version of its Corresponding Source. The +information must suffice to ensure that the continued functioning of +the modified object code is in no case prevented or interfered with +solely because modification has been made. + +If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + +The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or +updates for a work that has been modified or installed by the +recipient, or for the User Product in which it has been modified or +installed. Access to a network may be denied when the modification +itself materially and adversely affects the operation of the network +or violates the rules and protocols for communication across the +network. + +Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + +7. Additional Terms. + +"Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its +conditions. Additional permissions that are applicable to the entire +Program shall be treated as though they were included in this License, +to the extent that they are valid under applicable law. If additional +permissions apply only to part of the Program, that part may be used +separately under those permissions, but the entire Program remains +governed by this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + +Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders +of that material) supplement the terms of this License with terms: + +a) Disclaiming warranty or limiting liability differently from the +terms of sections 15 and 16 of this License; or b) Requiring +preservation of specified reasonable legal notices or author +attributions in that material or in the Appropriate Legal Notices +displayed by works containing it; or c) Prohibiting misrepresentation +of the origin of that material, or requiring that modified versions of +such material be marked in reasonable ways as different from the +original version; or d) Limiting the use for publicity purposes of +names of licensors or authors of the material; or e) Declining to +grant rights under trademark law for use of some trade names, +trademarks, or service marks; or f) Requiring indemnification of +licensors and authors of that material by anyone who conveys the +material (or modified versions of it) with contractual assumptions of +liability to the recipient, for any liability that these contractual +assumptions directly impose on those licensors and authors. All other +non-permissive additional terms are considered "further restrictions" +within the meaning of section 10. If the Program as you received it, +or any part of it, contains a notice stating that it is governed by +this License along with a term that is a further restriction, you may +remove that term. If a license document contains a further restriction +but permits relicensing or conveying under this License, you may add +to a covered work material governed by the terms of that license +document, provided that the further restriction does not survive such +relicensing or conveying. + +If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; the +above requirements apply either way. + +8. Termination. + +You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + +However, if you cease all violation of this License, then your license +from a particular copyright holder is reinstated (a) provisionally, +unless and until the copyright holder explicitly and finally +terminates your license, and (b) permanently, if the copyright holder +fails to notify you of the violation by some reasonable means prior to +60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + +9. Acceptance Not Required for Having Copies. + +You are not required to accept this License in order to receive or run +a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + +10. Automatic Licensing of Downstream Recipients. + +Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + +An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + +11. Patents. + +A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + +A contributor's "essential patent claims" are all patent claims owned +or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + +In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + +If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + +A patent license is "discriminatory" if it does not include within the +scope of its coverage, prohibits the exercise of, or is conditioned on +the non-exercise of one or more of the rights that are specifically +granted under this License. You may not convey a covered work if you +are a party to an arrangement with a third party that is in the +business of distributing software, under which you make payment to the +third party based on the extent of your activity of conveying the +work, and under which the third party grants, to any of the parties +who would receive the covered work from you, a discriminatory patent +license (a) in connection with copies of the covered work conveyed by +you (or copies made from those copies), or (b) primarily for and in +connection with specific products or compilations that contain the +covered work, unless you entered into that arrangement, or that patent +license was granted, prior to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + +12. No Surrender of Others' Freedom. + +If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under +this License and any other pertinent obligations, then as a +consequence you may not convey it at all. For example, if you agree to +terms that obligate you to collect a royalty for further conveying +from those to whom you convey the Program, the only way you could +satisfy both those terms and this License would be to refrain entirely +from conveying the Program. + +13. Remote Network Interaction; Use with the GNU General Public +License. + +Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your +version supports such interaction) an opportunity to receive the +Corresponding Source of your version by providing access to the +Corresponding Source from a network server at no charge, through some +standard or customary means of facilitating copying of software. This +Corresponding Source shall include the Corresponding Source for any +work covered by version 3 of the GNU General Public License that is +incorporated pursuant to the following paragraph. + +Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + +14. Revised Versions of this License. + +The Free Software Foundation may publish revised and/or new versions +of the GNU Affero General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever +published by the Free Software Foundation. + +If the Program specifies that a proxy can decide which future versions +of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + +Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + +15. Disclaimer of Warranty. + +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT +WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND +PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE +DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR +CORRECTION. + +16. Limitation of Liability. + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR +CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT +NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR +LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM +TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER +PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +17. Interpretation of Sections 15 and 16. + +If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + +To do so, attach the following notices to the program. It is safest to +attach them to the start of each source file to most effectively state +the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + Copyright (C) + + This program is free software: you can redistribute it and/or + modify it under the terms of the GNU Affero General Public License + as published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public + License along with this program. If not, see + . Also add information on how to + contact you by electronic and paper mail. + +If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for +the specific requirements. + +You should also get your employer (if you work as a programmer) or +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. For more information on this, and how to apply and follow +the GNU AGPL, see . \ No newline at end of file diff --git a/thirdparty/tetgen/README b/thirdparty/tetgen/README new file mode 100644 index 00000000..bc5cfa04 --- /dev/null +++ b/thirdparty/tetgen/README @@ -0,0 +1,25 @@ +This is TetGen version 1.5 (released on November 4, 2013) + +Please see the documentation of TetGen for compiling and using TetGen. +It is available at the following link: + + http://www.tetgen.org + +For more information on this product, contact : + + Hang Si + Research Group of Numerical Mathematics and Scientific Computing + Weierstrass Institute for Applied Analysis and Stochastics + Mohrenstr. 39 + 10117 Berlin, Germany + + Phone: +49 (0) 30-20372-446 Fax: +49 (0) 30-2044975 + EMail: + Web Site: http://www.wias-berlin.de/~si + +------------------- IMPORTANCE NOTICE ----------------------------- + +BEFORE INTALLING OR USING TetGen(R) READ the +GENERAL LICENSE TERMS AND CONDITIONS + +------------------------------------------------------------------- \ No newline at end of file diff --git a/thirdparty/tetgen/example.poly b/thirdparty/tetgen/example.poly new file mode 100644 index 00000000..e9249566 --- /dev/null +++ b/thirdparty/tetgen/example.poly @@ -0,0 +1,84 @@ +28 3 0 1 +1 0 0 0 1 +2 2 0 0 1 +3 2 2 0 1 +4 0 2 0 1 +5 0 0 4 9 +6 2 0 4 9 +7 2 2 3 9 +8 0 2 3 9 +9 0 0 5 2 +10 2 0 5 2 +11 2 2 5 2 +12 0 2 5 2 +13 0.25 0.25 0.5 4 +14 1.75 0.25 0.5 4 +15 1.75 1.5 0.5 4 +16 0.25 1.5 0.5 4 +17 0.25 0.25 1 4 +18 1.75 0.25 1 4 +19 1.75 1.5 1 4 +20 0.25 1.5 1 4 +21 0.25 0 2 4 +22 1.75 0 2 4 +23 1.75 1.5 2 4 +24 0.25 1.5 2 4 +25 0.25 0 2.5 4 +26 1.75 0 2.5 4 +27 1.75 1.5 2.5 4 +28 0.25 1.5 2.5 4 +23 1 +1 0 1 # 1 +4 1 2 3 4 +1 0 9 # 2 +4 5 6 7 8 +2 1 3 # 3 +4 1 2 6 5 +4 21 22 26 25 +1 1 0 2.25 +1 0 3 # 4 +4 2 3 7 6 +1 0 3 # 5 +4 3 4 8 7 +1 0 3 # 6 +4 4 1 5 8 +1 0 2 # 7 +4 9 10 11 12 +1 0 3 # 8 +4 9 10 6 5 +1 0 3 # 9 +4 10 11 7 6 +1 0 3 # 10 +4 11 12 8 7 +1 0 3 # 11 +4 12 9 5 8 +1 0 4 # 12 +4 13 14 15 16 +1 0 4 # 13 +4 17 18 19 20 +1 0 4 # 14 +4 13 14 18 17 +1 0 4 # 15 +4 14 15 19 18 +1 0 4 # 16 +4 15 16 20 19 +1 0 4 # 17 +4 16 13 17 20 +1 0 4 # 18 +4 21 22 23 24 +1 0 4 # 19 +4 25 26 27 28 +1 0 4 # 20 +4 21 22 26 25 +1 0 4 # 21 +4 22 23 27 26 +1 0 4 # 22 +4 23 24 28 27 +1 0 4 # 23 +4 24 21 25 28 +2 +1 1 0.4 2.25 +2 1 0.4 0.75 +2 +1 1 0.25 0.1 10 0.001 +2 1 0.5 4 20 0.01 diff --git a/thirdparty/tetgen/predicates.cxx b/thirdparty/tetgen/predicates.cxx new file mode 100644 index 00000000..33817d79 --- /dev/null +++ b/thirdparty/tetgen/predicates.cxx @@ -0,0 +1,4706 @@ +/*****************************************************************************/ +/* */ +/* Routines for Arbitrary Precision Floating-point Arithmetic */ +/* and Fast Robust Geometric Predicates */ +/* (predicates.c) */ +/* */ +/* May 18, 1996 */ +/* */ +/* Placed in the public domain by */ +/* Jonathan Richard Shewchuk */ +/* School of Computer Science */ +/* Carnegie Mellon University */ +/* 5000 Forbes Avenue */ +/* Pittsburgh, Pennsylvania 15213-3891 */ +/* jrs@cs.cmu.edu */ +/* */ +/* This file contains C implementation of algorithms for exact addition */ +/* and multiplication of floating-point numbers, and predicates for */ +/* robustly performing the orientation and incircle tests used in */ +/* computational geometry. The algorithms and underlying theory are */ +/* described in Jonathan Richard Shewchuk. "Adaptive Precision Floating- */ +/* Point Arithmetic and Fast Robust Geometric Predicates." Technical */ +/* Report CMU-CS-96-140, School of Computer Science, Carnegie Mellon */ +/* University, Pittsburgh, Pennsylvania, May 1996. (Submitted to */ +/* Discrete & Computational Geometry.) */ +/* */ +/* This file, the paper listed above, and other information are available */ +/* from the Web page http://www.cs.cmu.edu/~quake/robust.html . */ +/* */ +/*****************************************************************************/ + +/*****************************************************************************/ +/* */ +/* Using this code: */ +/* */ +/* First, read the short or long version of the paper (from the Web page */ +/* above). */ +/* */ +/* Be sure to call exactinit() once, before calling any of the arithmetic */ +/* functions or geometric predicates. Also be sure to turn on the */ +/* optimizer when compiling this file. */ +/* */ +/* */ +/* Several geometric predicates are defined. Their parameters are all */ +/* points. Each point is an array of two or three floating-point */ +/* numbers. The geometric predicates, described in the papers, are */ +/* */ +/* orient2d(pa, pb, pc) */ +/* orient2dfast(pa, pb, pc) */ +/* orient3d(pa, pb, pc, pd) */ +/* orient3dfast(pa, pb, pc, pd) */ +/* incircle(pa, pb, pc, pd) */ +/* incirclefast(pa, pb, pc, pd) */ +/* insphere(pa, pb, pc, pd, pe) */ +/* inspherefast(pa, pb, pc, pd, pe) */ +/* */ +/* Those with suffix "fast" are approximate, non-robust versions. Those */ +/* without the suffix are adaptive precision, robust versions. There */ +/* are also versions with the suffices "exact" and "slow", which are */ +/* non-adaptive, exact arithmetic versions, which I use only for timings */ +/* in my arithmetic papers. */ +/* */ +/* */ +/* An expansion is represented by an array of floating-point numbers, */ +/* sorted from smallest to largest magnitude (possibly with interspersed */ +/* zeros). The length of each expansion is stored as a separate integer, */ +/* and each arithmetic function returns an integer which is the length */ +/* of the expansion it created. */ +/* */ +/* Several arithmetic functions are defined. Their parameters are */ +/* */ +/* e, f Input expansions */ +/* elen, flen Lengths of input expansions (must be >= 1) */ +/* h Output expansion */ +/* b Input scalar */ +/* */ +/* The arithmetic functions are */ +/* */ +/* grow_expansion(elen, e, b, h) */ +/* grow_expansion_zeroelim(elen, e, b, h) */ +/* expansion_sum(elen, e, flen, f, h) */ +/* expansion_sum_zeroelim1(elen, e, flen, f, h) */ +/* expansion_sum_zeroelim2(elen, e, flen, f, h) */ +/* fast_expansion_sum(elen, e, flen, f, h) */ +/* fast_expansion_sum_zeroelim(elen, e, flen, f, h) */ +/* linear_expansion_sum(elen, e, flen, f, h) */ +/* linear_expansion_sum_zeroelim(elen, e, flen, f, h) */ +/* scale_expansion(elen, e, b, h) */ +/* scale_expansion_zeroelim(elen, e, b, h) */ +/* compress(elen, e, h) */ +/* */ +/* All of these are described in the long version of the paper; some are */ +/* described in the short version. All return an integer that is the */ +/* length of h. Those with suffix _zeroelim perform zero elimination, */ +/* and are recommended over their counterparts. The procedure */ +/* fast_expansion_sum_zeroelim() (or linear_expansion_sum_zeroelim() on */ +/* processors that do not use the round-to-even tiebreaking rule) is */ +/* recommended over expansion_sum_zeroelim(). Each procedure has a */ +/* little note next to it (in the code below) that tells you whether or */ +/* not the output expansion may be the same array as one of the input */ +/* expansions. */ +/* */ +/* */ +/* If you look around below, you'll also find macros for a bunch of */ +/* simple unrolled arithmetic operations, and procedures for printing */ +/* expansions (commented out because they don't work with all C */ +/* compilers) and for generating random floating-point numbers whose */ +/* significand bits are all random. Most of the macros have undocumented */ +/* requirements that certain of their parameters should not be the same */ +/* variable; for safety, better to make sure all the parameters are */ +/* distinct variables. Feel free to send email to jrs@cs.cmu.edu if you */ +/* have questions. */ +/* */ +/*****************************************************************************/ + +#include +#include +#include +#ifdef CPU86 +#include +#endif /* CPU86 */ +#ifdef LINUX +#include +#endif /* LINUX */ + +#include "tetgen.h" // Defines the symbol REAL (float or double). + +#ifdef USE_CGAL_PREDICATES + #include + typedef CGAL::Exact_predicates_inexact_constructions_kernel cgalEpick; + typedef cgalEpick::Point_3 Point; + cgalEpick cgal_pred_obj; +#endif // #ifdef USE_CGAL_PREDICATES + +/* On some machines, the exact arithmetic routines might be defeated by the */ +/* use of internal extended precision floating-point registers. Sometimes */ +/* this problem can be fixed by defining certain values to be volatile, */ +/* thus forcing them to be stored to memory and rounded off. This isn't */ +/* a great solution, though, as it slows the arithmetic down. */ +/* */ +/* To try this out, write "#define INEXACT volatile" below. Normally, */ +/* however, INEXACT should be defined to be nothing. ("#define INEXACT".) */ + +#define INEXACT /* Nothing */ +/* #define INEXACT volatile */ + +/* #define REAL double */ /* float or double */ +#define REALPRINT doubleprint +#define REALRAND doublerand +#define NARROWRAND narrowdoublerand +#define UNIFORMRAND uniformdoublerand + +/* Which of the following two methods of finding the absolute values is */ +/* fastest is compiler-dependent. A few compilers can inline and optimize */ +/* the fabs() call; but most will incur the overhead of a function call, */ +/* which is disastrously slow. A faster way on IEEE machines might be to */ +/* mask the appropriate bit, but that's difficult to do in C. */ + +//#define Absolute(a) ((a) >= 0.0 ? (a) : -(a)) +#define Absolute(a) fabs(a) + +/* Many of the operations are broken up into two pieces, a main part that */ +/* performs an approximate operation, and a "tail" that computes the */ +/* roundoff error of that operation. */ +/* */ +/* The operations Fast_Two_Sum(), Fast_Two_Diff(), Two_Sum(), Two_Diff(), */ +/* Split(), and Two_Product() are all implemented as described in the */ +/* reference. Each of these macros requires certain variables to be */ +/* defined in the calling routine. The variables `bvirt', `c', `abig', */ +/* `_i', `_j', `_k', `_l', `_m', and `_n' are declared `INEXACT' because */ +/* they store the result of an operation that may incur roundoff error. */ +/* The input parameter `x' (or the highest numbered `x_' parameter) must */ +/* also be declared `INEXACT'. */ + +#define Fast_Two_Sum_Tail(a, b, x, y) \ + bvirt = x - a; \ + y = b - bvirt + +#define Fast_Two_Sum(a, b, x, y) \ + x = (REAL) (a + b); \ + Fast_Two_Sum_Tail(a, b, x, y) + +#define Fast_Two_Diff_Tail(a, b, x, y) \ + bvirt = a - x; \ + y = bvirt - b + +#define Fast_Two_Diff(a, b, x, y) \ + x = (REAL) (a - b); \ + Fast_Two_Diff_Tail(a, b, x, y) + +#define Two_Sum_Tail(a, b, x, y) \ + bvirt = (REAL) (x - a); \ + avirt = x - bvirt; \ + bround = b - bvirt; \ + around = a - avirt; \ + y = around + bround + +#define Two_Sum(a, b, x, y) \ + x = (REAL) (a + b); \ + Two_Sum_Tail(a, b, x, y) + +#define Two_Diff_Tail(a, b, x, y) \ + bvirt = (REAL) (a - x); \ + avirt = x + bvirt; \ + bround = bvirt - b; \ + around = a - avirt; \ + y = around + bround + +#define Two_Diff(a, b, x, y) \ + x = (REAL) (a - b); \ + Two_Diff_Tail(a, b, x, y) + +#define Split(a, ahi, alo) \ + c = (REAL) (splitter * a); \ + abig = (REAL) (c - a); \ + ahi = c - abig; \ + alo = a - ahi + +#define Two_Product_Tail(a, b, x, y) \ + Split(a, ahi, alo); \ + Split(b, bhi, blo); \ + err1 = x - (ahi * bhi); \ + err2 = err1 - (alo * bhi); \ + err3 = err2 - (ahi * blo); \ + y = (alo * blo) - err3 + +#define Two_Product(a, b, x, y) \ + x = (REAL) (a * b); \ + Two_Product_Tail(a, b, x, y) + +/* Two_Product_Presplit() is Two_Product() where one of the inputs has */ +/* already been split. Avoids redundant splitting. */ + +#define Two_Product_Presplit(a, b, bhi, blo, x, y) \ + x = (REAL) (a * b); \ + Split(a, ahi, alo); \ + err1 = x - (ahi * bhi); \ + err2 = err1 - (alo * bhi); \ + err3 = err2 - (ahi * blo); \ + y = (alo * blo) - err3 + +/* Two_Product_2Presplit() is Two_Product() where both of the inputs have */ +/* already been split. Avoids redundant splitting. */ + +#define Two_Product_2Presplit(a, ahi, alo, b, bhi, blo, x, y) \ + x = (REAL) (a * b); \ + err1 = x - (ahi * bhi); \ + err2 = err1 - (alo * bhi); \ + err3 = err2 - (ahi * blo); \ + y = (alo * blo) - err3 + +/* Square() can be done more quickly than Two_Product(). */ + +#define Square_Tail(a, x, y) \ + Split(a, ahi, alo); \ + err1 = x - (ahi * ahi); \ + err3 = err1 - ((ahi + ahi) * alo); \ + y = (alo * alo) - err3 + +#define Square(a, x, y) \ + x = (REAL) (a * a); \ + Square_Tail(a, x, y) + +/* Macros for summing expansions of various fixed lengths. These are all */ +/* unrolled versions of Expansion_Sum(). */ + +#define Two_One_Sum(a1, a0, b, x2, x1, x0) \ + Two_Sum(a0, b , _i, x0); \ + Two_Sum(a1, _i, x2, x1) + +#define Two_One_Diff(a1, a0, b, x2, x1, x0) \ + Two_Diff(a0, b , _i, x0); \ + Two_Sum( a1, _i, x2, x1) + +#define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0) \ + Two_One_Sum(a1, a0, b0, _j, _0, x0); \ + Two_One_Sum(_j, _0, b1, x3, x2, x1) + +#define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0) \ + Two_One_Diff(a1, a0, b0, _j, _0, x0); \ + Two_One_Diff(_j, _0, b1, x3, x2, x1) + +#define Four_One_Sum(a3, a2, a1, a0, b, x4, x3, x2, x1, x0) \ + Two_One_Sum(a1, a0, b , _j, x1, x0); \ + Two_One_Sum(a3, a2, _j, x4, x3, x2) + +#define Four_Two_Sum(a3, a2, a1, a0, b1, b0, x5, x4, x3, x2, x1, x0) \ + Four_One_Sum(a3, a2, a1, a0, b0, _k, _2, _1, _0, x0); \ + Four_One_Sum(_k, _2, _1, _0, b1, x5, x4, x3, x2, x1) + +#define Four_Four_Sum(a3, a2, a1, a0, b4, b3, b1, b0, x7, x6, x5, x4, x3, x2, \ + x1, x0) \ + Four_Two_Sum(a3, a2, a1, a0, b1, b0, _l, _2, _1, _0, x1, x0); \ + Four_Two_Sum(_l, _2, _1, _0, b4, b3, x7, x6, x5, x4, x3, x2) + +#define Eight_One_Sum(a7, a6, a5, a4, a3, a2, a1, a0, b, x8, x7, x6, x5, x4, \ + x3, x2, x1, x0) \ + Four_One_Sum(a3, a2, a1, a0, b , _j, x3, x2, x1, x0); \ + Four_One_Sum(a7, a6, a5, a4, _j, x8, x7, x6, x5, x4) + +#define Eight_Two_Sum(a7, a6, a5, a4, a3, a2, a1, a0, b1, b0, x9, x8, x7, \ + x6, x5, x4, x3, x2, x1, x0) \ + Eight_One_Sum(a7, a6, a5, a4, a3, a2, a1, a0, b0, _k, _6, _5, _4, _3, _2, \ + _1, _0, x0); \ + Eight_One_Sum(_k, _6, _5, _4, _3, _2, _1, _0, b1, x9, x8, x7, x6, x5, x4, \ + x3, x2, x1) + +#define Eight_Four_Sum(a7, a6, a5, a4, a3, a2, a1, a0, b4, b3, b1, b0, x11, \ + x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0) \ + Eight_Two_Sum(a7, a6, a5, a4, a3, a2, a1, a0, b1, b0, _l, _6, _5, _4, _3, \ + _2, _1, _0, x1, x0); \ + Eight_Two_Sum(_l, _6, _5, _4, _3, _2, _1, _0, b4, b3, x11, x10, x9, x8, \ + x7, x6, x5, x4, x3, x2) + +/* Macros for multiplying expansions of various fixed lengths. */ + +#define Two_One_Product(a1, a0, b, x3, x2, x1, x0) \ + Split(b, bhi, blo); \ + Two_Product_Presplit(a0, b, bhi, blo, _i, x0); \ + Two_Product_Presplit(a1, b, bhi, blo, _j, _0); \ + Two_Sum(_i, _0, _k, x1); \ + Fast_Two_Sum(_j, _k, x3, x2) + +#define Four_One_Product(a3, a2, a1, a0, b, x7, x6, x5, x4, x3, x2, x1, x0) \ + Split(b, bhi, blo); \ + Two_Product_Presplit(a0, b, bhi, blo, _i, x0); \ + Two_Product_Presplit(a1, b, bhi, blo, _j, _0); \ + Two_Sum(_i, _0, _k, x1); \ + Fast_Two_Sum(_j, _k, _i, x2); \ + Two_Product_Presplit(a2, b, bhi, blo, _j, _0); \ + Two_Sum(_i, _0, _k, x3); \ + Fast_Two_Sum(_j, _k, _i, x4); \ + Two_Product_Presplit(a3, b, bhi, blo, _j, _0); \ + Two_Sum(_i, _0, _k, x5); \ + Fast_Two_Sum(_j, _k, x7, x6) + +#define Two_Two_Product(a1, a0, b1, b0, x7, x6, x5, x4, x3, x2, x1, x0) \ + Split(a0, a0hi, a0lo); \ + Split(b0, bhi, blo); \ + Two_Product_2Presplit(a0, a0hi, a0lo, b0, bhi, blo, _i, x0); \ + Split(a1, a1hi, a1lo); \ + Two_Product_2Presplit(a1, a1hi, a1lo, b0, bhi, blo, _j, _0); \ + Two_Sum(_i, _0, _k, _1); \ + Fast_Two_Sum(_j, _k, _l, _2); \ + Split(b1, bhi, blo); \ + Two_Product_2Presplit(a0, a0hi, a0lo, b1, bhi, blo, _i, _0); \ + Two_Sum(_1, _0, _k, x1); \ + Two_Sum(_2, _k, _j, _1); \ + Two_Sum(_l, _j, _m, _2); \ + Two_Product_2Presplit(a1, a1hi, a1lo, b1, bhi, blo, _j, _0); \ + Two_Sum(_i, _0, _n, _0); \ + Two_Sum(_1, _0, _i, x2); \ + Two_Sum(_2, _i, _k, _1); \ + Two_Sum(_m, _k, _l, _2); \ + Two_Sum(_j, _n, _k, _0); \ + Two_Sum(_1, _0, _j, x3); \ + Two_Sum(_2, _j, _i, _1); \ + Two_Sum(_l, _i, _m, _2); \ + Two_Sum(_1, _k, _i, x4); \ + Two_Sum(_2, _i, _k, x5); \ + Two_Sum(_m, _k, x7, x6) + +/* An expansion of length two can be squared more quickly than finding the */ +/* product of two different expansions of length two, and the result is */ +/* guaranteed to have no more than six (rather than eight) components. */ + +#define Two_Square(a1, a0, x5, x4, x3, x2, x1, x0) \ + Square(a0, _j, x0); \ + _0 = a0 + a0; \ + Two_Product(a1, _0, _k, _1); \ + Two_One_Sum(_k, _1, _j, _l, _2, x1); \ + Square(a1, _j, _1); \ + Two_Two_Sum(_j, _1, _l, _2, x5, x4, x3, x2) + +/* splitter = 2^ceiling(p / 2) + 1. Used to split floats in half. */ +static REAL splitter; +static REAL epsilon; /* = 2^(-p). Used to estimate roundoff errors. */ +/* A set of coefficients used to calculate maximum roundoff errors. */ +static REAL resulterrbound; +static REAL ccwerrboundA, ccwerrboundB, ccwerrboundC; +static REAL o3derrboundA, o3derrboundB, o3derrboundC; +static REAL iccerrboundA, iccerrboundB, iccerrboundC; +static REAL isperrboundA, isperrboundB, isperrboundC; + +// Options to choose types of geometric computtaions. +// Added by H. Si, 2012-08-23. +static int _use_inexact_arith; // -X option. +static int _use_static_filter; // Default option, disable it by -X1 + +// Static filters for orient3d() and insphere(). +// They are pre-calcualted and set in exactinit(). +// Added by H. Si, 2012-08-23. +static REAL o3dstaticfilter; +static REAL ispstaticfilter; + + + +// The following codes were part of "IEEE 754 floating-point test software" +// http://www.math.utah.edu/~beebe/software/ieee/ +// The original program was "fpinfo2.c". + +double fppow2(int n) +{ + double x, power; + x = (n < 0) ? ((double)1.0/(double)2.0) : (double)2.0; + n = (n < 0) ? -n : n; + power = (double)1.0; + while (n-- > 0) + power *= x; + return (power); +} + +#ifdef SINGLE + +float fstore(float x) +{ + return (x); +} + +int test_float(int verbose) +{ + float x; + int pass = 1; + + //(void)printf("float:\n"); + + if (verbose) { + (void)printf(" sizeof(float) = %2u\n", (unsigned int)sizeof(float)); +#ifdef CPU86 // + (void)printf(" FLT_MANT_DIG = %2d\n", FLT_MANT_DIG); +#endif + } + + x = (float)1.0; + while (fstore((float)1.0 + x/(float)2.0) != (float)1.0) + x /= (float)2.0; + if (verbose) + (void)printf(" machine epsilon = %13.5e ", x); + + if (x == (float)fppow2(-23)) { + if (verbose) + (void)printf("[IEEE 754 32-bit macheps]\n"); + } else { + (void)printf("[not IEEE 754 conformant] !!\n"); + pass = 0; + } + + x = (float)1.0; + while (fstore(x / (float)2.0) != (float)0.0) + x /= (float)2.0; + if (verbose) + (void)printf(" smallest positive number = %13.5e ", x); + + if (x == (float)fppow2(-149)) { + if (verbose) + (void)printf("[smallest 32-bit subnormal]\n"); + } else if (x == (float)fppow2(-126)) { + if (verbose) + (void)printf("[smallest 32-bit normal]\n"); + } else { + (void)printf("[not IEEE 754 conformant] !!\n"); + pass = 0; + } + + return pass; +} + +# else + +double dstore(double x) +{ + return (x); +} + +int test_double(int verbose) +{ + double x; + int pass = 1; + + // (void)printf("double:\n"); + if (verbose) { + (void)printf(" sizeof(double) = %2u\n", (unsigned int)sizeof(double)); +#ifdef CPU86 // + (void)printf(" DBL_MANT_DIG = %2d\n", DBL_MANT_DIG); +#endif + } + + x = 1.0; + while (dstore(1.0 + x/2.0) != 1.0) + x /= 2.0; + if (verbose) + (void)printf(" machine epsilon = %13.5le ", x); + + if (x == (double)fppow2(-52)) { + if (verbose) + (void)printf("[IEEE 754 64-bit macheps]\n"); + } else { + (void)printf("[not IEEE 754 conformant] !!\n"); + pass = 0; + } + + x = 1.0; + while (dstore(x / 2.0) != 0.0) + x /= 2.0; + //if (verbose) + // (void)printf(" smallest positive number = %13.5le ", x); + + if (x == (double)fppow2(-1074)) { + //if (verbose) + // (void)printf("[smallest 64-bit subnormal]\n"); + } else if (x == (double)fppow2(-1022)) { + //if (verbose) + // (void)printf("[smallest 64-bit normal]\n"); + } else { + (void)printf("[not IEEE 754 conformant] !!\n"); + pass = 0; + } + + return pass; +} + +#endif + +/*****************************************************************************/ +/* */ +/* exactinit() Initialize the variables used for exact arithmetic. */ +/* */ +/* `epsilon' is the largest power of two such that 1.0 + epsilon = 1.0 in */ +/* floating-point arithmetic. `epsilon' bounds the relative roundoff */ +/* error. It is used for floating-point error analysis. */ +/* */ +/* `splitter' is used to split floating-point numbers into two half- */ +/* length significands for exact multiplication. */ +/* */ +/* I imagine that a highly optimizing compiler might be too smart for its */ +/* own good, and somehow cause this routine to fail, if it pretends that */ +/* floating-point arithmetic is too much like real arithmetic. */ +/* */ +/* Don't change this routine unless you fully understand it. */ +/* */ +/*****************************************************************************/ + +void exactinit(int verbose, int noexact, int nofilter, REAL maxx, REAL maxy, + REAL maxz) +{ + REAL half; + REAL check, lastcheck; + int every_other; +#ifdef LINUX + int cword; +#endif /* LINUX */ + +#ifdef CPU86 +#ifdef SINGLE + _control87(_PC_24, _MCW_PC); /* Set FPU control word for single precision. */ +#else /* not SINGLE */ + _control87(_PC_53, _MCW_PC); /* Set FPU control word for double precision. */ +#endif /* not SINGLE */ +#endif /* CPU86 */ +#ifdef LINUX +#ifdef SINGLE + /* cword = 4223; */ + cword = 4210; /* set FPU control word for single precision */ +#else /* not SINGLE */ + /* cword = 4735; */ + cword = 4722; /* set FPU control word for double precision */ +#endif /* not SINGLE */ + _FPU_SETCW(cword); +#endif /* LINUX */ + + if (verbose) { + printf(" Initializing robust predicates.\n"); + } + +#ifdef USE_CGAL_PREDICATES + if (cgal_pred_obj.Has_static_filters) { + printf(" Use static filter.\n"); + } else { + printf(" No static filter.\n"); + } +#endif // USE_CGAL_PREDICATES + +#ifdef SINGLE + test_float(verbose); +#else + test_double(verbose); +#endif + + every_other = 1; + half = 0.5; + epsilon = 1.0; + splitter = 1.0; + check = 1.0; + /* Repeatedly divide `epsilon' by two until it is too small to add to */ + /* one without causing roundoff. (Also check if the sum is equal to */ + /* the previous sum, for machines that round up instead of using exact */ + /* rounding. Not that this library will work on such machines anyway. */ + do { + lastcheck = check; + epsilon *= half; + if (every_other) { + splitter *= 2.0; + } + every_other = !every_other; + check = 1.0 + epsilon; + } while ((check != 1.0) && (check != lastcheck)); + splitter += 1.0; + + /* Error bounds for orientation and incircle tests. */ + resulterrbound = (3.0 + 8.0 * epsilon) * epsilon; + ccwerrboundA = (3.0 + 16.0 * epsilon) * epsilon; + ccwerrboundB = (2.0 + 12.0 * epsilon) * epsilon; + ccwerrboundC = (9.0 + 64.0 * epsilon) * epsilon * epsilon; + o3derrboundA = (7.0 + 56.0 * epsilon) * epsilon; + o3derrboundB = (3.0 + 28.0 * epsilon) * epsilon; + o3derrboundC = (26.0 + 288.0 * epsilon) * epsilon * epsilon; + iccerrboundA = (10.0 + 96.0 * epsilon) * epsilon; + iccerrboundB = (4.0 + 48.0 * epsilon) * epsilon; + iccerrboundC = (44.0 + 576.0 * epsilon) * epsilon * epsilon; + isperrboundA = (16.0 + 224.0 * epsilon) * epsilon; + isperrboundB = (5.0 + 72.0 * epsilon) * epsilon; + isperrboundC = (71.0 + 1408.0 * epsilon) * epsilon * epsilon; + + // Set TetGen options. Added by H. Si, 2012-08-23. + _use_inexact_arith = noexact; + _use_static_filter = !nofilter; + + // Calculate the two static filters for orient3d() and insphere() tests. + // Added by H. Si, 2012-08-23. + + // Sort maxx < maxy < maxz. Re-use 'half' for swapping. + assert(maxx > 0); + assert(maxy > 0); + assert(maxz > 0); + + if (maxx > maxz) { + half = maxx; maxx = maxz; maxz = half; + } + if (maxy > maxz) { + half = maxy; maxy = maxz; maxz = half; + } + else if (maxy < maxx) { + half = maxy; maxy = maxx; maxx = half; + } + + o3dstaticfilter = 5.1107127829973299e-15 * maxx * maxy * maxz; + ispstaticfilter = 1.2466136531027298e-13 * maxx * maxy * maxz * (maxz * maxz); + +} + +/*****************************************************************************/ +/* */ +/* grow_expansion() Add a scalar to an expansion. */ +/* */ +/* Sets h = e + b. See the long version of my paper for details. */ +/* */ +/* Maintains the nonoverlapping property. If round-to-even is used (as */ +/* with IEEE 754), maintains the strongly nonoverlapping and nonadjacent */ +/* properties as well. (That is, if e has one of these properties, so */ +/* will h.) */ +/* */ +/*****************************************************************************/ + +int grow_expansion(int elen, REAL *e, REAL b, REAL *h) +/* e and h can be the same. */ +{ + REAL Q; + INEXACT REAL Qnew; + int eindex; + REAL enow; + INEXACT REAL bvirt; + REAL avirt, bround, around; + + Q = b; + for (eindex = 0; eindex < elen; eindex++) { + enow = e[eindex]; + Two_Sum(Q, enow, Qnew, h[eindex]); + Q = Qnew; + } + h[eindex] = Q; + return eindex + 1; +} + +/*****************************************************************************/ +/* */ +/* grow_expansion_zeroelim() Add a scalar to an expansion, eliminating */ +/* zero components from the output expansion. */ +/* */ +/* Sets h = e + b. See the long version of my paper for details. */ +/* */ +/* Maintains the nonoverlapping property. If round-to-even is used (as */ +/* with IEEE 754), maintains the strongly nonoverlapping and nonadjacent */ +/* properties as well. (That is, if e has one of these properties, so */ +/* will h.) */ +/* */ +/*****************************************************************************/ + +int grow_expansion_zeroelim(int elen, REAL *e, REAL b, REAL *h) +/* e and h can be the same. */ +{ + REAL Q, hh; + INEXACT REAL Qnew; + int eindex, hindex; + REAL enow; + INEXACT REAL bvirt; + REAL avirt, bround, around; + + hindex = 0; + Q = b; + for (eindex = 0; eindex < elen; eindex++) { + enow = e[eindex]; + Two_Sum(Q, enow, Qnew, hh); + Q = Qnew; + if (hh != 0.0) { + h[hindex++] = hh; + } + } + if ((Q != 0.0) || (hindex == 0)) { + h[hindex++] = Q; + } + return hindex; +} + +/*****************************************************************************/ +/* */ +/* expansion_sum() Sum two expansions. */ +/* */ +/* Sets h = e + f. See the long version of my paper for details. */ +/* */ +/* Maintains the nonoverlapping property. If round-to-even is used (as */ +/* with IEEE 754), maintains the nonadjacent property as well. (That is, */ +/* if e has one of these properties, so will h.) Does NOT maintain the */ +/* strongly nonoverlapping property. */ +/* */ +/*****************************************************************************/ + +int expansion_sum(int elen, REAL *e, int flen, REAL *f, REAL *h) +/* e and h can be the same, but f and h cannot. */ +{ + REAL Q; + INEXACT REAL Qnew; + int findex, hindex, hlast; + REAL hnow; + INEXACT REAL bvirt; + REAL avirt, bround, around; + + Q = f[0]; + for (hindex = 0; hindex < elen; hindex++) { + hnow = e[hindex]; + Two_Sum(Q, hnow, Qnew, h[hindex]); + Q = Qnew; + } + h[hindex] = Q; + hlast = hindex; + for (findex = 1; findex < flen; findex++) { + Q = f[findex]; + for (hindex = findex; hindex <= hlast; hindex++) { + hnow = h[hindex]; + Two_Sum(Q, hnow, Qnew, h[hindex]); + Q = Qnew; + } + h[++hlast] = Q; + } + return hlast + 1; +} + +/*****************************************************************************/ +/* */ +/* expansion_sum_zeroelim1() Sum two expansions, eliminating zero */ +/* components from the output expansion. */ +/* */ +/* Sets h = e + f. See the long version of my paper for details. */ +/* */ +/* Maintains the nonoverlapping property. If round-to-even is used (as */ +/* with IEEE 754), maintains the nonadjacent property as well. (That is, */ +/* if e has one of these properties, so will h.) Does NOT maintain the */ +/* strongly nonoverlapping property. */ +/* */ +/*****************************************************************************/ + +int expansion_sum_zeroelim1(int elen, REAL *e, int flen, REAL *f, REAL *h) +/* e and h can be the same, but f and h cannot. */ +{ + REAL Q; + INEXACT REAL Qnew; + int index, findex, hindex, hlast; + REAL hnow; + INEXACT REAL bvirt; + REAL avirt, bround, around; + + Q = f[0]; + for (hindex = 0; hindex < elen; hindex++) { + hnow = e[hindex]; + Two_Sum(Q, hnow, Qnew, h[hindex]); + Q = Qnew; + } + h[hindex] = Q; + hlast = hindex; + for (findex = 1; findex < flen; findex++) { + Q = f[findex]; + for (hindex = findex; hindex <= hlast; hindex++) { + hnow = h[hindex]; + Two_Sum(Q, hnow, Qnew, h[hindex]); + Q = Qnew; + } + h[++hlast] = Q; + } + hindex = -1; + for (index = 0; index <= hlast; index++) { + hnow = h[index]; + if (hnow != 0.0) { + h[++hindex] = hnow; + } + } + if (hindex == -1) { + return 1; + } else { + return hindex + 1; + } +} + +/*****************************************************************************/ +/* */ +/* expansion_sum_zeroelim2() Sum two expansions, eliminating zero */ +/* components from the output expansion. */ +/* */ +/* Sets h = e + f. See the long version of my paper for details. */ +/* */ +/* Maintains the nonoverlapping property. If round-to-even is used (as */ +/* with IEEE 754), maintains the nonadjacent property as well. (That is, */ +/* if e has one of these properties, so will h.) Does NOT maintain the */ +/* strongly nonoverlapping property. */ +/* */ +/*****************************************************************************/ + +int expansion_sum_zeroelim2(int elen, REAL *e, int flen, REAL *f, REAL *h) +/* e and h can be the same, but f and h cannot. */ +{ + REAL Q, hh; + INEXACT REAL Qnew; + int eindex, findex, hindex, hlast; + REAL enow; + INEXACT REAL bvirt; + REAL avirt, bround, around; + + hindex = 0; + Q = f[0]; + for (eindex = 0; eindex < elen; eindex++) { + enow = e[eindex]; + Two_Sum(Q, enow, Qnew, hh); + Q = Qnew; + if (hh != 0.0) { + h[hindex++] = hh; + } + } + h[hindex] = Q; + hlast = hindex; + for (findex = 1; findex < flen; findex++) { + hindex = 0; + Q = f[findex]; + for (eindex = 0; eindex <= hlast; eindex++) { + enow = h[eindex]; + Two_Sum(Q, enow, Qnew, hh); + Q = Qnew; + if (hh != 0) { + h[hindex++] = hh; + } + } + h[hindex] = Q; + hlast = hindex; + } + return hlast + 1; +} + +/*****************************************************************************/ +/* */ +/* fast_expansion_sum() Sum two expansions. */ +/* */ +/* Sets h = e + f. See the long version of my paper for details. */ +/* */ +/* If round-to-even is used (as with IEEE 754), maintains the strongly */ +/* nonoverlapping property. (That is, if e is strongly nonoverlapping, h */ +/* will be also.) Does NOT maintain the nonoverlapping or nonadjacent */ +/* properties. */ +/* */ +/*****************************************************************************/ + +int fast_expansion_sum(int elen, REAL *e, int flen, REAL *f, REAL *h) +/* h cannot be e or f. */ +{ + REAL Q; + INEXACT REAL Qnew; + INEXACT REAL bvirt; + REAL avirt, bround, around; + int eindex, findex, hindex; + REAL enow, fnow; + + enow = e[0]; + fnow = f[0]; + eindex = findex = 0; + if ((fnow > enow) == (fnow > -enow)) { + Q = enow; + enow = e[++eindex]; + } else { + Q = fnow; + fnow = f[++findex]; + } + hindex = 0; + if ((eindex < elen) && (findex < flen)) { + if ((fnow > enow) == (fnow > -enow)) { + Fast_Two_Sum(enow, Q, Qnew, h[0]); + enow = e[++eindex]; + } else { + Fast_Two_Sum(fnow, Q, Qnew, h[0]); + fnow = f[++findex]; + } + Q = Qnew; + hindex = 1; + while ((eindex < elen) && (findex < flen)) { + if ((fnow > enow) == (fnow > -enow)) { + Two_Sum(Q, enow, Qnew, h[hindex]); + enow = e[++eindex]; + } else { + Two_Sum(Q, fnow, Qnew, h[hindex]); + fnow = f[++findex]; + } + Q = Qnew; + hindex++; + } + } + while (eindex < elen) { + Two_Sum(Q, enow, Qnew, h[hindex]); + enow = e[++eindex]; + Q = Qnew; + hindex++; + } + while (findex < flen) { + Two_Sum(Q, fnow, Qnew, h[hindex]); + fnow = f[++findex]; + Q = Qnew; + hindex++; + } + h[hindex] = Q; + return hindex + 1; +} + +/*****************************************************************************/ +/* */ +/* fast_expansion_sum_zeroelim() Sum two expansions, eliminating zero */ +/* components from the output expansion. */ +/* */ +/* Sets h = e + f. See the long version of my paper for details. */ +/* */ +/* If round-to-even is used (as with IEEE 754), maintains the strongly */ +/* nonoverlapping property. (That is, if e is strongly nonoverlapping, h */ +/* will be also.) Does NOT maintain the nonoverlapping or nonadjacent */ +/* properties. */ +/* */ +/*****************************************************************************/ + +int fast_expansion_sum_zeroelim(int elen, REAL *e, int flen, REAL *f, REAL *h) +/* h cannot be e or f. */ +{ + REAL Q; + INEXACT REAL Qnew; + INEXACT REAL hh; + INEXACT REAL bvirt; + REAL avirt, bround, around; + int eindex, findex, hindex; + REAL enow, fnow; + + enow = e[0]; + fnow = f[0]; + eindex = findex = 0; + if ((fnow > enow) == (fnow > -enow)) { + Q = enow; + enow = e[++eindex]; + } else { + Q = fnow; + fnow = f[++findex]; + } + hindex = 0; + if ((eindex < elen) && (findex < flen)) { + if ((fnow > enow) == (fnow > -enow)) { + Fast_Two_Sum(enow, Q, Qnew, hh); + enow = e[++eindex]; + } else { + Fast_Two_Sum(fnow, Q, Qnew, hh); + fnow = f[++findex]; + } + Q = Qnew; + if (hh != 0.0) { + h[hindex++] = hh; + } + while ((eindex < elen) && (findex < flen)) { + if ((fnow > enow) == (fnow > -enow)) { + Two_Sum(Q, enow, Qnew, hh); + enow = e[++eindex]; + } else { + Two_Sum(Q, fnow, Qnew, hh); + fnow = f[++findex]; + } + Q = Qnew; + if (hh != 0.0) { + h[hindex++] = hh; + } + } + } + while (eindex < elen) { + Two_Sum(Q, enow, Qnew, hh); + enow = e[++eindex]; + Q = Qnew; + if (hh != 0.0) { + h[hindex++] = hh; + } + } + while (findex < flen) { + Two_Sum(Q, fnow, Qnew, hh); + fnow = f[++findex]; + Q = Qnew; + if (hh != 0.0) { + h[hindex++] = hh; + } + } + if ((Q != 0.0) || (hindex == 0)) { + h[hindex++] = Q; + } + return hindex; +} + +/*****************************************************************************/ +/* */ +/* linear_expansion_sum() Sum two expansions. */ +/* */ +/* Sets h = e + f. See either version of my paper for details. */ +/* */ +/* Maintains the nonoverlapping property. (That is, if e is */ +/* nonoverlapping, h will be also.) */ +/* */ +/*****************************************************************************/ + +int linear_expansion_sum(int elen, REAL *e, int flen, REAL *f, REAL *h) +/* h cannot be e or f. */ +{ + REAL Q, q; + INEXACT REAL Qnew; + INEXACT REAL R; + INEXACT REAL bvirt; + REAL avirt, bround, around; + int eindex, findex, hindex; + REAL enow, fnow; + REAL g0; + + enow = e[0]; + fnow = f[0]; + eindex = findex = 0; + if ((fnow > enow) == (fnow > -enow)) { + g0 = enow; + enow = e[++eindex]; + } else { + g0 = fnow; + fnow = f[++findex]; + } + if ((eindex < elen) && ((findex >= flen) + || ((fnow > enow) == (fnow > -enow)))) { + Fast_Two_Sum(enow, g0, Qnew, q); + enow = e[++eindex]; + } else { + Fast_Two_Sum(fnow, g0, Qnew, q); + fnow = f[++findex]; + } + Q = Qnew; + for (hindex = 0; hindex < elen + flen - 2; hindex++) { + if ((eindex < elen) && ((findex >= flen) + || ((fnow > enow) == (fnow > -enow)))) { + Fast_Two_Sum(enow, q, R, h[hindex]); + enow = e[++eindex]; + } else { + Fast_Two_Sum(fnow, q, R, h[hindex]); + fnow = f[++findex]; + } + Two_Sum(Q, R, Qnew, q); + Q = Qnew; + } + h[hindex] = q; + h[hindex + 1] = Q; + return hindex + 2; +} + +/*****************************************************************************/ +/* */ +/* linear_expansion_sum_zeroelim() Sum two expansions, eliminating zero */ +/* components from the output expansion. */ +/* */ +/* Sets h = e + f. See either version of my paper for details. */ +/* */ +/* Maintains the nonoverlapping property. (That is, if e is */ +/* nonoverlapping, h will be also.) */ +/* */ +/*****************************************************************************/ + +int linear_expansion_sum_zeroelim(int elen, REAL *e, int flen, REAL *f, + REAL *h) +/* h cannot be e or f. */ +{ + REAL Q, q, hh; + INEXACT REAL Qnew; + INEXACT REAL R; + INEXACT REAL bvirt; + REAL avirt, bround, around; + int eindex, findex, hindex; + int count; + REAL enow, fnow; + REAL g0; + + enow = e[0]; + fnow = f[0]; + eindex = findex = 0; + hindex = 0; + if ((fnow > enow) == (fnow > -enow)) { + g0 = enow; + enow = e[++eindex]; + } else { + g0 = fnow; + fnow = f[++findex]; + } + if ((eindex < elen) && ((findex >= flen) + || ((fnow > enow) == (fnow > -enow)))) { + Fast_Two_Sum(enow, g0, Qnew, q); + enow = e[++eindex]; + } else { + Fast_Two_Sum(fnow, g0, Qnew, q); + fnow = f[++findex]; + } + Q = Qnew; + for (count = 2; count < elen + flen; count++) { + if ((eindex < elen) && ((findex >= flen) + || ((fnow > enow) == (fnow > -enow)))) { + Fast_Two_Sum(enow, q, R, hh); + enow = e[++eindex]; + } else { + Fast_Two_Sum(fnow, q, R, hh); + fnow = f[++findex]; + } + Two_Sum(Q, R, Qnew, q); + Q = Qnew; + if (hh != 0) { + h[hindex++] = hh; + } + } + if (q != 0) { + h[hindex++] = q; + } + if ((Q != 0.0) || (hindex == 0)) { + h[hindex++] = Q; + } + return hindex; +} + +/*****************************************************************************/ +/* */ +/* scale_expansion() Multiply an expansion by a scalar. */ +/* */ +/* Sets h = be. See either version of my paper for details. */ +/* */ +/* Maintains the nonoverlapping property. If round-to-even is used (as */ +/* with IEEE 754), maintains the strongly nonoverlapping and nonadjacent */ +/* properties as well. (That is, if e has one of these properties, so */ +/* will h.) */ +/* */ +/*****************************************************************************/ + +int scale_expansion(int elen, REAL *e, REAL b, REAL *h) +/* e and h cannot be the same. */ +{ + INEXACT REAL Q; + INEXACT REAL sum; + INEXACT REAL product1; + REAL product0; + int eindex, hindex; + REAL enow; + INEXACT REAL bvirt; + REAL avirt, bround, around; + INEXACT REAL c; + INEXACT REAL abig; + REAL ahi, alo, bhi, blo; + REAL err1, err2, err3; + + Split(b, bhi, blo); + Two_Product_Presplit(e[0], b, bhi, blo, Q, h[0]); + hindex = 1; + for (eindex = 1; eindex < elen; eindex++) { + enow = e[eindex]; + Two_Product_Presplit(enow, b, bhi, blo, product1, product0); + Two_Sum(Q, product0, sum, h[hindex]); + hindex++; + Two_Sum(product1, sum, Q, h[hindex]); + hindex++; + } + h[hindex] = Q; + return elen + elen; +} + +/*****************************************************************************/ +/* */ +/* scale_expansion_zeroelim() Multiply an expansion by a scalar, */ +/* eliminating zero components from the */ +/* output expansion. */ +/* */ +/* Sets h = be. See either version of my paper for details. */ +/* */ +/* Maintains the nonoverlapping property. If round-to-even is used (as */ +/* with IEEE 754), maintains the strongly nonoverlapping and nonadjacent */ +/* properties as well. (That is, if e has one of these properties, so */ +/* will h.) */ +/* */ +/*****************************************************************************/ + +int scale_expansion_zeroelim(int elen, REAL *e, REAL b, REAL *h) +/* e and h cannot be the same. */ +{ + INEXACT REAL Q, sum; + REAL hh; + INEXACT REAL product1; + REAL product0; + int eindex, hindex; + REAL enow; + INEXACT REAL bvirt; + REAL avirt, bround, around; + INEXACT REAL c; + INEXACT REAL abig; + REAL ahi, alo, bhi, blo; + REAL err1, err2, err3; + + Split(b, bhi, blo); + Two_Product_Presplit(e[0], b, bhi, blo, Q, hh); + hindex = 0; + if (hh != 0) { + h[hindex++] = hh; + } + for (eindex = 1; eindex < elen; eindex++) { + enow = e[eindex]; + Two_Product_Presplit(enow, b, bhi, blo, product1, product0); + Two_Sum(Q, product0, sum, hh); + if (hh != 0) { + h[hindex++] = hh; + } + Fast_Two_Sum(product1, sum, Q, hh); + if (hh != 0) { + h[hindex++] = hh; + } + } + if ((Q != 0.0) || (hindex == 0)) { + h[hindex++] = Q; + } + return hindex; +} + +/*****************************************************************************/ +/* */ +/* compress() Compress an expansion. */ +/* */ +/* See the long version of my paper for details. */ +/* */ +/* Maintains the nonoverlapping property. If round-to-even is used (as */ +/* with IEEE 754), then any nonoverlapping expansion is converted to a */ +/* nonadjacent expansion. */ +/* */ +/*****************************************************************************/ + +int compress(int elen, REAL *e, REAL *h) +/* e and h may be the same. */ +{ + REAL Q, q; + INEXACT REAL Qnew; + int eindex, hindex; + INEXACT REAL bvirt; + REAL enow, hnow; + int top, bottom; + + bottom = elen - 1; + Q = e[bottom]; + for (eindex = elen - 2; eindex >= 0; eindex--) { + enow = e[eindex]; + Fast_Two_Sum(Q, enow, Qnew, q); + if (q != 0) { + h[bottom--] = Qnew; + Q = q; + } else { + Q = Qnew; + } + } + top = 0; + for (hindex = bottom + 1; hindex < elen; hindex++) { + hnow = h[hindex]; + Fast_Two_Sum(hnow, Q, Qnew, q); + if (q != 0) { + h[top++] = q; + } + Q = Qnew; + } + h[top] = Q; + return top + 1; +} + +/*****************************************************************************/ +/* */ +/* estimate() Produce a one-word estimate of an expansion's value. */ +/* */ +/* See either version of my paper for details. */ +/* */ +/*****************************************************************************/ + +REAL estimate(int elen, REAL *e) +{ + REAL Q; + int eindex; + + Q = e[0]; + for (eindex = 1; eindex < elen; eindex++) { + Q += e[eindex]; + } + return Q; +} + +/*****************************************************************************/ +/* */ +/* orient2dfast() Approximate 2D orientation test. Nonrobust. */ +/* orient2dexact() Exact 2D orientation test. Robust. */ +/* orient2dslow() Another exact 2D orientation test. Robust. */ +/* orient2d() Adaptive exact 2D orientation test. Robust. */ +/* */ +/* Return a positive value if the points pa, pb, and pc occur */ +/* in counterclockwise order; a negative value if they occur */ +/* in clockwise order; and zero if they are collinear. The */ +/* result is also a rough approximation of twice the signed */ +/* area of the triangle defined by the three points. */ +/* */ +/* Only the first and last routine should be used; the middle two are for */ +/* timings. */ +/* */ +/* The last three use exact arithmetic to ensure a correct answer. The */ +/* result returned is the determinant of a matrix. In orient2d() only, */ +/* this determinant is computed adaptively, in the sense that exact */ +/* arithmetic is used only to the degree it is needed to ensure that the */ +/* returned value has the correct sign. Hence, orient2d() is usually quite */ +/* fast, but will run more slowly when the input points are collinear or */ +/* nearly so. */ +/* */ +/*****************************************************************************/ + +REAL orient2dfast(REAL *pa, REAL *pb, REAL *pc) +{ + REAL acx, bcx, acy, bcy; + + acx = pa[0] - pc[0]; + bcx = pb[0] - pc[0]; + acy = pa[1] - pc[1]; + bcy = pb[1] - pc[1]; + return acx * bcy - acy * bcx; +} + +REAL orient2dexact(REAL *pa, REAL *pb, REAL *pc) +{ + INEXACT REAL axby1, axcy1, bxcy1, bxay1, cxay1, cxby1; + REAL axby0, axcy0, bxcy0, bxay0, cxay0, cxby0; + REAL aterms[4], bterms[4], cterms[4]; + INEXACT REAL aterms3, bterms3, cterms3; + REAL v[8], w[12]; + int vlength, wlength; + + INEXACT REAL bvirt; + REAL avirt, bround, around; + INEXACT REAL c; + INEXACT REAL abig; + REAL ahi, alo, bhi, blo; + REAL err1, err2, err3; + INEXACT REAL _i, _j; + REAL _0; + + Two_Product(pa[0], pb[1], axby1, axby0); + Two_Product(pa[0], pc[1], axcy1, axcy0); + Two_Two_Diff(axby1, axby0, axcy1, axcy0, + aterms3, aterms[2], aterms[1], aterms[0]); + aterms[3] = aterms3; + + Two_Product(pb[0], pc[1], bxcy1, bxcy0); + Two_Product(pb[0], pa[1], bxay1, bxay0); + Two_Two_Diff(bxcy1, bxcy0, bxay1, bxay0, + bterms3, bterms[2], bterms[1], bterms[0]); + bterms[3] = bterms3; + + Two_Product(pc[0], pa[1], cxay1, cxay0); + Two_Product(pc[0], pb[1], cxby1, cxby0); + Two_Two_Diff(cxay1, cxay0, cxby1, cxby0, + cterms3, cterms[2], cterms[1], cterms[0]); + cterms[3] = cterms3; + + vlength = fast_expansion_sum_zeroelim(4, aterms, 4, bterms, v); + wlength = fast_expansion_sum_zeroelim(vlength, v, 4, cterms, w); + + return w[wlength - 1]; +} + +REAL orient2dslow(REAL *pa, REAL *pb, REAL *pc) +{ + INEXACT REAL acx, acy, bcx, bcy; + REAL acxtail, acytail; + REAL bcxtail, bcytail; + REAL negate, negatetail; + REAL axby[8], bxay[8]; + INEXACT REAL axby7, bxay7; + REAL deter[16]; + int deterlen; + + INEXACT REAL bvirt; + REAL avirt, bround, around; + INEXACT REAL c; + INEXACT REAL abig; + REAL a0hi, a0lo, a1hi, a1lo, bhi, blo; + REAL err1, err2, err3; + INEXACT REAL _i, _j, _k, _l, _m, _n; + REAL _0, _1, _2; + + Two_Diff(pa[0], pc[0], acx, acxtail); + Two_Diff(pa[1], pc[1], acy, acytail); + Two_Diff(pb[0], pc[0], bcx, bcxtail); + Two_Diff(pb[1], pc[1], bcy, bcytail); + + Two_Two_Product(acx, acxtail, bcy, bcytail, + axby7, axby[6], axby[5], axby[4], + axby[3], axby[2], axby[1], axby[0]); + axby[7] = axby7; + negate = -acy; + negatetail = -acytail; + Two_Two_Product(bcx, bcxtail, negate, negatetail, + bxay7, bxay[6], bxay[5], bxay[4], + bxay[3], bxay[2], bxay[1], bxay[0]); + bxay[7] = bxay7; + + deterlen = fast_expansion_sum_zeroelim(8, axby, 8, bxay, deter); + + return deter[deterlen - 1]; +} + +REAL orient2dadapt(REAL *pa, REAL *pb, REAL *pc, REAL detsum) +{ + INEXACT REAL acx, acy, bcx, bcy; + REAL acxtail, acytail, bcxtail, bcytail; + INEXACT REAL detleft, detright; + REAL detlefttail, detrighttail; + REAL det, errbound; + REAL B[4], C1[8], C2[12], D[16]; + INEXACT REAL B3; + int C1length, C2length, Dlength; + REAL u[4]; + INEXACT REAL u3; + INEXACT REAL s1, t1; + REAL s0, t0; + + INEXACT REAL bvirt; + REAL avirt, bround, around; + INEXACT REAL c; + INEXACT REAL abig; + REAL ahi, alo, bhi, blo; + REAL err1, err2, err3; + INEXACT REAL _i, _j; + REAL _0; + + acx = (REAL) (pa[0] - pc[0]); + bcx = (REAL) (pb[0] - pc[0]); + acy = (REAL) (pa[1] - pc[1]); + bcy = (REAL) (pb[1] - pc[1]); + + Two_Product(acx, bcy, detleft, detlefttail); + Two_Product(acy, bcx, detright, detrighttail); + + Two_Two_Diff(detleft, detlefttail, detright, detrighttail, + B3, B[2], B[1], B[0]); + B[3] = B3; + + det = estimate(4, B); + errbound = ccwerrboundB * detsum; + if ((det >= errbound) || (-det >= errbound)) { + return det; + } + + Two_Diff_Tail(pa[0], pc[0], acx, acxtail); + Two_Diff_Tail(pb[0], pc[0], bcx, bcxtail); + Two_Diff_Tail(pa[1], pc[1], acy, acytail); + Two_Diff_Tail(pb[1], pc[1], bcy, bcytail); + + if ((acxtail == 0.0) && (acytail == 0.0) + && (bcxtail == 0.0) && (bcytail == 0.0)) { + return det; + } + + errbound = ccwerrboundC * detsum + resulterrbound * Absolute(det); + det += (acx * bcytail + bcy * acxtail) + - (acy * bcxtail + bcx * acytail); + if ((det >= errbound) || (-det >= errbound)) { + return det; + } + + Two_Product(acxtail, bcy, s1, s0); + Two_Product(acytail, bcx, t1, t0); + Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]); + u[3] = u3; + C1length = fast_expansion_sum_zeroelim(4, B, 4, u, C1); + + Two_Product(acx, bcytail, s1, s0); + Two_Product(acy, bcxtail, t1, t0); + Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]); + u[3] = u3; + C2length = fast_expansion_sum_zeroelim(C1length, C1, 4, u, C2); + + Two_Product(acxtail, bcytail, s1, s0); + Two_Product(acytail, bcxtail, t1, t0); + Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]); + u[3] = u3; + Dlength = fast_expansion_sum_zeroelim(C2length, C2, 4, u, D); + + return(D[Dlength - 1]); +} + +REAL orient2d(REAL *pa, REAL *pb, REAL *pc) +{ + REAL detleft, detright, det; + REAL detsum, errbound; + + detleft = (pa[0] - pc[0]) * (pb[1] - pc[1]); + detright = (pa[1] - pc[1]) * (pb[0] - pc[0]); + det = detleft - detright; + + if (detleft > 0.0) { + if (detright <= 0.0) { + return det; + } else { + detsum = detleft + detright; + } + } else if (detleft < 0.0) { + if (detright >= 0.0) { + return det; + } else { + detsum = -detleft - detright; + } + } else { + return det; + } + + errbound = ccwerrboundA * detsum; + if ((det >= errbound) || (-det >= errbound)) { + return det; + } + + return orient2dadapt(pa, pb, pc, detsum); +} + +/*****************************************************************************/ +/* */ +/* orient3dfast() Approximate 3D orientation test. Nonrobust. */ +/* orient3dexact() Exact 3D orientation test. Robust. */ +/* orient3dslow() Another exact 3D orientation test. Robust. */ +/* orient3d() Adaptive exact 3D orientation test. Robust. */ +/* */ +/* Return a positive value if the point pd lies below the */ +/* plane passing through pa, pb, and pc; "below" is defined so */ +/* that pa, pb, and pc appear in counterclockwise order when */ +/* viewed from above the plane. Returns a negative value if */ +/* pd lies above the plane. Returns zero if the points are */ +/* coplanar. The result is also a rough approximation of six */ +/* times the signed volume of the tetrahedron defined by the */ +/* four points. */ +/* */ +/* Only the first and last routine should be used; the middle two are for */ +/* timings. */ +/* */ +/* The last three use exact arithmetic to ensure a correct answer. The */ +/* result returned is the determinant of a matrix. In orient3d() only, */ +/* this determinant is computed adaptively, in the sense that exact */ +/* arithmetic is used only to the degree it is needed to ensure that the */ +/* returned value has the correct sign. Hence, orient3d() is usually quite */ +/* fast, but will run more slowly when the input points are coplanar or */ +/* nearly so. */ +/* */ +/*****************************************************************************/ + +REAL orient3dfast(REAL *pa, REAL *pb, REAL *pc, REAL *pd) +{ + REAL adx, bdx, cdx; + REAL ady, bdy, cdy; + REAL adz, bdz, cdz; + + adx = pa[0] - pd[0]; + bdx = pb[0] - pd[0]; + cdx = pc[0] - pd[0]; + ady = pa[1] - pd[1]; + bdy = pb[1] - pd[1]; + cdy = pc[1] - pd[1]; + adz = pa[2] - pd[2]; + bdz = pb[2] - pd[2]; + cdz = pc[2] - pd[2]; + + return adx * (bdy * cdz - bdz * cdy) + + bdx * (cdy * adz - cdz * ady) + + cdx * (ady * bdz - adz * bdy); +} + +REAL orient3dexact(REAL *pa, REAL *pb, REAL *pc, REAL *pd) +{ + INEXACT REAL axby1, bxcy1, cxdy1, dxay1, axcy1, bxdy1; + INEXACT REAL bxay1, cxby1, dxcy1, axdy1, cxay1, dxby1; + REAL axby0, bxcy0, cxdy0, dxay0, axcy0, bxdy0; + REAL bxay0, cxby0, dxcy0, axdy0, cxay0, dxby0; + REAL ab[4], bc[4], cd[4], da[4], ac[4], bd[4]; + REAL temp8[8]; + int templen; + REAL abc[12], bcd[12], cda[12], dab[12]; + int abclen, bcdlen, cdalen, dablen; + REAL adet[24], bdet[24], cdet[24], ddet[24]; + int alen, blen, clen, dlen; + REAL abdet[48], cddet[48]; + int ablen, cdlen; + REAL deter[96]; + int deterlen; + int i; + + INEXACT REAL bvirt; + REAL avirt, bround, around; + INEXACT REAL c; + INEXACT REAL abig; + REAL ahi, alo, bhi, blo; + REAL err1, err2, err3; + INEXACT REAL _i, _j; + REAL _0; + + Two_Product(pa[0], pb[1], axby1, axby0); + Two_Product(pb[0], pa[1], bxay1, bxay0); + Two_Two_Diff(axby1, axby0, bxay1, bxay0, ab[3], ab[2], ab[1], ab[0]); + + Two_Product(pb[0], pc[1], bxcy1, bxcy0); + Two_Product(pc[0], pb[1], cxby1, cxby0); + Two_Two_Diff(bxcy1, bxcy0, cxby1, cxby0, bc[3], bc[2], bc[1], bc[0]); + + Two_Product(pc[0], pd[1], cxdy1, cxdy0); + Two_Product(pd[0], pc[1], dxcy1, dxcy0); + Two_Two_Diff(cxdy1, cxdy0, dxcy1, dxcy0, cd[3], cd[2], cd[1], cd[0]); + + Two_Product(pd[0], pa[1], dxay1, dxay0); + Two_Product(pa[0], pd[1], axdy1, axdy0); + Two_Two_Diff(dxay1, dxay0, axdy1, axdy0, da[3], da[2], da[1], da[0]); + + Two_Product(pa[0], pc[1], axcy1, axcy0); + Two_Product(pc[0], pa[1], cxay1, cxay0); + Two_Two_Diff(axcy1, axcy0, cxay1, cxay0, ac[3], ac[2], ac[1], ac[0]); + + Two_Product(pb[0], pd[1], bxdy1, bxdy0); + Two_Product(pd[0], pb[1], dxby1, dxby0); + Two_Two_Diff(bxdy1, bxdy0, dxby1, dxby0, bd[3], bd[2], bd[1], bd[0]); + + templen = fast_expansion_sum_zeroelim(4, cd, 4, da, temp8); + cdalen = fast_expansion_sum_zeroelim(templen, temp8, 4, ac, cda); + templen = fast_expansion_sum_zeroelim(4, da, 4, ab, temp8); + dablen = fast_expansion_sum_zeroelim(templen, temp8, 4, bd, dab); + for (i = 0; i < 4; i++) { + bd[i] = -bd[i]; + ac[i] = -ac[i]; + } + templen = fast_expansion_sum_zeroelim(4, ab, 4, bc, temp8); + abclen = fast_expansion_sum_zeroelim(templen, temp8, 4, ac, abc); + templen = fast_expansion_sum_zeroelim(4, bc, 4, cd, temp8); + bcdlen = fast_expansion_sum_zeroelim(templen, temp8, 4, bd, bcd); + + alen = scale_expansion_zeroelim(bcdlen, bcd, pa[2], adet); + blen = scale_expansion_zeroelim(cdalen, cda, -pb[2], bdet); + clen = scale_expansion_zeroelim(dablen, dab, pc[2], cdet); + dlen = scale_expansion_zeroelim(abclen, abc, -pd[2], ddet); + + ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet); + cdlen = fast_expansion_sum_zeroelim(clen, cdet, dlen, ddet, cddet); + deterlen = fast_expansion_sum_zeroelim(ablen, abdet, cdlen, cddet, deter); + + return deter[deterlen - 1]; +} + +REAL orient3dslow(REAL *pa, REAL *pb, REAL *pc, REAL *pd) +{ + INEXACT REAL adx, ady, adz, bdx, bdy, bdz, cdx, cdy, cdz; + REAL adxtail, adytail, adztail; + REAL bdxtail, bdytail, bdztail; + REAL cdxtail, cdytail, cdztail; + REAL negate, negatetail; + INEXACT REAL axby7, bxcy7, axcy7, bxay7, cxby7, cxay7; + REAL axby[8], bxcy[8], axcy[8], bxay[8], cxby[8], cxay[8]; + REAL temp16[16], temp32[32], temp32t[32]; + int temp16len, temp32len, temp32tlen; + REAL adet[64], bdet[64], cdet[64]; + int alen, blen, clen; + REAL abdet[128]; + int ablen; + REAL deter[192]; + int deterlen; + + INEXACT REAL bvirt; + REAL avirt, bround, around; + INEXACT REAL c; + INEXACT REAL abig; + REAL a0hi, a0lo, a1hi, a1lo, bhi, blo; + REAL err1, err2, err3; + INEXACT REAL _i, _j, _k, _l, _m, _n; + REAL _0, _1, _2; + + Two_Diff(pa[0], pd[0], adx, adxtail); + Two_Diff(pa[1], pd[1], ady, adytail); + Two_Diff(pa[2], pd[2], adz, adztail); + Two_Diff(pb[0], pd[0], bdx, bdxtail); + Two_Diff(pb[1], pd[1], bdy, bdytail); + Two_Diff(pb[2], pd[2], bdz, bdztail); + Two_Diff(pc[0], pd[0], cdx, cdxtail); + Two_Diff(pc[1], pd[1], cdy, cdytail); + Two_Diff(pc[2], pd[2], cdz, cdztail); + + Two_Two_Product(adx, adxtail, bdy, bdytail, + axby7, axby[6], axby[5], axby[4], + axby[3], axby[2], axby[1], axby[0]); + axby[7] = axby7; + negate = -ady; + negatetail = -adytail; + Two_Two_Product(bdx, bdxtail, negate, negatetail, + bxay7, bxay[6], bxay[5], bxay[4], + bxay[3], bxay[2], bxay[1], bxay[0]); + bxay[7] = bxay7; + Two_Two_Product(bdx, bdxtail, cdy, cdytail, + bxcy7, bxcy[6], bxcy[5], bxcy[4], + bxcy[3], bxcy[2], bxcy[1], bxcy[0]); + bxcy[7] = bxcy7; + negate = -bdy; + negatetail = -bdytail; + Two_Two_Product(cdx, cdxtail, negate, negatetail, + cxby7, cxby[6], cxby[5], cxby[4], + cxby[3], cxby[2], cxby[1], cxby[0]); + cxby[7] = cxby7; + Two_Two_Product(cdx, cdxtail, ady, adytail, + cxay7, cxay[6], cxay[5], cxay[4], + cxay[3], cxay[2], cxay[1], cxay[0]); + cxay[7] = cxay7; + negate = -cdy; + negatetail = -cdytail; + Two_Two_Product(adx, adxtail, negate, negatetail, + axcy7, axcy[6], axcy[5], axcy[4], + axcy[3], axcy[2], axcy[1], axcy[0]); + axcy[7] = axcy7; + + temp16len = fast_expansion_sum_zeroelim(8, bxcy, 8, cxby, temp16); + temp32len = scale_expansion_zeroelim(temp16len, temp16, adz, temp32); + temp32tlen = scale_expansion_zeroelim(temp16len, temp16, adztail, temp32t); + alen = fast_expansion_sum_zeroelim(temp32len, temp32, temp32tlen, temp32t, + adet); + + temp16len = fast_expansion_sum_zeroelim(8, cxay, 8, axcy, temp16); + temp32len = scale_expansion_zeroelim(temp16len, temp16, bdz, temp32); + temp32tlen = scale_expansion_zeroelim(temp16len, temp16, bdztail, temp32t); + blen = fast_expansion_sum_zeroelim(temp32len, temp32, temp32tlen, temp32t, + bdet); + + temp16len = fast_expansion_sum_zeroelim(8, axby, 8, bxay, temp16); + temp32len = scale_expansion_zeroelim(temp16len, temp16, cdz, temp32); + temp32tlen = scale_expansion_zeroelim(temp16len, temp16, cdztail, temp32t); + clen = fast_expansion_sum_zeroelim(temp32len, temp32, temp32tlen, temp32t, + cdet); + + ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet); + deterlen = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, deter); + + return deter[deterlen - 1]; +} + +REAL orient3dadapt(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL permanent) +{ + INEXACT REAL adx, bdx, cdx, ady, bdy, cdy, adz, bdz, cdz; + REAL det, errbound; + + INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1; + REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0; + REAL bc[4], ca[4], ab[4]; + INEXACT REAL bc3, ca3, ab3; + REAL adet[8], bdet[8], cdet[8]; + int alen, blen, clen; + REAL abdet[16]; + int ablen; + REAL *finnow, *finother, *finswap; + REAL fin1[192], fin2[192]; + int finlength; + + + REAL adxtail, bdxtail, cdxtail; + REAL adytail, bdytail, cdytail; + REAL adztail, bdztail, cdztail; + INEXACT REAL at_blarge, at_clarge; + INEXACT REAL bt_clarge, bt_alarge; + INEXACT REAL ct_alarge, ct_blarge; + REAL at_b[4], at_c[4], bt_c[4], bt_a[4], ct_a[4], ct_b[4]; + int at_blen, at_clen, bt_clen, bt_alen, ct_alen, ct_blen; + INEXACT REAL bdxt_cdy1, cdxt_bdy1, cdxt_ady1; + INEXACT REAL adxt_cdy1, adxt_bdy1, bdxt_ady1; + REAL bdxt_cdy0, cdxt_bdy0, cdxt_ady0; + REAL adxt_cdy0, adxt_bdy0, bdxt_ady0; + INEXACT REAL bdyt_cdx1, cdyt_bdx1, cdyt_adx1; + INEXACT REAL adyt_cdx1, adyt_bdx1, bdyt_adx1; + REAL bdyt_cdx0, cdyt_bdx0, cdyt_adx0; + REAL adyt_cdx0, adyt_bdx0, bdyt_adx0; + REAL bct[8], cat[8], abt[8]; + int bctlen, catlen, abtlen; + INEXACT REAL bdxt_cdyt1, cdxt_bdyt1, cdxt_adyt1; + INEXACT REAL adxt_cdyt1, adxt_bdyt1, bdxt_adyt1; + REAL bdxt_cdyt0, cdxt_bdyt0, cdxt_adyt0; + REAL adxt_cdyt0, adxt_bdyt0, bdxt_adyt0; + REAL u[4], v[12], w[16]; + INEXACT REAL u3; + int vlength, wlength; + REAL negate; + + INEXACT REAL bvirt; + REAL avirt, bround, around; + INEXACT REAL c; + INEXACT REAL abig; + REAL ahi, alo, bhi, blo; + REAL err1, err2, err3; + INEXACT REAL _i, _j, _k; + REAL _0; + + + adx = (REAL) (pa[0] - pd[0]); + bdx = (REAL) (pb[0] - pd[0]); + cdx = (REAL) (pc[0] - pd[0]); + ady = (REAL) (pa[1] - pd[1]); + bdy = (REAL) (pb[1] - pd[1]); + cdy = (REAL) (pc[1] - pd[1]); + adz = (REAL) (pa[2] - pd[2]); + bdz = (REAL) (pb[2] - pd[2]); + cdz = (REAL) (pc[2] - pd[2]); + + Two_Product(bdx, cdy, bdxcdy1, bdxcdy0); + Two_Product(cdx, bdy, cdxbdy1, cdxbdy0); + Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]); + bc[3] = bc3; + alen = scale_expansion_zeroelim(4, bc, adz, adet); + + Two_Product(cdx, ady, cdxady1, cdxady0); + Two_Product(adx, cdy, adxcdy1, adxcdy0); + Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]); + ca[3] = ca3; + blen = scale_expansion_zeroelim(4, ca, bdz, bdet); + + Two_Product(adx, bdy, adxbdy1, adxbdy0); + Two_Product(bdx, ady, bdxady1, bdxady0); + Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]); + ab[3] = ab3; + clen = scale_expansion_zeroelim(4, ab, cdz, cdet); + + ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet); + finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1); + + det = estimate(finlength, fin1); + errbound = o3derrboundB * permanent; + if ((det >= errbound) || (-det >= errbound)) { + return det; + } + + Two_Diff_Tail(pa[0], pd[0], adx, adxtail); + Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail); + Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail); + Two_Diff_Tail(pa[1], pd[1], ady, adytail); + Two_Diff_Tail(pb[1], pd[1], bdy, bdytail); + Two_Diff_Tail(pc[1], pd[1], cdy, cdytail); + Two_Diff_Tail(pa[2], pd[2], adz, adztail); + Two_Diff_Tail(pb[2], pd[2], bdz, bdztail); + Two_Diff_Tail(pc[2], pd[2], cdz, cdztail); + + if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0) + && (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0) + && (adztail == 0.0) && (bdztail == 0.0) && (cdztail == 0.0)) { + return det; + } + + errbound = o3derrboundC * permanent + resulterrbound * Absolute(det); + det += (adz * ((bdx * cdytail + cdy * bdxtail) + - (bdy * cdxtail + cdx * bdytail)) + + adztail * (bdx * cdy - bdy * cdx)) + + (bdz * ((cdx * adytail + ady * cdxtail) + - (cdy * adxtail + adx * cdytail)) + + bdztail * (cdx * ady - cdy * adx)) + + (cdz * ((adx * bdytail + bdy * adxtail) + - (ady * bdxtail + bdx * adytail)) + + cdztail * (adx * bdy - ady * bdx)); + if ((det >= errbound) || (-det >= errbound)) { + return det; + } + + finnow = fin1; + finother = fin2; + + if (adxtail == 0.0) { + if (adytail == 0.0) { + at_b[0] = 0.0; + at_blen = 1; + at_c[0] = 0.0; + at_clen = 1; + } else { + negate = -adytail; + Two_Product(negate, bdx, at_blarge, at_b[0]); + at_b[1] = at_blarge; + at_blen = 2; + Two_Product(adytail, cdx, at_clarge, at_c[0]); + at_c[1] = at_clarge; + at_clen = 2; + } + } else { + if (adytail == 0.0) { + Two_Product(adxtail, bdy, at_blarge, at_b[0]); + at_b[1] = at_blarge; + at_blen = 2; + negate = -adxtail; + Two_Product(negate, cdy, at_clarge, at_c[0]); + at_c[1] = at_clarge; + at_clen = 2; + } else { + Two_Product(adxtail, bdy, adxt_bdy1, adxt_bdy0); + Two_Product(adytail, bdx, adyt_bdx1, adyt_bdx0); + Two_Two_Diff(adxt_bdy1, adxt_bdy0, adyt_bdx1, adyt_bdx0, + at_blarge, at_b[2], at_b[1], at_b[0]); + at_b[3] = at_blarge; + at_blen = 4; + Two_Product(adytail, cdx, adyt_cdx1, adyt_cdx0); + Two_Product(adxtail, cdy, adxt_cdy1, adxt_cdy0); + Two_Two_Diff(adyt_cdx1, adyt_cdx0, adxt_cdy1, adxt_cdy0, + at_clarge, at_c[2], at_c[1], at_c[0]); + at_c[3] = at_clarge; + at_clen = 4; + } + } + if (bdxtail == 0.0) { + if (bdytail == 0.0) { + bt_c[0] = 0.0; + bt_clen = 1; + bt_a[0] = 0.0; + bt_alen = 1; + } else { + negate = -bdytail; + Two_Product(negate, cdx, bt_clarge, bt_c[0]); + bt_c[1] = bt_clarge; + bt_clen = 2; + Two_Product(bdytail, adx, bt_alarge, bt_a[0]); + bt_a[1] = bt_alarge; + bt_alen = 2; + } + } else { + if (bdytail == 0.0) { + Two_Product(bdxtail, cdy, bt_clarge, bt_c[0]); + bt_c[1] = bt_clarge; + bt_clen = 2; + negate = -bdxtail; + Two_Product(negate, ady, bt_alarge, bt_a[0]); + bt_a[1] = bt_alarge; + bt_alen = 2; + } else { + Two_Product(bdxtail, cdy, bdxt_cdy1, bdxt_cdy0); + Two_Product(bdytail, cdx, bdyt_cdx1, bdyt_cdx0); + Two_Two_Diff(bdxt_cdy1, bdxt_cdy0, bdyt_cdx1, bdyt_cdx0, + bt_clarge, bt_c[2], bt_c[1], bt_c[0]); + bt_c[3] = bt_clarge; + bt_clen = 4; + Two_Product(bdytail, adx, bdyt_adx1, bdyt_adx0); + Two_Product(bdxtail, ady, bdxt_ady1, bdxt_ady0); + Two_Two_Diff(bdyt_adx1, bdyt_adx0, bdxt_ady1, bdxt_ady0, + bt_alarge, bt_a[2], bt_a[1], bt_a[0]); + bt_a[3] = bt_alarge; + bt_alen = 4; + } + } + if (cdxtail == 0.0) { + if (cdytail == 0.0) { + ct_a[0] = 0.0; + ct_alen = 1; + ct_b[0] = 0.0; + ct_blen = 1; + } else { + negate = -cdytail; + Two_Product(negate, adx, ct_alarge, ct_a[0]); + ct_a[1] = ct_alarge; + ct_alen = 2; + Two_Product(cdytail, bdx, ct_blarge, ct_b[0]); + ct_b[1] = ct_blarge; + ct_blen = 2; + } + } else { + if (cdytail == 0.0) { + Two_Product(cdxtail, ady, ct_alarge, ct_a[0]); + ct_a[1] = ct_alarge; + ct_alen = 2; + negate = -cdxtail; + Two_Product(negate, bdy, ct_blarge, ct_b[0]); + ct_b[1] = ct_blarge; + ct_blen = 2; + } else { + Two_Product(cdxtail, ady, cdxt_ady1, cdxt_ady0); + Two_Product(cdytail, adx, cdyt_adx1, cdyt_adx0); + Two_Two_Diff(cdxt_ady1, cdxt_ady0, cdyt_adx1, cdyt_adx0, + ct_alarge, ct_a[2], ct_a[1], ct_a[0]); + ct_a[3] = ct_alarge; + ct_alen = 4; + Two_Product(cdytail, bdx, cdyt_bdx1, cdyt_bdx0); + Two_Product(cdxtail, bdy, cdxt_bdy1, cdxt_bdy0); + Two_Two_Diff(cdyt_bdx1, cdyt_bdx0, cdxt_bdy1, cdxt_bdy0, + ct_blarge, ct_b[2], ct_b[1], ct_b[0]); + ct_b[3] = ct_blarge; + ct_blen = 4; + } + } + + bctlen = fast_expansion_sum_zeroelim(bt_clen, bt_c, ct_blen, ct_b, bct); + wlength = scale_expansion_zeroelim(bctlen, bct, adz, w); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w, + finother); + finswap = finnow; finnow = finother; finother = finswap; + + catlen = fast_expansion_sum_zeroelim(ct_alen, ct_a, at_clen, at_c, cat); + wlength = scale_expansion_zeroelim(catlen, cat, bdz, w); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w, + finother); + finswap = finnow; finnow = finother; finother = finswap; + + abtlen = fast_expansion_sum_zeroelim(at_blen, at_b, bt_alen, bt_a, abt); + wlength = scale_expansion_zeroelim(abtlen, abt, cdz, w); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w, + finother); + finswap = finnow; finnow = finother; finother = finswap; + + if (adztail != 0.0) { + vlength = scale_expansion_zeroelim(4, bc, adztail, v); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v, + finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (bdztail != 0.0) { + vlength = scale_expansion_zeroelim(4, ca, bdztail, v); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v, + finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (cdztail != 0.0) { + vlength = scale_expansion_zeroelim(4, ab, cdztail, v); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v, + finother); + finswap = finnow; finnow = finother; finother = finswap; + } + + if (adxtail != 0.0) { + if (bdytail != 0.0) { + Two_Product(adxtail, bdytail, adxt_bdyt1, adxt_bdyt0); + Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdz, u3, u[2], u[1], u[0]); + u[3] = u3; + finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, + finother); + finswap = finnow; finnow = finother; finother = finswap; + if (cdztail != 0.0) { + Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdztail, u3, u[2], u[1], u[0]); + u[3] = u3; + finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, + finother); + finswap = finnow; finnow = finother; finother = finswap; + } + } + if (cdytail != 0.0) { + negate = -adxtail; + Two_Product(negate, cdytail, adxt_cdyt1, adxt_cdyt0); + Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdz, u3, u[2], u[1], u[0]); + u[3] = u3; + finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, + finother); + finswap = finnow; finnow = finother; finother = finswap; + if (bdztail != 0.0) { + Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdztail, u3, u[2], u[1], u[0]); + u[3] = u3; + finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, + finother); + finswap = finnow; finnow = finother; finother = finswap; + } + } + } + if (bdxtail != 0.0) { + if (cdytail != 0.0) { + Two_Product(bdxtail, cdytail, bdxt_cdyt1, bdxt_cdyt0); + Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adz, u3, u[2], u[1], u[0]); + u[3] = u3; + finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, + finother); + finswap = finnow; finnow = finother; finother = finswap; + if (adztail != 0.0) { + Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adztail, u3, u[2], u[1], u[0]); + u[3] = u3; + finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, + finother); + finswap = finnow; finnow = finother; finother = finswap; + } + } + if (adytail != 0.0) { + negate = -bdxtail; + Two_Product(negate, adytail, bdxt_adyt1, bdxt_adyt0); + Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdz, u3, u[2], u[1], u[0]); + u[3] = u3; + finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, + finother); + finswap = finnow; finnow = finother; finother = finswap; + if (cdztail != 0.0) { + Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdztail, u3, u[2], u[1], u[0]); + u[3] = u3; + finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, + finother); + finswap = finnow; finnow = finother; finother = finswap; + } + } + } + if (cdxtail != 0.0) { + if (adytail != 0.0) { + Two_Product(cdxtail, adytail, cdxt_adyt1, cdxt_adyt0); + Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdz, u3, u[2], u[1], u[0]); + u[3] = u3; + finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, + finother); + finswap = finnow; finnow = finother; finother = finswap; + if (bdztail != 0.0) { + Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdztail, u3, u[2], u[1], u[0]); + u[3] = u3; + finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, + finother); + finswap = finnow; finnow = finother; finother = finswap; + } + } + if (bdytail != 0.0) { + negate = -cdxtail; + Two_Product(negate, bdytail, cdxt_bdyt1, cdxt_bdyt0); + Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adz, u3, u[2], u[1], u[0]); + u[3] = u3; + finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, + finother); + finswap = finnow; finnow = finother; finother = finswap; + if (adztail != 0.0) { + Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adztail, u3, u[2], u[1], u[0]); + u[3] = u3; + finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, + finother); + finswap = finnow; finnow = finother; finother = finswap; + } + } + } + + if (adztail != 0.0) { + wlength = scale_expansion_zeroelim(bctlen, bct, adztail, w); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w, + finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (bdztail != 0.0) { + wlength = scale_expansion_zeroelim(catlen, cat, bdztail, w); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w, + finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (cdztail != 0.0) { + wlength = scale_expansion_zeroelim(abtlen, abt, cdztail, w); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w, + finother); + finswap = finnow; finnow = finother; finother = finswap; + } + + return finnow[finlength - 1]; +} + +#ifdef USE_CGAL_PREDICATES + +REAL orient3d(REAL *pa, REAL *pb, REAL *pc, REAL *pd) +{ + return (REAL) + - cgal_pred_obj.orientation_3_object() + (Point(pa[0], pa[1], pa[2]), + Point(pb[0], pb[1], pb[2]), + Point(pc[0], pc[1], pc[2]), + Point(pd[0], pd[1], pd[2])); +} + +#else + +REAL orient3d(REAL *pa, REAL *pb, REAL *pc, REAL *pd) +{ + REAL adx, bdx, cdx, ady, bdy, cdy, adz, bdz, cdz; + REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady; + REAL det; + + + adx = pa[0] - pd[0]; + ady = pa[1] - pd[1]; + adz = pa[2] - pd[2]; + bdx = pb[0] - pd[0]; + bdy = pb[1] - pd[1]; + bdz = pb[2] - pd[2]; + cdx = pc[0] - pd[0]; + cdy = pc[1] - pd[1]; + cdz = pc[2] - pd[2]; + + bdxcdy = bdx * cdy; + cdxbdy = cdx * bdy; + + cdxady = cdx * ady; + adxcdy = adx * cdy; + + adxbdy = adx * bdy; + bdxady = bdx * ady; + + det = adz * (bdxcdy - cdxbdy) + + bdz * (cdxady - adxcdy) + + cdz * (adxbdy - bdxady); + + if (_use_inexact_arith) { + return det; + } + + if (_use_static_filter) { + //if (fabs(det) > o3dstaticfilter) return det; + if (det > o3dstaticfilter) return det; + if (det < -o3dstaticfilter) return det; + } + + + REAL permanent, errbound; + + permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * Absolute(adz) + + (Absolute(cdxady) + Absolute(adxcdy)) * Absolute(bdz) + + (Absolute(adxbdy) + Absolute(bdxady)) * Absolute(cdz); + errbound = o3derrboundA * permanent; + if ((det > errbound) || (-det > errbound)) { + return det; + } + + return orient3dadapt(pa, pb, pc, pd, permanent); +} + +#endif // #ifdef USE_CGAL_PREDICATES + +/*****************************************************************************/ +/* */ +/* incirclefast() Approximate 2D incircle test. Nonrobust. */ +/* incircleexact() Exact 2D incircle test. Robust. */ +/* incircleslow() Another exact 2D incircle test. Robust. */ +/* incircle() Adaptive exact 2D incircle test. Robust. */ +/* */ +/* Return a positive value if the point pd lies inside the */ +/* circle passing through pa, pb, and pc; a negative value if */ +/* it lies outside; and zero if the four points are cocircular.*/ +/* The points pa, pb, and pc must be in counterclockwise */ +/* order, or the sign of the result will be reversed. */ +/* */ +/* Only the first and last routine should be used; the middle two are for */ +/* timings. */ +/* */ +/* The last three use exact arithmetic to ensure a correct answer. The */ +/* result returned is the determinant of a matrix. In incircle() only, */ +/* this determinant is computed adaptively, in the sense that exact */ +/* arithmetic is used only to the degree it is needed to ensure that the */ +/* returned value has the correct sign. Hence, incircle() is usually quite */ +/* fast, but will run more slowly when the input points are cocircular or */ +/* nearly so. */ +/* */ +/*****************************************************************************/ + +REAL incirclefast(REAL *pa, REAL *pb, REAL *pc, REAL *pd) +{ + REAL adx, ady, bdx, bdy, cdx, cdy; + REAL abdet, bcdet, cadet; + REAL alift, blift, clift; + + adx = pa[0] - pd[0]; + ady = pa[1] - pd[1]; + bdx = pb[0] - pd[0]; + bdy = pb[1] - pd[1]; + cdx = pc[0] - pd[0]; + cdy = pc[1] - pd[1]; + + abdet = adx * bdy - bdx * ady; + bcdet = bdx * cdy - cdx * bdy; + cadet = cdx * ady - adx * cdy; + alift = adx * adx + ady * ady; + blift = bdx * bdx + bdy * bdy; + clift = cdx * cdx + cdy * cdy; + + return alift * bcdet + blift * cadet + clift * abdet; +} + +REAL incircleexact(REAL *pa, REAL *pb, REAL *pc, REAL *pd) +{ + INEXACT REAL axby1, bxcy1, cxdy1, dxay1, axcy1, bxdy1; + INEXACT REAL bxay1, cxby1, dxcy1, axdy1, cxay1, dxby1; + REAL axby0, bxcy0, cxdy0, dxay0, axcy0, bxdy0; + REAL bxay0, cxby0, dxcy0, axdy0, cxay0, dxby0; + REAL ab[4], bc[4], cd[4], da[4], ac[4], bd[4]; + REAL temp8[8]; + int templen; + REAL abc[12], bcd[12], cda[12], dab[12]; + int abclen, bcdlen, cdalen, dablen; + REAL det24x[24], det24y[24], det48x[48], det48y[48]; + int xlen, ylen; + REAL adet[96], bdet[96], cdet[96], ddet[96]; + int alen, blen, clen, dlen; + REAL abdet[192], cddet[192]; + int ablen, cdlen; + REAL deter[384]; + int deterlen; + int i; + + INEXACT REAL bvirt; + REAL avirt, bround, around; + INEXACT REAL c; + INEXACT REAL abig; + REAL ahi, alo, bhi, blo; + REAL err1, err2, err3; + INEXACT REAL _i, _j; + REAL _0; + + Two_Product(pa[0], pb[1], axby1, axby0); + Two_Product(pb[0], pa[1], bxay1, bxay0); + Two_Two_Diff(axby1, axby0, bxay1, bxay0, ab[3], ab[2], ab[1], ab[0]); + + Two_Product(pb[0], pc[1], bxcy1, bxcy0); + Two_Product(pc[0], pb[1], cxby1, cxby0); + Two_Two_Diff(bxcy1, bxcy0, cxby1, cxby0, bc[3], bc[2], bc[1], bc[0]); + + Two_Product(pc[0], pd[1], cxdy1, cxdy0); + Two_Product(pd[0], pc[1], dxcy1, dxcy0); + Two_Two_Diff(cxdy1, cxdy0, dxcy1, dxcy0, cd[3], cd[2], cd[1], cd[0]); + + Two_Product(pd[0], pa[1], dxay1, dxay0); + Two_Product(pa[0], pd[1], axdy1, axdy0); + Two_Two_Diff(dxay1, dxay0, axdy1, axdy0, da[3], da[2], da[1], da[0]); + + Two_Product(pa[0], pc[1], axcy1, axcy0); + Two_Product(pc[0], pa[1], cxay1, cxay0); + Two_Two_Diff(axcy1, axcy0, cxay1, cxay0, ac[3], ac[2], ac[1], ac[0]); + + Two_Product(pb[0], pd[1], bxdy1, bxdy0); + Two_Product(pd[0], pb[1], dxby1, dxby0); + Two_Two_Diff(bxdy1, bxdy0, dxby1, dxby0, bd[3], bd[2], bd[1], bd[0]); + + templen = fast_expansion_sum_zeroelim(4, cd, 4, da, temp8); + cdalen = fast_expansion_sum_zeroelim(templen, temp8, 4, ac, cda); + templen = fast_expansion_sum_zeroelim(4, da, 4, ab, temp8); + dablen = fast_expansion_sum_zeroelim(templen, temp8, 4, bd, dab); + for (i = 0; i < 4; i++) { + bd[i] = -bd[i]; + ac[i] = -ac[i]; + } + templen = fast_expansion_sum_zeroelim(4, ab, 4, bc, temp8); + abclen = fast_expansion_sum_zeroelim(templen, temp8, 4, ac, abc); + templen = fast_expansion_sum_zeroelim(4, bc, 4, cd, temp8); + bcdlen = fast_expansion_sum_zeroelim(templen, temp8, 4, bd, bcd); + + xlen = scale_expansion_zeroelim(bcdlen, bcd, pa[0], det24x); + xlen = scale_expansion_zeroelim(xlen, det24x, pa[0], det48x); + ylen = scale_expansion_zeroelim(bcdlen, bcd, pa[1], det24y); + ylen = scale_expansion_zeroelim(ylen, det24y, pa[1], det48y); + alen = fast_expansion_sum_zeroelim(xlen, det48x, ylen, det48y, adet); + + xlen = scale_expansion_zeroelim(cdalen, cda, pb[0], det24x); + xlen = scale_expansion_zeroelim(xlen, det24x, -pb[0], det48x); + ylen = scale_expansion_zeroelim(cdalen, cda, pb[1], det24y); + ylen = scale_expansion_zeroelim(ylen, det24y, -pb[1], det48y); + blen = fast_expansion_sum_zeroelim(xlen, det48x, ylen, det48y, bdet); + + xlen = scale_expansion_zeroelim(dablen, dab, pc[0], det24x); + xlen = scale_expansion_zeroelim(xlen, det24x, pc[0], det48x); + ylen = scale_expansion_zeroelim(dablen, dab, pc[1], det24y); + ylen = scale_expansion_zeroelim(ylen, det24y, pc[1], det48y); + clen = fast_expansion_sum_zeroelim(xlen, det48x, ylen, det48y, cdet); + + xlen = scale_expansion_zeroelim(abclen, abc, pd[0], det24x); + xlen = scale_expansion_zeroelim(xlen, det24x, -pd[0], det48x); + ylen = scale_expansion_zeroelim(abclen, abc, pd[1], det24y); + ylen = scale_expansion_zeroelim(ylen, det24y, -pd[1], det48y); + dlen = fast_expansion_sum_zeroelim(xlen, det48x, ylen, det48y, ddet); + + ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet); + cdlen = fast_expansion_sum_zeroelim(clen, cdet, dlen, ddet, cddet); + deterlen = fast_expansion_sum_zeroelim(ablen, abdet, cdlen, cddet, deter); + + return deter[deterlen - 1]; +} + +REAL incircleslow(REAL *pa, REAL *pb, REAL *pc, REAL *pd) +{ + INEXACT REAL adx, bdx, cdx, ady, bdy, cdy; + REAL adxtail, bdxtail, cdxtail; + REAL adytail, bdytail, cdytail; + REAL negate, negatetail; + INEXACT REAL axby7, bxcy7, axcy7, bxay7, cxby7, cxay7; + REAL axby[8], bxcy[8], axcy[8], bxay[8], cxby[8], cxay[8]; + REAL temp16[16]; + int temp16len; + REAL detx[32], detxx[64], detxt[32], detxxt[64], detxtxt[64]; + int xlen, xxlen, xtlen, xxtlen, xtxtlen; + REAL x1[128], x2[192]; + int x1len, x2len; + REAL dety[32], detyy[64], detyt[32], detyyt[64], detytyt[64]; + int ylen, yylen, ytlen, yytlen, ytytlen; + REAL y1[128], y2[192]; + int y1len, y2len; + REAL adet[384], bdet[384], cdet[384], abdet[768], deter[1152]; + int alen, blen, clen, ablen, deterlen; + int i; + + INEXACT REAL bvirt; + REAL avirt, bround, around; + INEXACT REAL c; + INEXACT REAL abig; + REAL a0hi, a0lo, a1hi, a1lo, bhi, blo; + REAL err1, err2, err3; + INEXACT REAL _i, _j, _k, _l, _m, _n; + REAL _0, _1, _2; + + Two_Diff(pa[0], pd[0], adx, adxtail); + Two_Diff(pa[1], pd[1], ady, adytail); + Two_Diff(pb[0], pd[0], bdx, bdxtail); + Two_Diff(pb[1], pd[1], bdy, bdytail); + Two_Diff(pc[0], pd[0], cdx, cdxtail); + Two_Diff(pc[1], pd[1], cdy, cdytail); + + Two_Two_Product(adx, adxtail, bdy, bdytail, + axby7, axby[6], axby[5], axby[4], + axby[3], axby[2], axby[1], axby[0]); + axby[7] = axby7; + negate = -ady; + negatetail = -adytail; + Two_Two_Product(bdx, bdxtail, negate, negatetail, + bxay7, bxay[6], bxay[5], bxay[4], + bxay[3], bxay[2], bxay[1], bxay[0]); + bxay[7] = bxay7; + Two_Two_Product(bdx, bdxtail, cdy, cdytail, + bxcy7, bxcy[6], bxcy[5], bxcy[4], + bxcy[3], bxcy[2], bxcy[1], bxcy[0]); + bxcy[7] = bxcy7; + negate = -bdy; + negatetail = -bdytail; + Two_Two_Product(cdx, cdxtail, negate, negatetail, + cxby7, cxby[6], cxby[5], cxby[4], + cxby[3], cxby[2], cxby[1], cxby[0]); + cxby[7] = cxby7; + Two_Two_Product(cdx, cdxtail, ady, adytail, + cxay7, cxay[6], cxay[5], cxay[4], + cxay[3], cxay[2], cxay[1], cxay[0]); + cxay[7] = cxay7; + negate = -cdy; + negatetail = -cdytail; + Two_Two_Product(adx, adxtail, negate, negatetail, + axcy7, axcy[6], axcy[5], axcy[4], + axcy[3], axcy[2], axcy[1], axcy[0]); + axcy[7] = axcy7; + + + temp16len = fast_expansion_sum_zeroelim(8, bxcy, 8, cxby, temp16); + + xlen = scale_expansion_zeroelim(temp16len, temp16, adx, detx); + xxlen = scale_expansion_zeroelim(xlen, detx, adx, detxx); + xtlen = scale_expansion_zeroelim(temp16len, temp16, adxtail, detxt); + xxtlen = scale_expansion_zeroelim(xtlen, detxt, adx, detxxt); + for (i = 0; i < xxtlen; i++) { + detxxt[i] *= 2.0; + } + xtxtlen = scale_expansion_zeroelim(xtlen, detxt, adxtail, detxtxt); + x1len = fast_expansion_sum_zeroelim(xxlen, detxx, xxtlen, detxxt, x1); + x2len = fast_expansion_sum_zeroelim(x1len, x1, xtxtlen, detxtxt, x2); + + ylen = scale_expansion_zeroelim(temp16len, temp16, ady, dety); + yylen = scale_expansion_zeroelim(ylen, dety, ady, detyy); + ytlen = scale_expansion_zeroelim(temp16len, temp16, adytail, detyt); + yytlen = scale_expansion_zeroelim(ytlen, detyt, ady, detyyt); + for (i = 0; i < yytlen; i++) { + detyyt[i] *= 2.0; + } + ytytlen = scale_expansion_zeroelim(ytlen, detyt, adytail, detytyt); + y1len = fast_expansion_sum_zeroelim(yylen, detyy, yytlen, detyyt, y1); + y2len = fast_expansion_sum_zeroelim(y1len, y1, ytytlen, detytyt, y2); + + alen = fast_expansion_sum_zeroelim(x2len, x2, y2len, y2, adet); + + + temp16len = fast_expansion_sum_zeroelim(8, cxay, 8, axcy, temp16); + + xlen = scale_expansion_zeroelim(temp16len, temp16, bdx, detx); + xxlen = scale_expansion_zeroelim(xlen, detx, bdx, detxx); + xtlen = scale_expansion_zeroelim(temp16len, temp16, bdxtail, detxt); + xxtlen = scale_expansion_zeroelim(xtlen, detxt, bdx, detxxt); + for (i = 0; i < xxtlen; i++) { + detxxt[i] *= 2.0; + } + xtxtlen = scale_expansion_zeroelim(xtlen, detxt, bdxtail, detxtxt); + x1len = fast_expansion_sum_zeroelim(xxlen, detxx, xxtlen, detxxt, x1); + x2len = fast_expansion_sum_zeroelim(x1len, x1, xtxtlen, detxtxt, x2); + + ylen = scale_expansion_zeroelim(temp16len, temp16, bdy, dety); + yylen = scale_expansion_zeroelim(ylen, dety, bdy, detyy); + ytlen = scale_expansion_zeroelim(temp16len, temp16, bdytail, detyt); + yytlen = scale_expansion_zeroelim(ytlen, detyt, bdy, detyyt); + for (i = 0; i < yytlen; i++) { + detyyt[i] *= 2.0; + } + ytytlen = scale_expansion_zeroelim(ytlen, detyt, bdytail, detytyt); + y1len = fast_expansion_sum_zeroelim(yylen, detyy, yytlen, detyyt, y1); + y2len = fast_expansion_sum_zeroelim(y1len, y1, ytytlen, detytyt, y2); + + blen = fast_expansion_sum_zeroelim(x2len, x2, y2len, y2, bdet); + + + temp16len = fast_expansion_sum_zeroelim(8, axby, 8, bxay, temp16); + + xlen = scale_expansion_zeroelim(temp16len, temp16, cdx, detx); + xxlen = scale_expansion_zeroelim(xlen, detx, cdx, detxx); + xtlen = scale_expansion_zeroelim(temp16len, temp16, cdxtail, detxt); + xxtlen = scale_expansion_zeroelim(xtlen, detxt, cdx, detxxt); + for (i = 0; i < xxtlen; i++) { + detxxt[i] *= 2.0; + } + xtxtlen = scale_expansion_zeroelim(xtlen, detxt, cdxtail, detxtxt); + x1len = fast_expansion_sum_zeroelim(xxlen, detxx, xxtlen, detxxt, x1); + x2len = fast_expansion_sum_zeroelim(x1len, x1, xtxtlen, detxtxt, x2); + + ylen = scale_expansion_zeroelim(temp16len, temp16, cdy, dety); + yylen = scale_expansion_zeroelim(ylen, dety, cdy, detyy); + ytlen = scale_expansion_zeroelim(temp16len, temp16, cdytail, detyt); + yytlen = scale_expansion_zeroelim(ytlen, detyt, cdy, detyyt); + for (i = 0; i < yytlen; i++) { + detyyt[i] *= 2.0; + } + ytytlen = scale_expansion_zeroelim(ytlen, detyt, cdytail, detytyt); + y1len = fast_expansion_sum_zeroelim(yylen, detyy, yytlen, detyyt, y1); + y2len = fast_expansion_sum_zeroelim(y1len, y1, ytytlen, detytyt, y2); + + clen = fast_expansion_sum_zeroelim(x2len, x2, y2len, y2, cdet); + + ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet); + deterlen = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, deter); + + return deter[deterlen - 1]; +} + +REAL incircleadapt(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL permanent) +{ + INEXACT REAL adx, bdx, cdx, ady, bdy, cdy; + REAL det, errbound; + + INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1; + REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0; + REAL bc[4], ca[4], ab[4]; + INEXACT REAL bc3, ca3, ab3; + REAL axbc[8], axxbc[16], aybc[8], ayybc[16], adet[32]; + int axbclen, axxbclen, aybclen, ayybclen, alen; + REAL bxca[8], bxxca[16], byca[8], byyca[16], bdet[32]; + int bxcalen, bxxcalen, bycalen, byycalen, blen; + REAL cxab[8], cxxab[16], cyab[8], cyyab[16], cdet[32]; + int cxablen, cxxablen, cyablen, cyyablen, clen; + REAL abdet[64]; + int ablen; + REAL fin1[1152], fin2[1152]; + REAL *finnow, *finother, *finswap; + int finlength; + + REAL adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail; + INEXACT REAL adxadx1, adyady1, bdxbdx1, bdybdy1, cdxcdx1, cdycdy1; + REAL adxadx0, adyady0, bdxbdx0, bdybdy0, cdxcdx0, cdycdy0; + REAL aa[4], bb[4], cc[4]; + INEXACT REAL aa3, bb3, cc3; + INEXACT REAL ti1, tj1; + REAL ti0, tj0; + REAL u[4], v[4]; + INEXACT REAL u3, v3; + REAL temp8[8], temp16a[16], temp16b[16], temp16c[16]; + REAL temp32a[32], temp32b[32], temp48[48], temp64[64]; + int temp8len, temp16alen, temp16blen, temp16clen; + int temp32alen, temp32blen, temp48len, temp64len; + REAL axtbb[8], axtcc[8], aytbb[8], aytcc[8]; + int axtbblen, axtcclen, aytbblen, aytcclen; + REAL bxtaa[8], bxtcc[8], bytaa[8], bytcc[8]; + int bxtaalen, bxtcclen, bytaalen, bytcclen; + REAL cxtaa[8], cxtbb[8], cytaa[8], cytbb[8]; + int cxtaalen, cxtbblen, cytaalen, cytbblen; + REAL axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8]; + int axtbclen, aytbclen, bxtcalen, bytcalen, cxtablen, cytablen; + REAL axtbct[16], aytbct[16], bxtcat[16], bytcat[16], cxtabt[16], cytabt[16]; + int axtbctlen, aytbctlen, bxtcatlen, bytcatlen, cxtabtlen, cytabtlen; + REAL axtbctt[8], aytbctt[8], bxtcatt[8]; + REAL bytcatt[8], cxtabtt[8], cytabtt[8]; + int axtbcttlen, aytbcttlen, bxtcattlen, bytcattlen, cxtabttlen, cytabttlen; + REAL abt[8], bct[8], cat[8]; + int abtlen, bctlen, catlen; + REAL abtt[4], bctt[4], catt[4]; + int abttlen, bcttlen, cattlen; + INEXACT REAL abtt3, bctt3, catt3; + REAL negate; + + INEXACT REAL bvirt; + REAL avirt, bround, around; + INEXACT REAL c; + INEXACT REAL abig; + REAL ahi, alo, bhi, blo; + REAL err1, err2, err3; + INEXACT REAL _i, _j; + REAL _0; + + // Avoid compiler warnings. H. Si, 2012-02-16. + axtbclen = aytbclen = bxtcalen = bytcalen = cxtablen = cytablen = 0; + + adx = (REAL) (pa[0] - pd[0]); + bdx = (REAL) (pb[0] - pd[0]); + cdx = (REAL) (pc[0] - pd[0]); + ady = (REAL) (pa[1] - pd[1]); + bdy = (REAL) (pb[1] - pd[1]); + cdy = (REAL) (pc[1] - pd[1]); + + Two_Product(bdx, cdy, bdxcdy1, bdxcdy0); + Two_Product(cdx, bdy, cdxbdy1, cdxbdy0); + Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]); + bc[3] = bc3; + axbclen = scale_expansion_zeroelim(4, bc, adx, axbc); + axxbclen = scale_expansion_zeroelim(axbclen, axbc, adx, axxbc); + aybclen = scale_expansion_zeroelim(4, bc, ady, aybc); + ayybclen = scale_expansion_zeroelim(aybclen, aybc, ady, ayybc); + alen = fast_expansion_sum_zeroelim(axxbclen, axxbc, ayybclen, ayybc, adet); + + Two_Product(cdx, ady, cdxady1, cdxady0); + Two_Product(adx, cdy, adxcdy1, adxcdy0); + Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]); + ca[3] = ca3; + bxcalen = scale_expansion_zeroelim(4, ca, bdx, bxca); + bxxcalen = scale_expansion_zeroelim(bxcalen, bxca, bdx, bxxca); + bycalen = scale_expansion_zeroelim(4, ca, bdy, byca); + byycalen = scale_expansion_zeroelim(bycalen, byca, bdy, byyca); + blen = fast_expansion_sum_zeroelim(bxxcalen, bxxca, byycalen, byyca, bdet); + + Two_Product(adx, bdy, adxbdy1, adxbdy0); + Two_Product(bdx, ady, bdxady1, bdxady0); + Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]); + ab[3] = ab3; + cxablen = scale_expansion_zeroelim(4, ab, cdx, cxab); + cxxablen = scale_expansion_zeroelim(cxablen, cxab, cdx, cxxab); + cyablen = scale_expansion_zeroelim(4, ab, cdy, cyab); + cyyablen = scale_expansion_zeroelim(cyablen, cyab, cdy, cyyab); + clen = fast_expansion_sum_zeroelim(cxxablen, cxxab, cyyablen, cyyab, cdet); + + ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet); + finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1); + + det = estimate(finlength, fin1); + errbound = iccerrboundB * permanent; + if ((det >= errbound) || (-det >= errbound)) { + return det; + } + + Two_Diff_Tail(pa[0], pd[0], adx, adxtail); + Two_Diff_Tail(pa[1], pd[1], ady, adytail); + Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail); + Two_Diff_Tail(pb[1], pd[1], bdy, bdytail); + Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail); + Two_Diff_Tail(pc[1], pd[1], cdy, cdytail); + if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0) + && (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0)) { + return det; + } + + errbound = iccerrboundC * permanent + resulterrbound * Absolute(det); + det += ((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail) + - (bdy * cdxtail + cdx * bdytail)) + + 2.0 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx)) + + ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail) + - (cdy * adxtail + adx * cdytail)) + + 2.0 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx)) + + ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail) + - (ady * bdxtail + bdx * adytail)) + + 2.0 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx)); + if ((det >= errbound) || (-det >= errbound)) { + return det; + } + + finnow = fin1; + finother = fin2; + + if ((bdxtail != 0.0) || (bdytail != 0.0) + || (cdxtail != 0.0) || (cdytail != 0.0)) { + Square(adx, adxadx1, adxadx0); + Square(ady, adyady1, adyady0); + Two_Two_Sum(adxadx1, adxadx0, adyady1, adyady0, aa3, aa[2], aa[1], aa[0]); + aa[3] = aa3; + } + if ((cdxtail != 0.0) || (cdytail != 0.0) + || (adxtail != 0.0) || (adytail != 0.0)) { + Square(bdx, bdxbdx1, bdxbdx0); + Square(bdy, bdybdy1, bdybdy0); + Two_Two_Sum(bdxbdx1, bdxbdx0, bdybdy1, bdybdy0, bb3, bb[2], bb[1], bb[0]); + bb[3] = bb3; + } + if ((adxtail != 0.0) || (adytail != 0.0) + || (bdxtail != 0.0) || (bdytail != 0.0)) { + Square(cdx, cdxcdx1, cdxcdx0); + Square(cdy, cdycdy1, cdycdy0); + Two_Two_Sum(cdxcdx1, cdxcdx0, cdycdy1, cdycdy0, cc3, cc[2], cc[1], cc[0]); + cc[3] = cc3; + } + + if (adxtail != 0.0) { + axtbclen = scale_expansion_zeroelim(4, bc, adxtail, axtbc); + temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, 2.0 * adx, + temp16a); + + axtcclen = scale_expansion_zeroelim(4, cc, adxtail, axtcc); + temp16blen = scale_expansion_zeroelim(axtcclen, axtcc, bdy, temp16b); + + axtbblen = scale_expansion_zeroelim(4, bb, adxtail, axtbb); + temp16clen = scale_expansion_zeroelim(axtbblen, axtbb, -cdy, temp16c); + + temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp16blen, temp16b, temp32a); + temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c, + temp32alen, temp32a, temp48); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, + temp48, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (adytail != 0.0) { + aytbclen = scale_expansion_zeroelim(4, bc, adytail, aytbc); + temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, 2.0 * ady, + temp16a); + + aytbblen = scale_expansion_zeroelim(4, bb, adytail, aytbb); + temp16blen = scale_expansion_zeroelim(aytbblen, aytbb, cdx, temp16b); + + aytcclen = scale_expansion_zeroelim(4, cc, adytail, aytcc); + temp16clen = scale_expansion_zeroelim(aytcclen, aytcc, -bdx, temp16c); + + temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp16blen, temp16b, temp32a); + temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c, + temp32alen, temp32a, temp48); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, + temp48, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (bdxtail != 0.0) { + bxtcalen = scale_expansion_zeroelim(4, ca, bdxtail, bxtca); + temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, 2.0 * bdx, + temp16a); + + bxtaalen = scale_expansion_zeroelim(4, aa, bdxtail, bxtaa); + temp16blen = scale_expansion_zeroelim(bxtaalen, bxtaa, cdy, temp16b); + + bxtcclen = scale_expansion_zeroelim(4, cc, bdxtail, bxtcc); + temp16clen = scale_expansion_zeroelim(bxtcclen, bxtcc, -ady, temp16c); + + temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp16blen, temp16b, temp32a); + temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c, + temp32alen, temp32a, temp48); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, + temp48, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (bdytail != 0.0) { + bytcalen = scale_expansion_zeroelim(4, ca, bdytail, bytca); + temp16alen = scale_expansion_zeroelim(bytcalen, bytca, 2.0 * bdy, + temp16a); + + bytcclen = scale_expansion_zeroelim(4, cc, bdytail, bytcc); + temp16blen = scale_expansion_zeroelim(bytcclen, bytcc, adx, temp16b); + + bytaalen = scale_expansion_zeroelim(4, aa, bdytail, bytaa); + temp16clen = scale_expansion_zeroelim(bytaalen, bytaa, -cdx, temp16c); + + temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp16blen, temp16b, temp32a); + temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c, + temp32alen, temp32a, temp48); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, + temp48, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (cdxtail != 0.0) { + cxtablen = scale_expansion_zeroelim(4, ab, cdxtail, cxtab); + temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, 2.0 * cdx, + temp16a); + + cxtbblen = scale_expansion_zeroelim(4, bb, cdxtail, cxtbb); + temp16blen = scale_expansion_zeroelim(cxtbblen, cxtbb, ady, temp16b); + + cxtaalen = scale_expansion_zeroelim(4, aa, cdxtail, cxtaa); + temp16clen = scale_expansion_zeroelim(cxtaalen, cxtaa, -bdy, temp16c); + + temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp16blen, temp16b, temp32a); + temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c, + temp32alen, temp32a, temp48); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, + temp48, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (cdytail != 0.0) { + cytablen = scale_expansion_zeroelim(4, ab, cdytail, cytab); + temp16alen = scale_expansion_zeroelim(cytablen, cytab, 2.0 * cdy, + temp16a); + + cytaalen = scale_expansion_zeroelim(4, aa, cdytail, cytaa); + temp16blen = scale_expansion_zeroelim(cytaalen, cytaa, bdx, temp16b); + + cytbblen = scale_expansion_zeroelim(4, bb, cdytail, cytbb); + temp16clen = scale_expansion_zeroelim(cytbblen, cytbb, -adx, temp16c); + + temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp16blen, temp16b, temp32a); + temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c, + temp32alen, temp32a, temp48); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, + temp48, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + + if ((adxtail != 0.0) || (adytail != 0.0)) { + if ((bdxtail != 0.0) || (bdytail != 0.0) + || (cdxtail != 0.0) || (cdytail != 0.0)) { + Two_Product(bdxtail, cdy, ti1, ti0); + Two_Product(bdx, cdytail, tj1, tj0); + Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]); + u[3] = u3; + negate = -bdy; + Two_Product(cdxtail, negate, ti1, ti0); + negate = -bdytail; + Two_Product(cdx, negate, tj1, tj0); + Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]); + v[3] = v3; + bctlen = fast_expansion_sum_zeroelim(4, u, 4, v, bct); + + Two_Product(bdxtail, cdytail, ti1, ti0); + Two_Product(cdxtail, bdytail, tj1, tj0); + Two_Two_Diff(ti1, ti0, tj1, tj0, bctt3, bctt[2], bctt[1], bctt[0]); + bctt[3] = bctt3; + bcttlen = 4; + } else { + bct[0] = 0.0; + bctlen = 1; + bctt[0] = 0.0; + bcttlen = 1; + } + + if (adxtail != 0.0) { + temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, adxtail, temp16a); + axtbctlen = scale_expansion_zeroelim(bctlen, bct, adxtail, axtbct); + temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, 2.0 * adx, + temp32a); + temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp32alen, temp32a, temp48); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, + temp48, finother); + finswap = finnow; finnow = finother; finother = finswap; + if (bdytail != 0.0) { + temp8len = scale_expansion_zeroelim(4, cc, adxtail, temp8); + temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail, + temp16a); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen, + temp16a, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (cdytail != 0.0) { + temp8len = scale_expansion_zeroelim(4, bb, -adxtail, temp8); + temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail, + temp16a); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen, + temp16a, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + + temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, adxtail, + temp32a); + axtbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adxtail, axtbctt); + temp16alen = scale_expansion_zeroelim(axtbcttlen, axtbctt, 2.0 * adx, + temp16a); + temp16blen = scale_expansion_zeroelim(axtbcttlen, axtbctt, adxtail, + temp16b); + temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp16blen, temp16b, temp32b); + temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a, + temp32blen, temp32b, temp64); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len, + temp64, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (adytail != 0.0) { + temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, adytail, temp16a); + aytbctlen = scale_expansion_zeroelim(bctlen, bct, adytail, aytbct); + temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, 2.0 * ady, + temp32a); + temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp32alen, temp32a, temp48); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, + temp48, finother); + finswap = finnow; finnow = finother; finother = finswap; + + + temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, adytail, + temp32a); + aytbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adytail, aytbctt); + temp16alen = scale_expansion_zeroelim(aytbcttlen, aytbctt, 2.0 * ady, + temp16a); + temp16blen = scale_expansion_zeroelim(aytbcttlen, aytbctt, adytail, + temp16b); + temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp16blen, temp16b, temp32b); + temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a, + temp32blen, temp32b, temp64); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len, + temp64, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + } + if ((bdxtail != 0.0) || (bdytail != 0.0)) { + if ((cdxtail != 0.0) || (cdytail != 0.0) + || (adxtail != 0.0) || (adytail != 0.0)) { + Two_Product(cdxtail, ady, ti1, ti0); + Two_Product(cdx, adytail, tj1, tj0); + Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]); + u[3] = u3; + negate = -cdy; + Two_Product(adxtail, negate, ti1, ti0); + negate = -cdytail; + Two_Product(adx, negate, tj1, tj0); + Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]); + v[3] = v3; + catlen = fast_expansion_sum_zeroelim(4, u, 4, v, cat); + + Two_Product(cdxtail, adytail, ti1, ti0); + Two_Product(adxtail, cdytail, tj1, tj0); + Two_Two_Diff(ti1, ti0, tj1, tj0, catt3, catt[2], catt[1], catt[0]); + catt[3] = catt3; + cattlen = 4; + } else { + cat[0] = 0.0; + catlen = 1; + catt[0] = 0.0; + cattlen = 1; + } + + if (bdxtail != 0.0) { + temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, bdxtail, temp16a); + bxtcatlen = scale_expansion_zeroelim(catlen, cat, bdxtail, bxtcat); + temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, 2.0 * bdx, + temp32a); + temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp32alen, temp32a, temp48); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, + temp48, finother); + finswap = finnow; finnow = finother; finother = finswap; + if (cdytail != 0.0) { + temp8len = scale_expansion_zeroelim(4, aa, bdxtail, temp8); + temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail, + temp16a); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen, + temp16a, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (adytail != 0.0) { + temp8len = scale_expansion_zeroelim(4, cc, -bdxtail, temp8); + temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail, + temp16a); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen, + temp16a, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + + temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, bdxtail, + temp32a); + bxtcattlen = scale_expansion_zeroelim(cattlen, catt, bdxtail, bxtcatt); + temp16alen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, 2.0 * bdx, + temp16a); + temp16blen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, bdxtail, + temp16b); + temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp16blen, temp16b, temp32b); + temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a, + temp32blen, temp32b, temp64); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len, + temp64, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (bdytail != 0.0) { + temp16alen = scale_expansion_zeroelim(bytcalen, bytca, bdytail, temp16a); + bytcatlen = scale_expansion_zeroelim(catlen, cat, bdytail, bytcat); + temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, 2.0 * bdy, + temp32a); + temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp32alen, temp32a, temp48); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, + temp48, finother); + finswap = finnow; finnow = finother; finother = finswap; + + + temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, bdytail, + temp32a); + bytcattlen = scale_expansion_zeroelim(cattlen, catt, bdytail, bytcatt); + temp16alen = scale_expansion_zeroelim(bytcattlen, bytcatt, 2.0 * bdy, + temp16a); + temp16blen = scale_expansion_zeroelim(bytcattlen, bytcatt, bdytail, + temp16b); + temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp16blen, temp16b, temp32b); + temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a, + temp32blen, temp32b, temp64); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len, + temp64, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + } + if ((cdxtail != 0.0) || (cdytail != 0.0)) { + if ((adxtail != 0.0) || (adytail != 0.0) + || (bdxtail != 0.0) || (bdytail != 0.0)) { + Two_Product(adxtail, bdy, ti1, ti0); + Two_Product(adx, bdytail, tj1, tj0); + Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]); + u[3] = u3; + negate = -ady; + Two_Product(bdxtail, negate, ti1, ti0); + negate = -adytail; + Two_Product(bdx, negate, tj1, tj0); + Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]); + v[3] = v3; + abtlen = fast_expansion_sum_zeroelim(4, u, 4, v, abt); + + Two_Product(adxtail, bdytail, ti1, ti0); + Two_Product(bdxtail, adytail, tj1, tj0); + Two_Two_Diff(ti1, ti0, tj1, tj0, abtt3, abtt[2], abtt[1], abtt[0]); + abtt[3] = abtt3; + abttlen = 4; + } else { + abt[0] = 0.0; + abtlen = 1; + abtt[0] = 0.0; + abttlen = 1; + } + + if (cdxtail != 0.0) { + temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, cdxtail, temp16a); + cxtabtlen = scale_expansion_zeroelim(abtlen, abt, cdxtail, cxtabt); + temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, 2.0 * cdx, + temp32a); + temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp32alen, temp32a, temp48); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, + temp48, finother); + finswap = finnow; finnow = finother; finother = finswap; + if (adytail != 0.0) { + temp8len = scale_expansion_zeroelim(4, bb, cdxtail, temp8); + temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail, + temp16a); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen, + temp16a, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (bdytail != 0.0) { + temp8len = scale_expansion_zeroelim(4, aa, -cdxtail, temp8); + temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail, + temp16a); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen, + temp16a, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + + temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, cdxtail, + temp32a); + cxtabttlen = scale_expansion_zeroelim(abttlen, abtt, cdxtail, cxtabtt); + temp16alen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, 2.0 * cdx, + temp16a); + temp16blen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, cdxtail, + temp16b); + temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp16blen, temp16b, temp32b); + temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a, + temp32blen, temp32b, temp64); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len, + temp64, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + if (cdytail != 0.0) { + temp16alen = scale_expansion_zeroelim(cytablen, cytab, cdytail, temp16a); + cytabtlen = scale_expansion_zeroelim(abtlen, abt, cdytail, cytabt); + temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, 2.0 * cdy, + temp32a); + temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp32alen, temp32a, temp48); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, + temp48, finother); + finswap = finnow; finnow = finother; finother = finswap; + + + temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, cdytail, + temp32a); + cytabttlen = scale_expansion_zeroelim(abttlen, abtt, cdytail, cytabtt); + temp16alen = scale_expansion_zeroelim(cytabttlen, cytabtt, 2.0 * cdy, + temp16a); + temp16blen = scale_expansion_zeroelim(cytabttlen, cytabtt, cdytail, + temp16b); + temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a, + temp16blen, temp16b, temp32b); + temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a, + temp32blen, temp32b, temp64); + finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len, + temp64, finother); + finswap = finnow; finnow = finother; finother = finswap; + } + } + + return finnow[finlength - 1]; +} + +REAL incircle(REAL *pa, REAL *pb, REAL *pc, REAL *pd) +{ + REAL adx, bdx, cdx, ady, bdy, cdy; + REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady; + REAL alift, blift, clift; + REAL det; + REAL permanent, errbound; + + adx = pa[0] - pd[0]; + bdx = pb[0] - pd[0]; + cdx = pc[0] - pd[0]; + ady = pa[1] - pd[1]; + bdy = pb[1] - pd[1]; + cdy = pc[1] - pd[1]; + + bdxcdy = bdx * cdy; + cdxbdy = cdx * bdy; + alift = adx * adx + ady * ady; + + cdxady = cdx * ady; + adxcdy = adx * cdy; + blift = bdx * bdx + bdy * bdy; + + adxbdy = adx * bdy; + bdxady = bdx * ady; + clift = cdx * cdx + cdy * cdy; + + det = alift * (bdxcdy - cdxbdy) + + blift * (cdxady - adxcdy) + + clift * (adxbdy - bdxady); + + permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * alift + + (Absolute(cdxady) + Absolute(adxcdy)) * blift + + (Absolute(adxbdy) + Absolute(bdxady)) * clift; + errbound = iccerrboundA * permanent; + if ((det > errbound) || (-det > errbound)) { + return det; + } + + return incircleadapt(pa, pb, pc, pd, permanent); +} + +/*****************************************************************************/ +/* */ +/* inspherefast() Approximate 3D insphere test. Nonrobust. */ +/* insphereexact() Exact 3D insphere test. Robust. */ +/* insphereslow() Another exact 3D insphere test. Robust. */ +/* insphere() Adaptive exact 3D insphere test. Robust. */ +/* */ +/* Return a positive value if the point pe lies inside the */ +/* sphere passing through pa, pb, pc, and pd; a negative value */ +/* if it lies outside; and zero if the five points are */ +/* cospherical. The points pa, pb, pc, and pd must be ordered */ +/* so that they have a positive orientation (as defined by */ +/* orient3d()), or the sign of the result will be reversed. */ +/* */ +/* Only the first and last routine should be used; the middle two are for */ +/* timings. */ +/* */ +/* The last three use exact arithmetic to ensure a correct answer. The */ +/* result returned is the determinant of a matrix. In insphere() only, */ +/* this determinant is computed adaptively, in the sense that exact */ +/* arithmetic is used only to the degree it is needed to ensure that the */ +/* returned value has the correct sign. Hence, insphere() is usually quite */ +/* fast, but will run more slowly when the input points are cospherical or */ +/* nearly so. */ +/* */ +/*****************************************************************************/ + +REAL inspherefast(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe) +{ + REAL aex, bex, cex, dex; + REAL aey, bey, cey, dey; + REAL aez, bez, cez, dez; + REAL alift, blift, clift, dlift; + REAL ab, bc, cd, da, ac, bd; + REAL abc, bcd, cda, dab; + + aex = pa[0] - pe[0]; + bex = pb[0] - pe[0]; + cex = pc[0] - pe[0]; + dex = pd[0] - pe[0]; + aey = pa[1] - pe[1]; + bey = pb[1] - pe[1]; + cey = pc[1] - pe[1]; + dey = pd[1] - pe[1]; + aez = pa[2] - pe[2]; + bez = pb[2] - pe[2]; + cez = pc[2] - pe[2]; + dez = pd[2] - pe[2]; + + ab = aex * bey - bex * aey; + bc = bex * cey - cex * bey; + cd = cex * dey - dex * cey; + da = dex * aey - aex * dey; + + ac = aex * cey - cex * aey; + bd = bex * dey - dex * bey; + + abc = aez * bc - bez * ac + cez * ab; + bcd = bez * cd - cez * bd + dez * bc; + cda = cez * da + dez * ac + aez * cd; + dab = dez * ab + aez * bd + bez * da; + + alift = aex * aex + aey * aey + aez * aez; + blift = bex * bex + bey * bey + bez * bez; + clift = cex * cex + cey * cey + cez * cez; + dlift = dex * dex + dey * dey + dez * dez; + + return (dlift * abc - clift * dab) + (blift * cda - alift * bcd); +} + +REAL insphereexact(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe) +{ + INEXACT REAL axby1, bxcy1, cxdy1, dxey1, exay1; + INEXACT REAL bxay1, cxby1, dxcy1, exdy1, axey1; + INEXACT REAL axcy1, bxdy1, cxey1, dxay1, exby1; + INEXACT REAL cxay1, dxby1, excy1, axdy1, bxey1; + REAL axby0, bxcy0, cxdy0, dxey0, exay0; + REAL bxay0, cxby0, dxcy0, exdy0, axey0; + REAL axcy0, bxdy0, cxey0, dxay0, exby0; + REAL cxay0, dxby0, excy0, axdy0, bxey0; + REAL ab[4], bc[4], cd[4], de[4], ea[4]; + REAL ac[4], bd[4], ce[4], da[4], eb[4]; + REAL temp8a[8], temp8b[8], temp16[16]; + int temp8alen, temp8blen, temp16len; + REAL abc[24], bcd[24], cde[24], dea[24], eab[24]; + REAL abd[24], bce[24], cda[24], deb[24], eac[24]; + int abclen, bcdlen, cdelen, dealen, eablen; + int abdlen, bcelen, cdalen, deblen, eaclen; + REAL temp48a[48], temp48b[48]; + int temp48alen, temp48blen; + REAL abcd[96], bcde[96], cdea[96], deab[96], eabc[96]; + int abcdlen, bcdelen, cdealen, deablen, eabclen; + REAL temp192[192]; + REAL det384x[384], det384y[384], det384z[384]; + int xlen, ylen, zlen; + REAL detxy[768]; + int xylen; + REAL adet[1152], bdet[1152], cdet[1152], ddet[1152], edet[1152]; + int alen, blen, clen, dlen, elen; + REAL abdet[2304], cddet[2304], cdedet[3456]; + int ablen, cdlen; + REAL deter[5760]; + int deterlen; + int i; + + INEXACT REAL bvirt; + REAL avirt, bround, around; + INEXACT REAL c; + INEXACT REAL abig; + REAL ahi, alo, bhi, blo; + REAL err1, err2, err3; + INEXACT REAL _i, _j; + REAL _0; + + + Two_Product(pa[0], pb[1], axby1, axby0); + Two_Product(pb[0], pa[1], bxay1, bxay0); + Two_Two_Diff(axby1, axby0, bxay1, bxay0, ab[3], ab[2], ab[1], ab[0]); + + Two_Product(pb[0], pc[1], bxcy1, bxcy0); + Two_Product(pc[0], pb[1], cxby1, cxby0); + Two_Two_Diff(bxcy1, bxcy0, cxby1, cxby0, bc[3], bc[2], bc[1], bc[0]); + + Two_Product(pc[0], pd[1], cxdy1, cxdy0); + Two_Product(pd[0], pc[1], dxcy1, dxcy0); + Two_Two_Diff(cxdy1, cxdy0, dxcy1, dxcy0, cd[3], cd[2], cd[1], cd[0]); + + Two_Product(pd[0], pe[1], dxey1, dxey0); + Two_Product(pe[0], pd[1], exdy1, exdy0); + Two_Two_Diff(dxey1, dxey0, exdy1, exdy0, de[3], de[2], de[1], de[0]); + + Two_Product(pe[0], pa[1], exay1, exay0); + Two_Product(pa[0], pe[1], axey1, axey0); + Two_Two_Diff(exay1, exay0, axey1, axey0, ea[3], ea[2], ea[1], ea[0]); + + Two_Product(pa[0], pc[1], axcy1, axcy0); + Two_Product(pc[0], pa[1], cxay1, cxay0); + Two_Two_Diff(axcy1, axcy0, cxay1, cxay0, ac[3], ac[2], ac[1], ac[0]); + + Two_Product(pb[0], pd[1], bxdy1, bxdy0); + Two_Product(pd[0], pb[1], dxby1, dxby0); + Two_Two_Diff(bxdy1, bxdy0, dxby1, dxby0, bd[3], bd[2], bd[1], bd[0]); + + Two_Product(pc[0], pe[1], cxey1, cxey0); + Two_Product(pe[0], pc[1], excy1, excy0); + Two_Two_Diff(cxey1, cxey0, excy1, excy0, ce[3], ce[2], ce[1], ce[0]); + + Two_Product(pd[0], pa[1], dxay1, dxay0); + Two_Product(pa[0], pd[1], axdy1, axdy0); + Two_Two_Diff(dxay1, dxay0, axdy1, axdy0, da[3], da[2], da[1], da[0]); + + Two_Product(pe[0], pb[1], exby1, exby0); + Two_Product(pb[0], pe[1], bxey1, bxey0); + Two_Two_Diff(exby1, exby0, bxey1, bxey0, eb[3], eb[2], eb[1], eb[0]); + + temp8alen = scale_expansion_zeroelim(4, bc, pa[2], temp8a); + temp8blen = scale_expansion_zeroelim(4, ac, -pb[2], temp8b); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b, + temp16); + temp8alen = scale_expansion_zeroelim(4, ab, pc[2], temp8a); + abclen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16, + abc); + + temp8alen = scale_expansion_zeroelim(4, cd, pb[2], temp8a); + temp8blen = scale_expansion_zeroelim(4, bd, -pc[2], temp8b); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b, + temp16); + temp8alen = scale_expansion_zeroelim(4, bc, pd[2], temp8a); + bcdlen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16, + bcd); + + temp8alen = scale_expansion_zeroelim(4, de, pc[2], temp8a); + temp8blen = scale_expansion_zeroelim(4, ce, -pd[2], temp8b); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b, + temp16); + temp8alen = scale_expansion_zeroelim(4, cd, pe[2], temp8a); + cdelen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16, + cde); + + temp8alen = scale_expansion_zeroelim(4, ea, pd[2], temp8a); + temp8blen = scale_expansion_zeroelim(4, da, -pe[2], temp8b); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b, + temp16); + temp8alen = scale_expansion_zeroelim(4, de, pa[2], temp8a); + dealen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16, + dea); + + temp8alen = scale_expansion_zeroelim(4, ab, pe[2], temp8a); + temp8blen = scale_expansion_zeroelim(4, eb, -pa[2], temp8b); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b, + temp16); + temp8alen = scale_expansion_zeroelim(4, ea, pb[2], temp8a); + eablen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16, + eab); + + temp8alen = scale_expansion_zeroelim(4, bd, pa[2], temp8a); + temp8blen = scale_expansion_zeroelim(4, da, pb[2], temp8b); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b, + temp16); + temp8alen = scale_expansion_zeroelim(4, ab, pd[2], temp8a); + abdlen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16, + abd); + + temp8alen = scale_expansion_zeroelim(4, ce, pb[2], temp8a); + temp8blen = scale_expansion_zeroelim(4, eb, pc[2], temp8b); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b, + temp16); + temp8alen = scale_expansion_zeroelim(4, bc, pe[2], temp8a); + bcelen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16, + bce); + + temp8alen = scale_expansion_zeroelim(4, da, pc[2], temp8a); + temp8blen = scale_expansion_zeroelim(4, ac, pd[2], temp8b); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b, + temp16); + temp8alen = scale_expansion_zeroelim(4, cd, pa[2], temp8a); + cdalen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16, + cda); + + temp8alen = scale_expansion_zeroelim(4, eb, pd[2], temp8a); + temp8blen = scale_expansion_zeroelim(4, bd, pe[2], temp8b); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b, + temp16); + temp8alen = scale_expansion_zeroelim(4, de, pb[2], temp8a); + deblen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16, + deb); + + temp8alen = scale_expansion_zeroelim(4, ac, pe[2], temp8a); + temp8blen = scale_expansion_zeroelim(4, ce, pa[2], temp8b); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b, + temp16); + temp8alen = scale_expansion_zeroelim(4, ea, pc[2], temp8a); + eaclen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16, + eac); + + temp48alen = fast_expansion_sum_zeroelim(cdelen, cde, bcelen, bce, temp48a); + temp48blen = fast_expansion_sum_zeroelim(deblen, deb, bcdlen, bcd, temp48b); + for (i = 0; i < temp48blen; i++) { + temp48b[i] = -temp48b[i]; + } + bcdelen = fast_expansion_sum_zeroelim(temp48alen, temp48a, + temp48blen, temp48b, bcde); + xlen = scale_expansion_zeroelim(bcdelen, bcde, pa[0], temp192); + xlen = scale_expansion_zeroelim(xlen, temp192, pa[0], det384x); + ylen = scale_expansion_zeroelim(bcdelen, bcde, pa[1], temp192); + ylen = scale_expansion_zeroelim(ylen, temp192, pa[1], det384y); + zlen = scale_expansion_zeroelim(bcdelen, bcde, pa[2], temp192); + zlen = scale_expansion_zeroelim(zlen, temp192, pa[2], det384z); + xylen = fast_expansion_sum_zeroelim(xlen, det384x, ylen, det384y, detxy); + alen = fast_expansion_sum_zeroelim(xylen, detxy, zlen, det384z, adet); + + temp48alen = fast_expansion_sum_zeroelim(dealen, dea, cdalen, cda, temp48a); + temp48blen = fast_expansion_sum_zeroelim(eaclen, eac, cdelen, cde, temp48b); + for (i = 0; i < temp48blen; i++) { + temp48b[i] = -temp48b[i]; + } + cdealen = fast_expansion_sum_zeroelim(temp48alen, temp48a, + temp48blen, temp48b, cdea); + xlen = scale_expansion_zeroelim(cdealen, cdea, pb[0], temp192); + xlen = scale_expansion_zeroelim(xlen, temp192, pb[0], det384x); + ylen = scale_expansion_zeroelim(cdealen, cdea, pb[1], temp192); + ylen = scale_expansion_zeroelim(ylen, temp192, pb[1], det384y); + zlen = scale_expansion_zeroelim(cdealen, cdea, pb[2], temp192); + zlen = scale_expansion_zeroelim(zlen, temp192, pb[2], det384z); + xylen = fast_expansion_sum_zeroelim(xlen, det384x, ylen, det384y, detxy); + blen = fast_expansion_sum_zeroelim(xylen, detxy, zlen, det384z, bdet); + + temp48alen = fast_expansion_sum_zeroelim(eablen, eab, deblen, deb, temp48a); + temp48blen = fast_expansion_sum_zeroelim(abdlen, abd, dealen, dea, temp48b); + for (i = 0; i < temp48blen; i++) { + temp48b[i] = -temp48b[i]; + } + deablen = fast_expansion_sum_zeroelim(temp48alen, temp48a, + temp48blen, temp48b, deab); + xlen = scale_expansion_zeroelim(deablen, deab, pc[0], temp192); + xlen = scale_expansion_zeroelim(xlen, temp192, pc[0], det384x); + ylen = scale_expansion_zeroelim(deablen, deab, pc[1], temp192); + ylen = scale_expansion_zeroelim(ylen, temp192, pc[1], det384y); + zlen = scale_expansion_zeroelim(deablen, deab, pc[2], temp192); + zlen = scale_expansion_zeroelim(zlen, temp192, pc[2], det384z); + xylen = fast_expansion_sum_zeroelim(xlen, det384x, ylen, det384y, detxy); + clen = fast_expansion_sum_zeroelim(xylen, detxy, zlen, det384z, cdet); + + temp48alen = fast_expansion_sum_zeroelim(abclen, abc, eaclen, eac, temp48a); + temp48blen = fast_expansion_sum_zeroelim(bcelen, bce, eablen, eab, temp48b); + for (i = 0; i < temp48blen; i++) { + temp48b[i] = -temp48b[i]; + } + eabclen = fast_expansion_sum_zeroelim(temp48alen, temp48a, + temp48blen, temp48b, eabc); + xlen = scale_expansion_zeroelim(eabclen, eabc, pd[0], temp192); + xlen = scale_expansion_zeroelim(xlen, temp192, pd[0], det384x); + ylen = scale_expansion_zeroelim(eabclen, eabc, pd[1], temp192); + ylen = scale_expansion_zeroelim(ylen, temp192, pd[1], det384y); + zlen = scale_expansion_zeroelim(eabclen, eabc, pd[2], temp192); + zlen = scale_expansion_zeroelim(zlen, temp192, pd[2], det384z); + xylen = fast_expansion_sum_zeroelim(xlen, det384x, ylen, det384y, detxy); + dlen = fast_expansion_sum_zeroelim(xylen, detxy, zlen, det384z, ddet); + + temp48alen = fast_expansion_sum_zeroelim(bcdlen, bcd, abdlen, abd, temp48a); + temp48blen = fast_expansion_sum_zeroelim(cdalen, cda, abclen, abc, temp48b); + for (i = 0; i < temp48blen; i++) { + temp48b[i] = -temp48b[i]; + } + abcdlen = fast_expansion_sum_zeroelim(temp48alen, temp48a, + temp48blen, temp48b, abcd); + xlen = scale_expansion_zeroelim(abcdlen, abcd, pe[0], temp192); + xlen = scale_expansion_zeroelim(xlen, temp192, pe[0], det384x); + ylen = scale_expansion_zeroelim(abcdlen, abcd, pe[1], temp192); + ylen = scale_expansion_zeroelim(ylen, temp192, pe[1], det384y); + zlen = scale_expansion_zeroelim(abcdlen, abcd, pe[2], temp192); + zlen = scale_expansion_zeroelim(zlen, temp192, pe[2], det384z); + xylen = fast_expansion_sum_zeroelim(xlen, det384x, ylen, det384y, detxy); + elen = fast_expansion_sum_zeroelim(xylen, detxy, zlen, det384z, edet); + + ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet); + cdlen = fast_expansion_sum_zeroelim(clen, cdet, dlen, ddet, cddet); + cdelen = fast_expansion_sum_zeroelim(cdlen, cddet, elen, edet, cdedet); + deterlen = fast_expansion_sum_zeroelim(ablen, abdet, cdelen, cdedet, deter); + + return deter[deterlen - 1]; +} + +REAL insphereslow(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe) +{ + INEXACT REAL aex, bex, cex, dex, aey, bey, cey, dey, aez, bez, cez, dez; + REAL aextail, bextail, cextail, dextail; + REAL aeytail, beytail, ceytail, deytail; + REAL aeztail, beztail, ceztail, deztail; + REAL negate, negatetail; + INEXACT REAL axby7, bxcy7, cxdy7, dxay7, axcy7, bxdy7; + INEXACT REAL bxay7, cxby7, dxcy7, axdy7, cxay7, dxby7; + REAL axby[8], bxcy[8], cxdy[8], dxay[8], axcy[8], bxdy[8]; + REAL bxay[8], cxby[8], dxcy[8], axdy[8], cxay[8], dxby[8]; + REAL ab[16], bc[16], cd[16], da[16], ac[16], bd[16]; + int ablen, bclen, cdlen, dalen, aclen, bdlen; + REAL temp32a[32], temp32b[32], temp64a[64], temp64b[64], temp64c[64]; + int temp32alen, temp32blen, temp64alen, temp64blen, temp64clen; + REAL temp128[128], temp192[192]; + int temp128len, temp192len; + REAL detx[384], detxx[768], detxt[384], detxxt[768], detxtxt[768]; + int xlen, xxlen, xtlen, xxtlen, xtxtlen; + REAL x1[1536], x2[2304]; + int x1len, x2len; + REAL dety[384], detyy[768], detyt[384], detyyt[768], detytyt[768]; + int ylen, yylen, ytlen, yytlen, ytytlen; + REAL y1[1536], y2[2304]; + int y1len, y2len; + REAL detz[384], detzz[768], detzt[384], detzzt[768], detztzt[768]; + int zlen, zzlen, ztlen, zztlen, ztztlen; + REAL z1[1536], z2[2304]; + int z1len, z2len; + REAL detxy[4608]; + int xylen; + REAL adet[6912], bdet[6912], cdet[6912], ddet[6912]; + int alen, blen, clen, dlen; + REAL abdet[13824], cddet[13824], deter[27648]; + int deterlen; + int i; + + INEXACT REAL bvirt; + REAL avirt, bround, around; + INEXACT REAL c; + INEXACT REAL abig; + REAL a0hi, a0lo, a1hi, a1lo, bhi, blo; + REAL err1, err2, err3; + INEXACT REAL _i, _j, _k, _l, _m, _n; + REAL _0, _1, _2; + + Two_Diff(pa[0], pe[0], aex, aextail); + Two_Diff(pa[1], pe[1], aey, aeytail); + Two_Diff(pa[2], pe[2], aez, aeztail); + Two_Diff(pb[0], pe[0], bex, bextail); + Two_Diff(pb[1], pe[1], bey, beytail); + Two_Diff(pb[2], pe[2], bez, beztail); + Two_Diff(pc[0], pe[0], cex, cextail); + Two_Diff(pc[1], pe[1], cey, ceytail); + Two_Diff(pc[2], pe[2], cez, ceztail); + Two_Diff(pd[0], pe[0], dex, dextail); + Two_Diff(pd[1], pe[1], dey, deytail); + Two_Diff(pd[2], pe[2], dez, deztail); + + Two_Two_Product(aex, aextail, bey, beytail, + axby7, axby[6], axby[5], axby[4], + axby[3], axby[2], axby[1], axby[0]); + axby[7] = axby7; + negate = -aey; + negatetail = -aeytail; + Two_Two_Product(bex, bextail, negate, negatetail, + bxay7, bxay[6], bxay[5], bxay[4], + bxay[3], bxay[2], bxay[1], bxay[0]); + bxay[7] = bxay7; + ablen = fast_expansion_sum_zeroelim(8, axby, 8, bxay, ab); + Two_Two_Product(bex, bextail, cey, ceytail, + bxcy7, bxcy[6], bxcy[5], bxcy[4], + bxcy[3], bxcy[2], bxcy[1], bxcy[0]); + bxcy[7] = bxcy7; + negate = -bey; + negatetail = -beytail; + Two_Two_Product(cex, cextail, negate, negatetail, + cxby7, cxby[6], cxby[5], cxby[4], + cxby[3], cxby[2], cxby[1], cxby[0]); + cxby[7] = cxby7; + bclen = fast_expansion_sum_zeroelim(8, bxcy, 8, cxby, bc); + Two_Two_Product(cex, cextail, dey, deytail, + cxdy7, cxdy[6], cxdy[5], cxdy[4], + cxdy[3], cxdy[2], cxdy[1], cxdy[0]); + cxdy[7] = cxdy7; + negate = -cey; + negatetail = -ceytail; + Two_Two_Product(dex, dextail, negate, negatetail, + dxcy7, dxcy[6], dxcy[5], dxcy[4], + dxcy[3], dxcy[2], dxcy[1], dxcy[0]); + dxcy[7] = dxcy7; + cdlen = fast_expansion_sum_zeroelim(8, cxdy, 8, dxcy, cd); + Two_Two_Product(dex, dextail, aey, aeytail, + dxay7, dxay[6], dxay[5], dxay[4], + dxay[3], dxay[2], dxay[1], dxay[0]); + dxay[7] = dxay7; + negate = -dey; + negatetail = -deytail; + Two_Two_Product(aex, aextail, negate, negatetail, + axdy7, axdy[6], axdy[5], axdy[4], + axdy[3], axdy[2], axdy[1], axdy[0]); + axdy[7] = axdy7; + dalen = fast_expansion_sum_zeroelim(8, dxay, 8, axdy, da); + Two_Two_Product(aex, aextail, cey, ceytail, + axcy7, axcy[6], axcy[5], axcy[4], + axcy[3], axcy[2], axcy[1], axcy[0]); + axcy[7] = axcy7; + negate = -aey; + negatetail = -aeytail; + Two_Two_Product(cex, cextail, negate, negatetail, + cxay7, cxay[6], cxay[5], cxay[4], + cxay[3], cxay[2], cxay[1], cxay[0]); + cxay[7] = cxay7; + aclen = fast_expansion_sum_zeroelim(8, axcy, 8, cxay, ac); + Two_Two_Product(bex, bextail, dey, deytail, + bxdy7, bxdy[6], bxdy[5], bxdy[4], + bxdy[3], bxdy[2], bxdy[1], bxdy[0]); + bxdy[7] = bxdy7; + negate = -bey; + negatetail = -beytail; + Two_Two_Product(dex, dextail, negate, negatetail, + dxby7, dxby[6], dxby[5], dxby[4], + dxby[3], dxby[2], dxby[1], dxby[0]); + dxby[7] = dxby7; + bdlen = fast_expansion_sum_zeroelim(8, bxdy, 8, dxby, bd); + + temp32alen = scale_expansion_zeroelim(cdlen, cd, -bez, temp32a); + temp32blen = scale_expansion_zeroelim(cdlen, cd, -beztail, temp32b); + temp64alen = fast_expansion_sum_zeroelim(temp32alen, temp32a, + temp32blen, temp32b, temp64a); + temp32alen = scale_expansion_zeroelim(bdlen, bd, cez, temp32a); + temp32blen = scale_expansion_zeroelim(bdlen, bd, ceztail, temp32b); + temp64blen = fast_expansion_sum_zeroelim(temp32alen, temp32a, + temp32blen, temp32b, temp64b); + temp32alen = scale_expansion_zeroelim(bclen, bc, -dez, temp32a); + temp32blen = scale_expansion_zeroelim(bclen, bc, -deztail, temp32b); + temp64clen = fast_expansion_sum_zeroelim(temp32alen, temp32a, + temp32blen, temp32b, temp64c); + temp128len = fast_expansion_sum_zeroelim(temp64alen, temp64a, + temp64blen, temp64b, temp128); + temp192len = fast_expansion_sum_zeroelim(temp64clen, temp64c, + temp128len, temp128, temp192); + xlen = scale_expansion_zeroelim(temp192len, temp192, aex, detx); + xxlen = scale_expansion_zeroelim(xlen, detx, aex, detxx); + xtlen = scale_expansion_zeroelim(temp192len, temp192, aextail, detxt); + xxtlen = scale_expansion_zeroelim(xtlen, detxt, aex, detxxt); + for (i = 0; i < xxtlen; i++) { + detxxt[i] *= 2.0; + } + xtxtlen = scale_expansion_zeroelim(xtlen, detxt, aextail, detxtxt); + x1len = fast_expansion_sum_zeroelim(xxlen, detxx, xxtlen, detxxt, x1); + x2len = fast_expansion_sum_zeroelim(x1len, x1, xtxtlen, detxtxt, x2); + ylen = scale_expansion_zeroelim(temp192len, temp192, aey, dety); + yylen = scale_expansion_zeroelim(ylen, dety, aey, detyy); + ytlen = scale_expansion_zeroelim(temp192len, temp192, aeytail, detyt); + yytlen = scale_expansion_zeroelim(ytlen, detyt, aey, detyyt); + for (i = 0; i < yytlen; i++) { + detyyt[i] *= 2.0; + } + ytytlen = scale_expansion_zeroelim(ytlen, detyt, aeytail, detytyt); + y1len = fast_expansion_sum_zeroelim(yylen, detyy, yytlen, detyyt, y1); + y2len = fast_expansion_sum_zeroelim(y1len, y1, ytytlen, detytyt, y2); + zlen = scale_expansion_zeroelim(temp192len, temp192, aez, detz); + zzlen = scale_expansion_zeroelim(zlen, detz, aez, detzz); + ztlen = scale_expansion_zeroelim(temp192len, temp192, aeztail, detzt); + zztlen = scale_expansion_zeroelim(ztlen, detzt, aez, detzzt); + for (i = 0; i < zztlen; i++) { + detzzt[i] *= 2.0; + } + ztztlen = scale_expansion_zeroelim(ztlen, detzt, aeztail, detztzt); + z1len = fast_expansion_sum_zeroelim(zzlen, detzz, zztlen, detzzt, z1); + z2len = fast_expansion_sum_zeroelim(z1len, z1, ztztlen, detztzt, z2); + xylen = fast_expansion_sum_zeroelim(x2len, x2, y2len, y2, detxy); + alen = fast_expansion_sum_zeroelim(z2len, z2, xylen, detxy, adet); + + temp32alen = scale_expansion_zeroelim(dalen, da, cez, temp32a); + temp32blen = scale_expansion_zeroelim(dalen, da, ceztail, temp32b); + temp64alen = fast_expansion_sum_zeroelim(temp32alen, temp32a, + temp32blen, temp32b, temp64a); + temp32alen = scale_expansion_zeroelim(aclen, ac, dez, temp32a); + temp32blen = scale_expansion_zeroelim(aclen, ac, deztail, temp32b); + temp64blen = fast_expansion_sum_zeroelim(temp32alen, temp32a, + temp32blen, temp32b, temp64b); + temp32alen = scale_expansion_zeroelim(cdlen, cd, aez, temp32a); + temp32blen = scale_expansion_zeroelim(cdlen, cd, aeztail, temp32b); + temp64clen = fast_expansion_sum_zeroelim(temp32alen, temp32a, + temp32blen, temp32b, temp64c); + temp128len = fast_expansion_sum_zeroelim(temp64alen, temp64a, + temp64blen, temp64b, temp128); + temp192len = fast_expansion_sum_zeroelim(temp64clen, temp64c, + temp128len, temp128, temp192); + xlen = scale_expansion_zeroelim(temp192len, temp192, bex, detx); + xxlen = scale_expansion_zeroelim(xlen, detx, bex, detxx); + xtlen = scale_expansion_zeroelim(temp192len, temp192, bextail, detxt); + xxtlen = scale_expansion_zeroelim(xtlen, detxt, bex, detxxt); + for (i = 0; i < xxtlen; i++) { + detxxt[i] *= 2.0; + } + xtxtlen = scale_expansion_zeroelim(xtlen, detxt, bextail, detxtxt); + x1len = fast_expansion_sum_zeroelim(xxlen, detxx, xxtlen, detxxt, x1); + x2len = fast_expansion_sum_zeroelim(x1len, x1, xtxtlen, detxtxt, x2); + ylen = scale_expansion_zeroelim(temp192len, temp192, bey, dety); + yylen = scale_expansion_zeroelim(ylen, dety, bey, detyy); + ytlen = scale_expansion_zeroelim(temp192len, temp192, beytail, detyt); + yytlen = scale_expansion_zeroelim(ytlen, detyt, bey, detyyt); + for (i = 0; i < yytlen; i++) { + detyyt[i] *= 2.0; + } + ytytlen = scale_expansion_zeroelim(ytlen, detyt, beytail, detytyt); + y1len = fast_expansion_sum_zeroelim(yylen, detyy, yytlen, detyyt, y1); + y2len = fast_expansion_sum_zeroelim(y1len, y1, ytytlen, detytyt, y2); + zlen = scale_expansion_zeroelim(temp192len, temp192, bez, detz); + zzlen = scale_expansion_zeroelim(zlen, detz, bez, detzz); + ztlen = scale_expansion_zeroelim(temp192len, temp192, beztail, detzt); + zztlen = scale_expansion_zeroelim(ztlen, detzt, bez, detzzt); + for (i = 0; i < zztlen; i++) { + detzzt[i] *= 2.0; + } + ztztlen = scale_expansion_zeroelim(ztlen, detzt, beztail, detztzt); + z1len = fast_expansion_sum_zeroelim(zzlen, detzz, zztlen, detzzt, z1); + z2len = fast_expansion_sum_zeroelim(z1len, z1, ztztlen, detztzt, z2); + xylen = fast_expansion_sum_zeroelim(x2len, x2, y2len, y2, detxy); + blen = fast_expansion_sum_zeroelim(z2len, z2, xylen, detxy, bdet); + + temp32alen = scale_expansion_zeroelim(ablen, ab, -dez, temp32a); + temp32blen = scale_expansion_zeroelim(ablen, ab, -deztail, temp32b); + temp64alen = fast_expansion_sum_zeroelim(temp32alen, temp32a, + temp32blen, temp32b, temp64a); + temp32alen = scale_expansion_zeroelim(bdlen, bd, -aez, temp32a); + temp32blen = scale_expansion_zeroelim(bdlen, bd, -aeztail, temp32b); + temp64blen = fast_expansion_sum_zeroelim(temp32alen, temp32a, + temp32blen, temp32b, temp64b); + temp32alen = scale_expansion_zeroelim(dalen, da, -bez, temp32a); + temp32blen = scale_expansion_zeroelim(dalen, da, -beztail, temp32b); + temp64clen = fast_expansion_sum_zeroelim(temp32alen, temp32a, + temp32blen, temp32b, temp64c); + temp128len = fast_expansion_sum_zeroelim(temp64alen, temp64a, + temp64blen, temp64b, temp128); + temp192len = fast_expansion_sum_zeroelim(temp64clen, temp64c, + temp128len, temp128, temp192); + xlen = scale_expansion_zeroelim(temp192len, temp192, cex, detx); + xxlen = scale_expansion_zeroelim(xlen, detx, cex, detxx); + xtlen = scale_expansion_zeroelim(temp192len, temp192, cextail, detxt); + xxtlen = scale_expansion_zeroelim(xtlen, detxt, cex, detxxt); + for (i = 0; i < xxtlen; i++) { + detxxt[i] *= 2.0; + } + xtxtlen = scale_expansion_zeroelim(xtlen, detxt, cextail, detxtxt); + x1len = fast_expansion_sum_zeroelim(xxlen, detxx, xxtlen, detxxt, x1); + x2len = fast_expansion_sum_zeroelim(x1len, x1, xtxtlen, detxtxt, x2); + ylen = scale_expansion_zeroelim(temp192len, temp192, cey, dety); + yylen = scale_expansion_zeroelim(ylen, dety, cey, detyy); + ytlen = scale_expansion_zeroelim(temp192len, temp192, ceytail, detyt); + yytlen = scale_expansion_zeroelim(ytlen, detyt, cey, detyyt); + for (i = 0; i < yytlen; i++) { + detyyt[i] *= 2.0; + } + ytytlen = scale_expansion_zeroelim(ytlen, detyt, ceytail, detytyt); + y1len = fast_expansion_sum_zeroelim(yylen, detyy, yytlen, detyyt, y1); + y2len = fast_expansion_sum_zeroelim(y1len, y1, ytytlen, detytyt, y2); + zlen = scale_expansion_zeroelim(temp192len, temp192, cez, detz); + zzlen = scale_expansion_zeroelim(zlen, detz, cez, detzz); + ztlen = scale_expansion_zeroelim(temp192len, temp192, ceztail, detzt); + zztlen = scale_expansion_zeroelim(ztlen, detzt, cez, detzzt); + for (i = 0; i < zztlen; i++) { + detzzt[i] *= 2.0; + } + ztztlen = scale_expansion_zeroelim(ztlen, detzt, ceztail, detztzt); + z1len = fast_expansion_sum_zeroelim(zzlen, detzz, zztlen, detzzt, z1); + z2len = fast_expansion_sum_zeroelim(z1len, z1, ztztlen, detztzt, z2); + xylen = fast_expansion_sum_zeroelim(x2len, x2, y2len, y2, detxy); + clen = fast_expansion_sum_zeroelim(z2len, z2, xylen, detxy, cdet); + + temp32alen = scale_expansion_zeroelim(bclen, bc, aez, temp32a); + temp32blen = scale_expansion_zeroelim(bclen, bc, aeztail, temp32b); + temp64alen = fast_expansion_sum_zeroelim(temp32alen, temp32a, + temp32blen, temp32b, temp64a); + temp32alen = scale_expansion_zeroelim(aclen, ac, -bez, temp32a); + temp32blen = scale_expansion_zeroelim(aclen, ac, -beztail, temp32b); + temp64blen = fast_expansion_sum_zeroelim(temp32alen, temp32a, + temp32blen, temp32b, temp64b); + temp32alen = scale_expansion_zeroelim(ablen, ab, cez, temp32a); + temp32blen = scale_expansion_zeroelim(ablen, ab, ceztail, temp32b); + temp64clen = fast_expansion_sum_zeroelim(temp32alen, temp32a, + temp32blen, temp32b, temp64c); + temp128len = fast_expansion_sum_zeroelim(temp64alen, temp64a, + temp64blen, temp64b, temp128); + temp192len = fast_expansion_sum_zeroelim(temp64clen, temp64c, + temp128len, temp128, temp192); + xlen = scale_expansion_zeroelim(temp192len, temp192, dex, detx); + xxlen = scale_expansion_zeroelim(xlen, detx, dex, detxx); + xtlen = scale_expansion_zeroelim(temp192len, temp192, dextail, detxt); + xxtlen = scale_expansion_zeroelim(xtlen, detxt, dex, detxxt); + for (i = 0; i < xxtlen; i++) { + detxxt[i] *= 2.0; + } + xtxtlen = scale_expansion_zeroelim(xtlen, detxt, dextail, detxtxt); + x1len = fast_expansion_sum_zeroelim(xxlen, detxx, xxtlen, detxxt, x1); + x2len = fast_expansion_sum_zeroelim(x1len, x1, xtxtlen, detxtxt, x2); + ylen = scale_expansion_zeroelim(temp192len, temp192, dey, dety); + yylen = scale_expansion_zeroelim(ylen, dety, dey, detyy); + ytlen = scale_expansion_zeroelim(temp192len, temp192, deytail, detyt); + yytlen = scale_expansion_zeroelim(ytlen, detyt, dey, detyyt); + for (i = 0; i < yytlen; i++) { + detyyt[i] *= 2.0; + } + ytytlen = scale_expansion_zeroelim(ytlen, detyt, deytail, detytyt); + y1len = fast_expansion_sum_zeroelim(yylen, detyy, yytlen, detyyt, y1); + y2len = fast_expansion_sum_zeroelim(y1len, y1, ytytlen, detytyt, y2); + zlen = scale_expansion_zeroelim(temp192len, temp192, dez, detz); + zzlen = scale_expansion_zeroelim(zlen, detz, dez, detzz); + ztlen = scale_expansion_zeroelim(temp192len, temp192, deztail, detzt); + zztlen = scale_expansion_zeroelim(ztlen, detzt, dez, detzzt); + for (i = 0; i < zztlen; i++) { + detzzt[i] *= 2.0; + } + ztztlen = scale_expansion_zeroelim(ztlen, detzt, deztail, detztzt); + z1len = fast_expansion_sum_zeroelim(zzlen, detzz, zztlen, detzzt, z1); + z2len = fast_expansion_sum_zeroelim(z1len, z1, ztztlen, detztzt, z2); + xylen = fast_expansion_sum_zeroelim(x2len, x2, y2len, y2, detxy); + dlen = fast_expansion_sum_zeroelim(z2len, z2, xylen, detxy, ddet); + + ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet); + cdlen = fast_expansion_sum_zeroelim(clen, cdet, dlen, ddet, cddet); + deterlen = fast_expansion_sum_zeroelim(ablen, abdet, cdlen, cddet, deter); + + return deter[deterlen - 1]; +} + +REAL insphereadapt(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe, + REAL permanent) +{ + INEXACT REAL aex, bex, cex, dex, aey, bey, cey, dey, aez, bez, cez, dez; + REAL det, errbound; + + INEXACT REAL aexbey1, bexaey1, bexcey1, cexbey1; + INEXACT REAL cexdey1, dexcey1, dexaey1, aexdey1; + INEXACT REAL aexcey1, cexaey1, bexdey1, dexbey1; + REAL aexbey0, bexaey0, bexcey0, cexbey0; + REAL cexdey0, dexcey0, dexaey0, aexdey0; + REAL aexcey0, cexaey0, bexdey0, dexbey0; + REAL ab[4], bc[4], cd[4], da[4], ac[4], bd[4]; + INEXACT REAL ab3, bc3, cd3, da3, ac3, bd3; + REAL abeps, bceps, cdeps, daeps, aceps, bdeps; + REAL temp8a[8], temp8b[8], temp8c[8], temp16[16], temp24[24], temp48[48]; + int temp8alen, temp8blen, temp8clen, temp16len, temp24len, temp48len; + REAL xdet[96], ydet[96], zdet[96], xydet[192]; + int xlen, ylen, zlen, xylen; + REAL adet[288], bdet[288], cdet[288], ddet[288]; + int alen, blen, clen, dlen; + REAL abdet[576], cddet[576]; + int ablen, cdlen; + REAL fin1[1152]; + int finlength; + + REAL aextail, bextail, cextail, dextail; + REAL aeytail, beytail, ceytail, deytail; + REAL aeztail, beztail, ceztail, deztail; + + INEXACT REAL bvirt; + REAL avirt, bround, around; + INEXACT REAL c; + INEXACT REAL abig; + REAL ahi, alo, bhi, blo; + REAL err1, err2, err3; + INEXACT REAL _i, _j; + REAL _0; + + + aex = (REAL) (pa[0] - pe[0]); + bex = (REAL) (pb[0] - pe[0]); + cex = (REAL) (pc[0] - pe[0]); + dex = (REAL) (pd[0] - pe[0]); + aey = (REAL) (pa[1] - pe[1]); + bey = (REAL) (pb[1] - pe[1]); + cey = (REAL) (pc[1] - pe[1]); + dey = (REAL) (pd[1] - pe[1]); + aez = (REAL) (pa[2] - pe[2]); + bez = (REAL) (pb[2] - pe[2]); + cez = (REAL) (pc[2] - pe[2]); + dez = (REAL) (pd[2] - pe[2]); + + Two_Product(aex, bey, aexbey1, aexbey0); + Two_Product(bex, aey, bexaey1, bexaey0); + Two_Two_Diff(aexbey1, aexbey0, bexaey1, bexaey0, ab3, ab[2], ab[1], ab[0]); + ab[3] = ab3; + + Two_Product(bex, cey, bexcey1, bexcey0); + Two_Product(cex, bey, cexbey1, cexbey0); + Two_Two_Diff(bexcey1, bexcey0, cexbey1, cexbey0, bc3, bc[2], bc[1], bc[0]); + bc[3] = bc3; + + Two_Product(cex, dey, cexdey1, cexdey0); + Two_Product(dex, cey, dexcey1, dexcey0); + Two_Two_Diff(cexdey1, cexdey0, dexcey1, dexcey0, cd3, cd[2], cd[1], cd[0]); + cd[3] = cd3; + + Two_Product(dex, aey, dexaey1, dexaey0); + Two_Product(aex, dey, aexdey1, aexdey0); + Two_Two_Diff(dexaey1, dexaey0, aexdey1, aexdey0, da3, da[2], da[1], da[0]); + da[3] = da3; + + Two_Product(aex, cey, aexcey1, aexcey0); + Two_Product(cex, aey, cexaey1, cexaey0); + Two_Two_Diff(aexcey1, aexcey0, cexaey1, cexaey0, ac3, ac[2], ac[1], ac[0]); + ac[3] = ac3; + + Two_Product(bex, dey, bexdey1, bexdey0); + Two_Product(dex, bey, dexbey1, dexbey0); + Two_Two_Diff(bexdey1, bexdey0, dexbey1, dexbey0, bd3, bd[2], bd[1], bd[0]); + bd[3] = bd3; + + temp8alen = scale_expansion_zeroelim(4, cd, bez, temp8a); + temp8blen = scale_expansion_zeroelim(4, bd, -cez, temp8b); + temp8clen = scale_expansion_zeroelim(4, bc, dez, temp8c); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, + temp8blen, temp8b, temp16); + temp24len = fast_expansion_sum_zeroelim(temp8clen, temp8c, + temp16len, temp16, temp24); + temp48len = scale_expansion_zeroelim(temp24len, temp24, aex, temp48); + xlen = scale_expansion_zeroelim(temp48len, temp48, -aex, xdet); + temp48len = scale_expansion_zeroelim(temp24len, temp24, aey, temp48); + ylen = scale_expansion_zeroelim(temp48len, temp48, -aey, ydet); + temp48len = scale_expansion_zeroelim(temp24len, temp24, aez, temp48); + zlen = scale_expansion_zeroelim(temp48len, temp48, -aez, zdet); + xylen = fast_expansion_sum_zeroelim(xlen, xdet, ylen, ydet, xydet); + alen = fast_expansion_sum_zeroelim(xylen, xydet, zlen, zdet, adet); + + temp8alen = scale_expansion_zeroelim(4, da, cez, temp8a); + temp8blen = scale_expansion_zeroelim(4, ac, dez, temp8b); + temp8clen = scale_expansion_zeroelim(4, cd, aez, temp8c); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, + temp8blen, temp8b, temp16); + temp24len = fast_expansion_sum_zeroelim(temp8clen, temp8c, + temp16len, temp16, temp24); + temp48len = scale_expansion_zeroelim(temp24len, temp24, bex, temp48); + xlen = scale_expansion_zeroelim(temp48len, temp48, bex, xdet); + temp48len = scale_expansion_zeroelim(temp24len, temp24, bey, temp48); + ylen = scale_expansion_zeroelim(temp48len, temp48, bey, ydet); + temp48len = scale_expansion_zeroelim(temp24len, temp24, bez, temp48); + zlen = scale_expansion_zeroelim(temp48len, temp48, bez, zdet); + xylen = fast_expansion_sum_zeroelim(xlen, xdet, ylen, ydet, xydet); + blen = fast_expansion_sum_zeroelim(xylen, xydet, zlen, zdet, bdet); + + temp8alen = scale_expansion_zeroelim(4, ab, dez, temp8a); + temp8blen = scale_expansion_zeroelim(4, bd, aez, temp8b); + temp8clen = scale_expansion_zeroelim(4, da, bez, temp8c); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, + temp8blen, temp8b, temp16); + temp24len = fast_expansion_sum_zeroelim(temp8clen, temp8c, + temp16len, temp16, temp24); + temp48len = scale_expansion_zeroelim(temp24len, temp24, cex, temp48); + xlen = scale_expansion_zeroelim(temp48len, temp48, -cex, xdet); + temp48len = scale_expansion_zeroelim(temp24len, temp24, cey, temp48); + ylen = scale_expansion_zeroelim(temp48len, temp48, -cey, ydet); + temp48len = scale_expansion_zeroelim(temp24len, temp24, cez, temp48); + zlen = scale_expansion_zeroelim(temp48len, temp48, -cez, zdet); + xylen = fast_expansion_sum_zeroelim(xlen, xdet, ylen, ydet, xydet); + clen = fast_expansion_sum_zeroelim(xylen, xydet, zlen, zdet, cdet); + + temp8alen = scale_expansion_zeroelim(4, bc, aez, temp8a); + temp8blen = scale_expansion_zeroelim(4, ac, -bez, temp8b); + temp8clen = scale_expansion_zeroelim(4, ab, cez, temp8c); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, + temp8blen, temp8b, temp16); + temp24len = fast_expansion_sum_zeroelim(temp8clen, temp8c, + temp16len, temp16, temp24); + temp48len = scale_expansion_zeroelim(temp24len, temp24, dex, temp48); + xlen = scale_expansion_zeroelim(temp48len, temp48, dex, xdet); + temp48len = scale_expansion_zeroelim(temp24len, temp24, dey, temp48); + ylen = scale_expansion_zeroelim(temp48len, temp48, dey, ydet); + temp48len = scale_expansion_zeroelim(temp24len, temp24, dez, temp48); + zlen = scale_expansion_zeroelim(temp48len, temp48, dez, zdet); + xylen = fast_expansion_sum_zeroelim(xlen, xdet, ylen, ydet, xydet); + dlen = fast_expansion_sum_zeroelim(xylen, xydet, zlen, zdet, ddet); + + ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet); + cdlen = fast_expansion_sum_zeroelim(clen, cdet, dlen, ddet, cddet); + finlength = fast_expansion_sum_zeroelim(ablen, abdet, cdlen, cddet, fin1); + + det = estimate(finlength, fin1); + errbound = isperrboundB * permanent; + if ((det >= errbound) || (-det >= errbound)) { + return det; + } + + Two_Diff_Tail(pa[0], pe[0], aex, aextail); + Two_Diff_Tail(pa[1], pe[1], aey, aeytail); + Two_Diff_Tail(pa[2], pe[2], aez, aeztail); + Two_Diff_Tail(pb[0], pe[0], bex, bextail); + Two_Diff_Tail(pb[1], pe[1], bey, beytail); + Two_Diff_Tail(pb[2], pe[2], bez, beztail); + Two_Diff_Tail(pc[0], pe[0], cex, cextail); + Two_Diff_Tail(pc[1], pe[1], cey, ceytail); + Two_Diff_Tail(pc[2], pe[2], cez, ceztail); + Two_Diff_Tail(pd[0], pe[0], dex, dextail); + Two_Diff_Tail(pd[1], pe[1], dey, deytail); + Two_Diff_Tail(pd[2], pe[2], dez, deztail); + if ((aextail == 0.0) && (aeytail == 0.0) && (aeztail == 0.0) + && (bextail == 0.0) && (beytail == 0.0) && (beztail == 0.0) + && (cextail == 0.0) && (ceytail == 0.0) && (ceztail == 0.0) + && (dextail == 0.0) && (deytail == 0.0) && (deztail == 0.0)) { + return det; + } + + errbound = isperrboundC * permanent + resulterrbound * Absolute(det); + abeps = (aex * beytail + bey * aextail) + - (aey * bextail + bex * aeytail); + bceps = (bex * ceytail + cey * bextail) + - (bey * cextail + cex * beytail); + cdeps = (cex * deytail + dey * cextail) + - (cey * dextail + dex * ceytail); + daeps = (dex * aeytail + aey * dextail) + - (dey * aextail + aex * deytail); + aceps = (aex * ceytail + cey * aextail) + - (aey * cextail + cex * aeytail); + bdeps = (bex * deytail + dey * bextail) + - (bey * dextail + dex * beytail); + det += (((bex * bex + bey * bey + bez * bez) + * ((cez * daeps + dez * aceps + aez * cdeps) + + (ceztail * da3 + deztail * ac3 + aeztail * cd3)) + + (dex * dex + dey * dey + dez * dez) + * ((aez * bceps - bez * aceps + cez * abeps) + + (aeztail * bc3 - beztail * ac3 + ceztail * ab3))) + - ((aex * aex + aey * aey + aez * aez) + * ((bez * cdeps - cez * bdeps + dez * bceps) + + (beztail * cd3 - ceztail * bd3 + deztail * bc3)) + + (cex * cex + cey * cey + cez * cez) + * ((dez * abeps + aez * bdeps + bez * daeps) + + (deztail * ab3 + aeztail * bd3 + beztail * da3)))) + + 2.0 * (((bex * bextail + bey * beytail + bez * beztail) + * (cez * da3 + dez * ac3 + aez * cd3) + + (dex * dextail + dey * deytail + dez * deztail) + * (aez * bc3 - bez * ac3 + cez * ab3)) + - ((aex * aextail + aey * aeytail + aez * aeztail) + * (bez * cd3 - cez * bd3 + dez * bc3) + + (cex * cextail + cey * ceytail + cez * ceztail) + * (dez * ab3 + aez * bd3 + bez * da3))); + if ((det >= errbound) || (-det >= errbound)) { + return det; + } + + return insphereexact(pa, pb, pc, pd, pe); +} + +#ifdef USE_CGAL_PREDICATES + +REAL insphere(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe) +{ + return (REAL) + - cgal_pred_obj.side_of_oriented_sphere_3_object() + (Point(pa[0], pa[1], pa[2]), + Point(pb[0], pb[1], pb[2]), + Point(pc[0], pc[1], pc[2]), + Point(pd[0], pd[1], pd[2]), + Point(pe[0], pe[1], pe[2])); +} + +#else + +REAL insphere(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe) +{ + REAL aex, bex, cex, dex; + REAL aey, bey, cey, dey; + REAL aez, bez, cez, dez; + REAL aexbey, bexaey, bexcey, cexbey, cexdey, dexcey, dexaey, aexdey; + REAL aexcey, cexaey, bexdey, dexbey; + REAL alift, blift, clift, dlift; + REAL ab, bc, cd, da, ac, bd; + REAL abc, bcd, cda, dab; + REAL det; + + + aex = pa[0] - pe[0]; + bex = pb[0] - pe[0]; + cex = pc[0] - pe[0]; + dex = pd[0] - pe[0]; + aey = pa[1] - pe[1]; + bey = pb[1] - pe[1]; + cey = pc[1] - pe[1]; + dey = pd[1] - pe[1]; + aez = pa[2] - pe[2]; + bez = pb[2] - pe[2]; + cez = pc[2] - pe[2]; + dez = pd[2] - pe[2]; + + aexbey = aex * bey; + bexaey = bex * aey; + ab = aexbey - bexaey; + bexcey = bex * cey; + cexbey = cex * bey; + bc = bexcey - cexbey; + cexdey = cex * dey; + dexcey = dex * cey; + cd = cexdey - dexcey; + dexaey = dex * aey; + aexdey = aex * dey; + da = dexaey - aexdey; + + aexcey = aex * cey; + cexaey = cex * aey; + ac = aexcey - cexaey; + bexdey = bex * dey; + dexbey = dex * bey; + bd = bexdey - dexbey; + + abc = aez * bc - bez * ac + cez * ab; + bcd = bez * cd - cez * bd + dez * bc; + cda = cez * da + dez * ac + aez * cd; + dab = dez * ab + aez * bd + bez * da; + + alift = aex * aex + aey * aey + aez * aez; + blift = bex * bex + bey * bey + bez * bez; + clift = cex * cex + cey * cey + cez * cez; + dlift = dex * dex + dey * dey + dez * dez; + + det = (dlift * abc - clift * dab) + (blift * cda - alift * bcd); + + if (_use_inexact_arith) { + return det; + } + + if (_use_static_filter) { + if (fabs(det) > ispstaticfilter) return det; + //if (det > ispstaticfilter) return det; + //if (det < minus_ispstaticfilter) return det; + + } + + REAL aezplus, bezplus, cezplus, dezplus; + REAL aexbeyplus, bexaeyplus, bexceyplus, cexbeyplus; + REAL cexdeyplus, dexceyplus, dexaeyplus, aexdeyplus; + REAL aexceyplus, cexaeyplus, bexdeyplus, dexbeyplus; + REAL permanent, errbound; + + aezplus = Absolute(aez); + bezplus = Absolute(bez); + cezplus = Absolute(cez); + dezplus = Absolute(dez); + aexbeyplus = Absolute(aexbey); + bexaeyplus = Absolute(bexaey); + bexceyplus = Absolute(bexcey); + cexbeyplus = Absolute(cexbey); + cexdeyplus = Absolute(cexdey); + dexceyplus = Absolute(dexcey); + dexaeyplus = Absolute(dexaey); + aexdeyplus = Absolute(aexdey); + aexceyplus = Absolute(aexcey); + cexaeyplus = Absolute(cexaey); + bexdeyplus = Absolute(bexdey); + dexbeyplus = Absolute(dexbey); + permanent = ((cexdeyplus + dexceyplus) * bezplus + + (dexbeyplus + bexdeyplus) * cezplus + + (bexceyplus + cexbeyplus) * dezplus) + * alift + + ((dexaeyplus + aexdeyplus) * cezplus + + (aexceyplus + cexaeyplus) * dezplus + + (cexdeyplus + dexceyplus) * aezplus) + * blift + + ((aexbeyplus + bexaeyplus) * dezplus + + (bexdeyplus + dexbeyplus) * aezplus + + (dexaeyplus + aexdeyplus) * bezplus) + * clift + + ((bexceyplus + cexbeyplus) * aezplus + + (cexaeyplus + aexceyplus) * bezplus + + (aexbeyplus + bexaeyplus) * cezplus) + * dlift; + errbound = isperrboundA * permanent; + if ((det > errbound) || (-det > errbound)) { + return det; + } + + return insphereadapt(pa, pb, pc, pd, pe, permanent); +} + +#endif // #ifdef USE_CGAL_PREDICATES + +/*****************************************************************************/ +/* */ +/* orient4d() Return a positive value if the point pe lies above the */ +/* hyperplane passing through pa, pb, pc, and pd; "above" is */ +/* defined in a manner best found by trial-and-error. Returns */ +/* a negative value if pe lies below the hyperplane. Returns */ +/* zero if the points are co-hyperplanar (not affinely */ +/* independent). The result is also a rough approximation of */ +/* 24 times the signed volume of the 4-simplex defined by the */ +/* five points. */ +/* */ +/* Uses exact arithmetic if necessary to ensure a correct answer. The */ +/* result returned is the determinant of a matrix. This determinant is */ +/* computed adaptively, in the sense that exact arithmetic is used only to */ +/* the degree it is needed to ensure that the returned value has the */ +/* correct sign. Hence, orient4d() is usually quite fast, but will run */ +/* more slowly when the input points are hyper-coplanar or nearly so. */ +/* */ +/* See my Robust Predicates paper for details. */ +/* */ +/*****************************************************************************/ + +REAL orient4dexact(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe, + REAL aheight, REAL bheight, REAL cheight, REAL dheight, + REAL eheight) +{ + INEXACT REAL axby1, bxcy1, cxdy1, dxey1, exay1; + INEXACT REAL bxay1, cxby1, dxcy1, exdy1, axey1; + INEXACT REAL axcy1, bxdy1, cxey1, dxay1, exby1; + INEXACT REAL cxay1, dxby1, excy1, axdy1, bxey1; + REAL axby0, bxcy0, cxdy0, dxey0, exay0; + REAL bxay0, cxby0, dxcy0, exdy0, axey0; + REAL axcy0, bxdy0, cxey0, dxay0, exby0; + REAL cxay0, dxby0, excy0, axdy0, bxey0; + REAL ab[4], bc[4], cd[4], de[4], ea[4]; + REAL ac[4], bd[4], ce[4], da[4], eb[4]; + REAL temp8a[8], temp8b[8], temp16[16]; + int temp8alen, temp8blen, temp16len; + REAL abc[24], bcd[24], cde[24], dea[24], eab[24]; + REAL abd[24], bce[24], cda[24], deb[24], eac[24]; + int abclen, bcdlen, cdelen, dealen, eablen; + int abdlen, bcelen, cdalen, deblen, eaclen; + REAL temp48a[48], temp48b[48]; + int temp48alen, temp48blen; + REAL abcd[96], bcde[96], cdea[96], deab[96], eabc[96]; + int abcdlen, bcdelen, cdealen, deablen, eabclen; + REAL adet[192], bdet[192], cdet[192], ddet[192], edet[192]; + int alen, blen, clen, dlen, elen; + REAL abdet[384], cddet[384], cdedet[576]; + int ablen, cdlen; + REAL deter[960]; + int deterlen; + int i; + + INEXACT REAL bvirt; + REAL avirt, bround, around; + INEXACT REAL c; + INEXACT REAL abig; + REAL ahi, alo, bhi, blo; + REAL err1, err2, err3; + INEXACT REAL _i, _j; + REAL _0; + + + Two_Product(pa[0], pb[1], axby1, axby0); + Two_Product(pb[0], pa[1], bxay1, bxay0); + Two_Two_Diff(axby1, axby0, bxay1, bxay0, ab[3], ab[2], ab[1], ab[0]); + + Two_Product(pb[0], pc[1], bxcy1, bxcy0); + Two_Product(pc[0], pb[1], cxby1, cxby0); + Two_Two_Diff(bxcy1, bxcy0, cxby1, cxby0, bc[3], bc[2], bc[1], bc[0]); + + Two_Product(pc[0], pd[1], cxdy1, cxdy0); + Two_Product(pd[0], pc[1], dxcy1, dxcy0); + Two_Two_Diff(cxdy1, cxdy0, dxcy1, dxcy0, cd[3], cd[2], cd[1], cd[0]); + + Two_Product(pd[0], pe[1], dxey1, dxey0); + Two_Product(pe[0], pd[1], exdy1, exdy0); + Two_Two_Diff(dxey1, dxey0, exdy1, exdy0, de[3], de[2], de[1], de[0]); + + Two_Product(pe[0], pa[1], exay1, exay0); + Two_Product(pa[0], pe[1], axey1, axey0); + Two_Two_Diff(exay1, exay0, axey1, axey0, ea[3], ea[2], ea[1], ea[0]); + + Two_Product(pa[0], pc[1], axcy1, axcy0); + Two_Product(pc[0], pa[1], cxay1, cxay0); + Two_Two_Diff(axcy1, axcy0, cxay1, cxay0, ac[3], ac[2], ac[1], ac[0]); + + Two_Product(pb[0], pd[1], bxdy1, bxdy0); + Two_Product(pd[0], pb[1], dxby1, dxby0); + Two_Two_Diff(bxdy1, bxdy0, dxby1, dxby0, bd[3], bd[2], bd[1], bd[0]); + + Two_Product(pc[0], pe[1], cxey1, cxey0); + Two_Product(pe[0], pc[1], excy1, excy0); + Two_Two_Diff(cxey1, cxey0, excy1, excy0, ce[3], ce[2], ce[1], ce[0]); + + Two_Product(pd[0], pa[1], dxay1, dxay0); + Two_Product(pa[0], pd[1], axdy1, axdy0); + Two_Two_Diff(dxay1, dxay0, axdy1, axdy0, da[3], da[2], da[1], da[0]); + + Two_Product(pe[0], pb[1], exby1, exby0); + Two_Product(pb[0], pe[1], bxey1, bxey0); + Two_Two_Diff(exby1, exby0, bxey1, bxey0, eb[3], eb[2], eb[1], eb[0]); + + temp8alen = scale_expansion_zeroelim(4, bc, pa[2], temp8a); + temp8blen = scale_expansion_zeroelim(4, ac, -pb[2], temp8b); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b, + temp16); + temp8alen = scale_expansion_zeroelim(4, ab, pc[2], temp8a); + abclen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16, + abc); + + temp8alen = scale_expansion_zeroelim(4, cd, pb[2], temp8a); + temp8blen = scale_expansion_zeroelim(4, bd, -pc[2], temp8b); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b, + temp16); + temp8alen = scale_expansion_zeroelim(4, bc, pd[2], temp8a); + bcdlen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16, + bcd); + + temp8alen = scale_expansion_zeroelim(4, de, pc[2], temp8a); + temp8blen = scale_expansion_zeroelim(4, ce, -pd[2], temp8b); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b, + temp16); + temp8alen = scale_expansion_zeroelim(4, cd, pe[2], temp8a); + cdelen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16, + cde); + + temp8alen = scale_expansion_zeroelim(4, ea, pd[2], temp8a); + temp8blen = scale_expansion_zeroelim(4, da, -pe[2], temp8b); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b, + temp16); + temp8alen = scale_expansion_zeroelim(4, de, pa[2], temp8a); + dealen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16, + dea); + + temp8alen = scale_expansion_zeroelim(4, ab, pe[2], temp8a); + temp8blen = scale_expansion_zeroelim(4, eb, -pa[2], temp8b); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b, + temp16); + temp8alen = scale_expansion_zeroelim(4, ea, pb[2], temp8a); + eablen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16, + eab); + + temp8alen = scale_expansion_zeroelim(4, bd, pa[2], temp8a); + temp8blen = scale_expansion_zeroelim(4, da, pb[2], temp8b); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b, + temp16); + temp8alen = scale_expansion_zeroelim(4, ab, pd[2], temp8a); + abdlen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16, + abd); + + temp8alen = scale_expansion_zeroelim(4, ce, pb[2], temp8a); + temp8blen = scale_expansion_zeroelim(4, eb, pc[2], temp8b); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b, + temp16); + temp8alen = scale_expansion_zeroelim(4, bc, pe[2], temp8a); + bcelen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16, + bce); + + temp8alen = scale_expansion_zeroelim(4, da, pc[2], temp8a); + temp8blen = scale_expansion_zeroelim(4, ac, pd[2], temp8b); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b, + temp16); + temp8alen = scale_expansion_zeroelim(4, cd, pa[2], temp8a); + cdalen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16, + cda); + + temp8alen = scale_expansion_zeroelim(4, eb, pd[2], temp8a); + temp8blen = scale_expansion_zeroelim(4, bd, pe[2], temp8b); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b, + temp16); + temp8alen = scale_expansion_zeroelim(4, de, pb[2], temp8a); + deblen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16, + deb); + + temp8alen = scale_expansion_zeroelim(4, ac, pe[2], temp8a); + temp8blen = scale_expansion_zeroelim(4, ce, pa[2], temp8b); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b, + temp16); + temp8alen = scale_expansion_zeroelim(4, ea, pc[2], temp8a); + eaclen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16, + eac); + + temp48alen = fast_expansion_sum_zeroelim(cdelen, cde, bcelen, bce, temp48a); + temp48blen = fast_expansion_sum_zeroelim(deblen, deb, bcdlen, bcd, temp48b); + for (i = 0; i < temp48blen; i++) { + temp48b[i] = -temp48b[i]; + } + bcdelen = fast_expansion_sum_zeroelim(temp48alen, temp48a, + temp48blen, temp48b, bcde); + alen = scale_expansion_zeroelim(bcdelen, bcde, aheight, adet); + + temp48alen = fast_expansion_sum_zeroelim(dealen, dea, cdalen, cda, temp48a); + temp48blen = fast_expansion_sum_zeroelim(eaclen, eac, cdelen, cde, temp48b); + for (i = 0; i < temp48blen; i++) { + temp48b[i] = -temp48b[i]; + } + cdealen = fast_expansion_sum_zeroelim(temp48alen, temp48a, + temp48blen, temp48b, cdea); + blen = scale_expansion_zeroelim(cdealen, cdea, bheight, bdet); + + temp48alen = fast_expansion_sum_zeroelim(eablen, eab, deblen, deb, temp48a); + temp48blen = fast_expansion_sum_zeroelim(abdlen, abd, dealen, dea, temp48b); + for (i = 0; i < temp48blen; i++) { + temp48b[i] = -temp48b[i]; + } + deablen = fast_expansion_sum_zeroelim(temp48alen, temp48a, + temp48blen, temp48b, deab); + clen = scale_expansion_zeroelim(deablen, deab, cheight, cdet); + + temp48alen = fast_expansion_sum_zeroelim(abclen, abc, eaclen, eac, temp48a); + temp48blen = fast_expansion_sum_zeroelim(bcelen, bce, eablen, eab, temp48b); + for (i = 0; i < temp48blen; i++) { + temp48b[i] = -temp48b[i]; + } + eabclen = fast_expansion_sum_zeroelim(temp48alen, temp48a, + temp48blen, temp48b, eabc); + dlen = scale_expansion_zeroelim(eabclen, eabc, dheight, ddet); + + temp48alen = fast_expansion_sum_zeroelim(bcdlen, bcd, abdlen, abd, temp48a); + temp48blen = fast_expansion_sum_zeroelim(cdalen, cda, abclen, abc, temp48b); + for (i = 0; i < temp48blen; i++) { + temp48b[i] = -temp48b[i]; + } + abcdlen = fast_expansion_sum_zeroelim(temp48alen, temp48a, + temp48blen, temp48b, abcd); + elen = scale_expansion_zeroelim(abcdlen, abcd, eheight, edet); + + ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet); + cdlen = fast_expansion_sum_zeroelim(clen, cdet, dlen, ddet, cddet); + cdelen = fast_expansion_sum_zeroelim(cdlen, cddet, elen, edet, cdedet); + deterlen = fast_expansion_sum_zeroelim(ablen, abdet, cdelen, cdedet, deter); + + return deter[deterlen - 1]; +} + +REAL orient4dadapt(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe, + REAL aheight, REAL bheight, REAL cheight, REAL dheight, + REAL eheight, REAL permanent) +{ + INEXACT REAL aex, bex, cex, dex, aey, bey, cey, dey, aez, bez, cez, dez; + INEXACT REAL aeheight, beheight, ceheight, deheight; + REAL det, errbound; + + INEXACT REAL aexbey1, bexaey1, bexcey1, cexbey1; + INEXACT REAL cexdey1, dexcey1, dexaey1, aexdey1; + INEXACT REAL aexcey1, cexaey1, bexdey1, dexbey1; + REAL aexbey0, bexaey0, bexcey0, cexbey0; + REAL cexdey0, dexcey0, dexaey0, aexdey0; + REAL aexcey0, cexaey0, bexdey0, dexbey0; + REAL ab[4], bc[4], cd[4], da[4], ac[4], bd[4]; + INEXACT REAL ab3, bc3, cd3, da3, ac3, bd3; + REAL abeps, bceps, cdeps, daeps, aceps, bdeps; + REAL temp8a[8], temp8b[8], temp8c[8], temp16[16], temp24[24]; + int temp8alen, temp8blen, temp8clen, temp16len, temp24len; + REAL adet[48], bdet[48], cdet[48], ddet[48]; + int alen, blen, clen, dlen; + REAL abdet[96], cddet[96]; + int ablen, cdlen; + REAL fin1[192]; + int finlength; + + REAL aextail, bextail, cextail, dextail; + REAL aeytail, beytail, ceytail, deytail; + REAL aeztail, beztail, ceztail, deztail; + REAL aeheighttail, beheighttail, ceheighttail, deheighttail; + + INEXACT REAL bvirt; + REAL avirt, bround, around; + INEXACT REAL c; + INEXACT REAL abig; + REAL ahi, alo, bhi, blo; + REAL err1, err2, err3; + INEXACT REAL _i, _j; + REAL _0; + + + aex = (REAL) (pa[0] - pe[0]); + bex = (REAL) (pb[0] - pe[0]); + cex = (REAL) (pc[0] - pe[0]); + dex = (REAL) (pd[0] - pe[0]); + aey = (REAL) (pa[1] - pe[1]); + bey = (REAL) (pb[1] - pe[1]); + cey = (REAL) (pc[1] - pe[1]); + dey = (REAL) (pd[1] - pe[1]); + aez = (REAL) (pa[2] - pe[2]); + bez = (REAL) (pb[2] - pe[2]); + cez = (REAL) (pc[2] - pe[2]); + dez = (REAL) (pd[2] - pe[2]); + aeheight = (REAL) (aheight - eheight); + beheight = (REAL) (bheight - eheight); + ceheight = (REAL) (cheight - eheight); + deheight = (REAL) (dheight - eheight); + + Two_Product(aex, bey, aexbey1, aexbey0); + Two_Product(bex, aey, bexaey1, bexaey0); + Two_Two_Diff(aexbey1, aexbey0, bexaey1, bexaey0, ab3, ab[2], ab[1], ab[0]); + ab[3] = ab3; + + Two_Product(bex, cey, bexcey1, bexcey0); + Two_Product(cex, bey, cexbey1, cexbey0); + Two_Two_Diff(bexcey1, bexcey0, cexbey1, cexbey0, bc3, bc[2], bc[1], bc[0]); + bc[3] = bc3; + + Two_Product(cex, dey, cexdey1, cexdey0); + Two_Product(dex, cey, dexcey1, dexcey0); + Two_Two_Diff(cexdey1, cexdey0, dexcey1, dexcey0, cd3, cd[2], cd[1], cd[0]); + cd[3] = cd3; + + Two_Product(dex, aey, dexaey1, dexaey0); + Two_Product(aex, dey, aexdey1, aexdey0); + Two_Two_Diff(dexaey1, dexaey0, aexdey1, aexdey0, da3, da[2], da[1], da[0]); + da[3] = da3; + + Two_Product(aex, cey, aexcey1, aexcey0); + Two_Product(cex, aey, cexaey1, cexaey0); + Two_Two_Diff(aexcey1, aexcey0, cexaey1, cexaey0, ac3, ac[2], ac[1], ac[0]); + ac[3] = ac3; + + Two_Product(bex, dey, bexdey1, bexdey0); + Two_Product(dex, bey, dexbey1, dexbey0); + Two_Two_Diff(bexdey1, bexdey0, dexbey1, dexbey0, bd3, bd[2], bd[1], bd[0]); + bd[3] = bd3; + + temp8alen = scale_expansion_zeroelim(4, cd, bez, temp8a); + temp8blen = scale_expansion_zeroelim(4, bd, -cez, temp8b); + temp8clen = scale_expansion_zeroelim(4, bc, dez, temp8c); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, + temp8blen, temp8b, temp16); + temp24len = fast_expansion_sum_zeroelim(temp8clen, temp8c, + temp16len, temp16, temp24); + alen = scale_expansion_zeroelim(temp24len, temp24, -aeheight, adet); + + temp8alen = scale_expansion_zeroelim(4, da, cez, temp8a); + temp8blen = scale_expansion_zeroelim(4, ac, dez, temp8b); + temp8clen = scale_expansion_zeroelim(4, cd, aez, temp8c); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, + temp8blen, temp8b, temp16); + temp24len = fast_expansion_sum_zeroelim(temp8clen, temp8c, + temp16len, temp16, temp24); + blen = scale_expansion_zeroelim(temp24len, temp24, beheight, bdet); + + temp8alen = scale_expansion_zeroelim(4, ab, dez, temp8a); + temp8blen = scale_expansion_zeroelim(4, bd, aez, temp8b); + temp8clen = scale_expansion_zeroelim(4, da, bez, temp8c); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, + temp8blen, temp8b, temp16); + temp24len = fast_expansion_sum_zeroelim(temp8clen, temp8c, + temp16len, temp16, temp24); + clen = scale_expansion_zeroelim(temp24len, temp24, -ceheight, cdet); + + temp8alen = scale_expansion_zeroelim(4, bc, aez, temp8a); + temp8blen = scale_expansion_zeroelim(4, ac, -bez, temp8b); + temp8clen = scale_expansion_zeroelim(4, ab, cez, temp8c); + temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, + temp8blen, temp8b, temp16); + temp24len = fast_expansion_sum_zeroelim(temp8clen, temp8c, + temp16len, temp16, temp24); + dlen = scale_expansion_zeroelim(temp24len, temp24, deheight, ddet); + + ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet); + cdlen = fast_expansion_sum_zeroelim(clen, cdet, dlen, ddet, cddet); + finlength = fast_expansion_sum_zeroelim(ablen, abdet, cdlen, cddet, fin1); + + det = estimate(finlength, fin1); + errbound = isperrboundB * permanent; + if ((det >= errbound) || (-det >= errbound)) { + return det; + } + + Two_Diff_Tail(pa[0], pe[0], aex, aextail); + Two_Diff_Tail(pa[1], pe[1], aey, aeytail); + Two_Diff_Tail(pa[2], pe[2], aez, aeztail); + Two_Diff_Tail(aheight, eheight, aeheight, aeheighttail); + Two_Diff_Tail(pb[0], pe[0], bex, bextail); + Two_Diff_Tail(pb[1], pe[1], bey, beytail); + Two_Diff_Tail(pb[2], pe[2], bez, beztail); + Two_Diff_Tail(bheight, eheight, beheight, beheighttail); + Two_Diff_Tail(pc[0], pe[0], cex, cextail); + Two_Diff_Tail(pc[1], pe[1], cey, ceytail); + Two_Diff_Tail(pc[2], pe[2], cez, ceztail); + Two_Diff_Tail(cheight, eheight, ceheight, ceheighttail); + Two_Diff_Tail(pd[0], pe[0], dex, dextail); + Two_Diff_Tail(pd[1], pe[1], dey, deytail); + Two_Diff_Tail(pd[2], pe[2], dez, deztail); + Two_Diff_Tail(dheight, eheight, deheight, deheighttail); + if ((aextail == 0.0) && (aeytail == 0.0) && (aeztail == 0.0) + && (bextail == 0.0) && (beytail == 0.0) && (beztail == 0.0) + && (cextail == 0.0) && (ceytail == 0.0) && (ceztail == 0.0) + && (dextail == 0.0) && (deytail == 0.0) && (deztail == 0.0) + && (aeheighttail == 0.0) && (beheighttail == 0.0) + && (ceheighttail == 0.0) && (deheighttail == 0.0)) { + return det; + } + + errbound = isperrboundC * permanent + resulterrbound * Absolute(det); + abeps = (aex * beytail + bey * aextail) + - (aey * bextail + bex * aeytail); + bceps = (bex * ceytail + cey * bextail) + - (bey * cextail + cex * beytail); + cdeps = (cex * deytail + dey * cextail) + - (cey * dextail + dex * ceytail); + daeps = (dex * aeytail + aey * dextail) + - (dey * aextail + aex * deytail); + aceps = (aex * ceytail + cey * aextail) + - (aey * cextail + cex * aeytail); + bdeps = (bex * deytail + dey * bextail) + - (bey * dextail + dex * beytail); + det += ((beheight + * ((cez * daeps + dez * aceps + aez * cdeps) + + (ceztail * da3 + deztail * ac3 + aeztail * cd3)) + + deheight + * ((aez * bceps - bez * aceps + cez * abeps) + + (aeztail * bc3 - beztail * ac3 + ceztail * ab3))) + - (aeheight + * ((bez * cdeps - cez * bdeps + dez * bceps) + + (beztail * cd3 - ceztail * bd3 + deztail * bc3)) + + ceheight + * ((dez * abeps + aez * bdeps + bez * daeps) + + (deztail * ab3 + aeztail * bd3 + beztail * da3)))) + + ((beheighttail * (cez * da3 + dez * ac3 + aez * cd3) + + deheighttail * (aez * bc3 - bez * ac3 + cez * ab3)) + - (aeheighttail * (bez * cd3 - cez * bd3 + dez * bc3) + + ceheighttail * (dez * ab3 + aez * bd3 + bez * da3))); + if ((det >= errbound) || (-det >= errbound)) { + return det; + } + + return orient4dexact(pa, pb, pc, pd, pe, + aheight, bheight, cheight, dheight, eheight); +} + +REAL orient4d(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe, + REAL aheight, REAL bheight, REAL cheight, REAL dheight, + REAL eheight) +{ + REAL aex, bex, cex, dex; + REAL aey, bey, cey, dey; + REAL aez, bez, cez, dez; + REAL aexbey, bexaey, bexcey, cexbey, cexdey, dexcey, dexaey, aexdey; + REAL aexcey, cexaey, bexdey, dexbey; + REAL aeheight, beheight, ceheight, deheight; + REAL ab, bc, cd, da, ac, bd; + REAL abc, bcd, cda, dab; + REAL aezplus, bezplus, cezplus, dezplus; + REAL aexbeyplus, bexaeyplus, bexceyplus, cexbeyplus; + REAL cexdeyplus, dexceyplus, dexaeyplus, aexdeyplus; + REAL aexceyplus, cexaeyplus, bexdeyplus, dexbeyplus; + REAL det; + REAL permanent, errbound; + + + aex = pa[0] - pe[0]; + bex = pb[0] - pe[0]; + cex = pc[0] - pe[0]; + dex = pd[0] - pe[0]; + aey = pa[1] - pe[1]; + bey = pb[1] - pe[1]; + cey = pc[1] - pe[1]; + dey = pd[1] - pe[1]; + aez = pa[2] - pe[2]; + bez = pb[2] - pe[2]; + cez = pc[2] - pe[2]; + dez = pd[2] - pe[2]; + aeheight = aheight - eheight; + beheight = bheight - eheight; + ceheight = cheight - eheight; + deheight = dheight - eheight; + + aexbey = aex * bey; + bexaey = bex * aey; + ab = aexbey - bexaey; + bexcey = bex * cey; + cexbey = cex * bey; + bc = bexcey - cexbey; + cexdey = cex * dey; + dexcey = dex * cey; + cd = cexdey - dexcey; + dexaey = dex * aey; + aexdey = aex * dey; + da = dexaey - aexdey; + + aexcey = aex * cey; + cexaey = cex * aey; + ac = aexcey - cexaey; + bexdey = bex * dey; + dexbey = dex * bey; + bd = bexdey - dexbey; + + abc = aez * bc - bez * ac + cez * ab; + bcd = bez * cd - cez * bd + dez * bc; + cda = cez * da + dez * ac + aez * cd; + dab = dez * ab + aez * bd + bez * da; + + det = (deheight * abc - ceheight * dab) + (beheight * cda - aeheight * bcd); + + aezplus = Absolute(aez); + bezplus = Absolute(bez); + cezplus = Absolute(cez); + dezplus = Absolute(dez); + aexbeyplus = Absolute(aexbey); + bexaeyplus = Absolute(bexaey); + bexceyplus = Absolute(bexcey); + cexbeyplus = Absolute(cexbey); + cexdeyplus = Absolute(cexdey); + dexceyplus = Absolute(dexcey); + dexaeyplus = Absolute(dexaey); + aexdeyplus = Absolute(aexdey); + aexceyplus = Absolute(aexcey); + cexaeyplus = Absolute(cexaey); + bexdeyplus = Absolute(bexdey); + dexbeyplus = Absolute(dexbey); + permanent = ((cexdeyplus + dexceyplus) * bezplus + + (dexbeyplus + bexdeyplus) * cezplus + + (bexceyplus + cexbeyplus) * dezplus) + * Absolute(aeheight) + + ((dexaeyplus + aexdeyplus) * cezplus + + (aexceyplus + cexaeyplus) * dezplus + + (cexdeyplus + dexceyplus) * aezplus) + * Absolute(beheight) + + ((aexbeyplus + bexaeyplus) * dezplus + + (bexdeyplus + dexbeyplus) * aezplus + + (dexaeyplus + aexdeyplus) * bezplus) + * Absolute(ceheight) + + ((bexceyplus + cexbeyplus) * aezplus + + (cexaeyplus + aexceyplus) * bezplus + + (aexbeyplus + bexaeyplus) * cezplus) + * Absolute(deheight); + errbound = isperrboundA * permanent; + if ((det > errbound) || (-det > errbound)) { + return det; + } + + return orient4dadapt(pa, pb, pc, pd, pe, + aheight, bheight, cheight, dheight, eheight, permanent); +} + + + diff --git a/thirdparty/tetgen/tetgen.cxx b/thirdparty/tetgen/tetgen.cxx new file mode 100644 index 00000000..30765c7f --- /dev/null +++ b/thirdparty/tetgen/tetgen.cxx @@ -0,0 +1,31244 @@ +/////////////////////////////////////////////////////////////////////////////// +// // +// TetGen // +// // +// A Quality Tetrahedral Mesh Generator and A 3D Delaunay Triangulator // +// // +// Version 1.5 // +// November 4, 2013 // +// // +// TetGen is freely available through the website: http://www.tetgen.org. // +// It may be copied, modified, and redistributed for non-commercial use. // +// Please consult the file LICENSE for the detailed copyright notices. // +// // +/////////////////////////////////////////////////////////////////////////////// + +#include "tetgen.h" + +//// io_cxx /////////////////////////////////////////////////////////////////// +//// //// +//// //// + +/////////////////////////////////////////////////////////////////////////////// +// // +// load_node_call() Read a list of points from a file. // +// // +// 'infile' is the file handle contains the node list. It may point to a // +// .node, or .poly or .smesh file. 'markers' indicates each node contains an // +// additional marker (integer) or not. 'uvflag' indicates each node contains // +// u,v coordinates or not. It is reuqired by a PSC. 'infilename' is the name // +// of the file being read, it is only used in error messages. // +// // +// The 'firstnumber' (0 or 1) is automatically determined by the number of // +// the first index of the first point. // +// // +/////////////////////////////////////////////////////////////////////////////// + +bool tetgenio::load_node_call(FILE* infile, int markers, int uvflag, + char* infilename) +{ + char inputline[INPUTLINESIZE]; + char *stringptr; + REAL x, y, z, attrib; + int firstnode, currentmarker; + int index, attribindex; + int i, j; + + // Initialize 'pointlist', 'pointattributelist', and 'pointmarkerlist'. + pointlist = new REAL[numberofpoints * 3]; + if (pointlist == (REAL *) NULL) { + terminatetetgen(NULL, 1); + } + if (numberofpointattributes > 0) { + pointattributelist = new REAL[numberofpoints * numberofpointattributes]; + if (pointattributelist == (REAL *) NULL) { + terminatetetgen(NULL, 1); + } + } + if (markers) { + pointmarkerlist = new int[numberofpoints]; + if (pointmarkerlist == (int *) NULL) { + terminatetetgen(NULL, 1); + } + } + if (uvflag) { + pointparamlist = new pointparam[numberofpoints]; + if (pointparamlist == NULL) { + terminatetetgen(NULL, 1); + } + } + + // Read the point section. + index = 0; + attribindex = 0; + for (i = 0; i < numberofpoints; i++) { + stringptr = readnumberline(inputline, infile, infilename); + if (useindex) { + if (i == 0) { + firstnode = (int) strtol (stringptr, &stringptr, 0); + if ((firstnode == 0) || (firstnode == 1)) { + firstnumber = firstnode; + } + } + stringptr = findnextnumber(stringptr); + } // if (useindex) + if (*stringptr == '\0') { + printf("Error: Point %d has no x coordinate.\n", firstnumber + i); + break; + } + x = (REAL) strtod(stringptr, &stringptr); + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + printf("Error: Point %d has no y coordinate.\n", firstnumber + i); + break; + } + y = (REAL) strtod(stringptr, &stringptr); + if (mesh_dim == 3) { + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + printf("Error: Point %d has no z coordinate.\n", firstnumber + i); + break; + } + z = (REAL) strtod(stringptr, &stringptr); + } else { + z = 0.0; // mesh_dim == 2; + } + pointlist[index++] = x; + pointlist[index++] = y; + pointlist[index++] = z; + // Read the point attributes. + for (j = 0; j < numberofpointattributes; j++) { + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + attrib = 0.0; + } else { + attrib = (REAL) strtod(stringptr, &stringptr); + } + pointattributelist[attribindex++] = attrib; + } + if (markers) { + // Read a point marker. + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + currentmarker = 0; + } else { + currentmarker = (int) strtol (stringptr, &stringptr, 0); + } + pointmarkerlist[i] = currentmarker; + } + if (uvflag) { + // Read point paramteters. + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + printf("Error: Point %d has no uv[0].\n", firstnumber + i); + break; + } + pointparamlist[i].uv[0] = (REAL) strtod(stringptr, &stringptr); + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + printf("Error: Point %d has no uv[1].\n", firstnumber + i); + break; + } + pointparamlist[i].uv[1] = (REAL) strtod(stringptr, &stringptr); + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + printf("Error: Point %d has no tag.\n", firstnumber + i); + break; + } + pointparamlist[i].tag = (int) strtol (stringptr, &stringptr, 0); + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + printf("Error: Point %d has no type.\n", firstnumber + i); + break; + } + pointparamlist[i].type = (int) strtol (stringptr, &stringptr, 0); + if ((pointparamlist[i].type < 0) || (pointparamlist[i].type > 2)) { + printf("Error: Point %d has an invalid type.\n", firstnumber + i); + break; + } + } + } + if (i < numberofpoints) { + // Failed to read points due to some error. + delete [] pointlist; + pointlist = (REAL *) NULL; + if (markers) { + delete [] pointmarkerlist; + pointmarkerlist = (int *) NULL; + } + if (numberofpointattributes > 0) { + delete [] pointattributelist; + pointattributelist = (REAL *) NULL; + } + if (uvflag) { + delete [] pointparamlist; + pointparamlist = NULL; + } + numberofpoints = 0; + return false; + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// load_node() Load a list of points from a .node file. // +// // +/////////////////////////////////////////////////////////////////////////////// + +bool tetgenio::load_node(char* filebasename) +{ + FILE *infile; + char innodefilename[FILENAMESIZE]; + char inputline[INPUTLINESIZE]; + char *stringptr; + bool okflag; + int markers; + int uvflag; // for psc input. + + // Assembling the actual file names we want to open. + strcpy(innodefilename, filebasename); + strcat(innodefilename, ".node"); + + // Try to open a .node file. + infile = fopen(innodefilename, "r"); + if (infile == (FILE *) NULL) { + printf(" Cannot access file %s.\n", innodefilename); + return false; + } + printf("Opening %s.\n", innodefilename); + + // Set initial flags. + mesh_dim = 3; + numberofpointattributes = 0; // no point attribute. + markers = 0; // no boundary marker. + uvflag = 0; // no uv parameters (required by a PSC). + + // Read the first line of the file. + stringptr = readnumberline(inputline, infile, innodefilename); + // Does this file contain an index column? + stringptr = strstr(inputline, "rbox"); + if (stringptr == NULL) { + // Read number of points, number of dimensions, number of point + // attributes, and number of boundary markers. + stringptr = inputline; + numberofpoints = (int) strtol (stringptr, &stringptr, 0); + stringptr = findnextnumber(stringptr); + if (*stringptr != '\0') { + mesh_dim = (int) strtol (stringptr, &stringptr, 0); + } + stringptr = findnextnumber(stringptr); + if (*stringptr != '\0') { + numberofpointattributes = (int) strtol (stringptr, &stringptr, 0); + } + stringptr = findnextnumber(stringptr); + if (*stringptr != '\0') { + markers = (int) strtol (stringptr, &stringptr, 0); + } + stringptr = findnextnumber(stringptr); + if (*stringptr != '\0') { + uvflag = (int) strtol (stringptr, &stringptr, 0); + } + } else { + // It is a rbox (qhull) input file. + stringptr = inputline; + // Get the dimension. + mesh_dim = (int) strtol (stringptr, &stringptr, 0); + // Get the number of points. + stringptr = readnumberline(inputline, infile, innodefilename); + numberofpoints = (int) strtol (stringptr, &stringptr, 0); + // There is no index column. + useindex = 0; + } + + // Load the list of nodes. + okflag = load_node_call(infile, markers, uvflag, innodefilename); + + fclose(infile); + return okflag; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// load_edge() Load a list of edges from a .edge file. // +// // +/////////////////////////////////////////////////////////////////////////////// + +bool tetgenio::load_edge(char* filebasename) +{ + FILE *infile; + char inedgefilename[FILENAMESIZE]; + char inputline[INPUTLINESIZE]; + char *stringptr; + int markers, corner; + int index; + int i, j; + + strcpy(inedgefilename, filebasename); + strcat(inedgefilename, ".edge"); + + infile = fopen(inedgefilename, "r"); + if (infile != (FILE *) NULL) { + printf("Opening %s.\n", inedgefilename); + } else { + //printf(" Cannot access file %s.\n", inedgefilename); + return false; + } + + // Read number of boundary edges. + stringptr = readnumberline(inputline, infile, inedgefilename); + numberofedges = (int) strtol (stringptr, &stringptr, 0); + if (numberofedges > 0) { + edgelist = new int[numberofedges * 2]; + if (edgelist == (int *) NULL) { + terminatetetgen(NULL, 1); + } + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + markers = 0; // Default value. + } else { + markers = (int) strtol (stringptr, &stringptr, 0); + } + if (markers > 0) { + edgemarkerlist = new int[numberofedges]; + } + } + + // Read the list of edges. + index = 0; + for (i = 0; i < numberofedges; i++) { + // Read edge index and the edge's two endpoints. + stringptr = readnumberline(inputline, infile, inedgefilename); + for (j = 0; j < 2; j++) { + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + printf("Error: Edge %d is missing vertex %d in %s.\n", + i + firstnumber, j + 1, inedgefilename); + terminatetetgen(NULL, 1); + } + corner = (int) strtol(stringptr, &stringptr, 0); + if (corner < firstnumber || corner >= numberofpoints + firstnumber) { + printf("Error: Edge %d has an invalid vertex index.\n", + i + firstnumber); + terminatetetgen(NULL, 1); + } + edgelist[index++] = corner; + } + if (numberofcorners == 10) { + // Skip an extra vertex (generated by a previous -o2 option). + stringptr = findnextnumber(stringptr); + } + // Read the edge marker if it has. + if (markers) { + stringptr = findnextnumber(stringptr); + edgemarkerlist[i] = (int) strtol(stringptr, &stringptr, 0); + } + } + + fclose(infile); + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// load_face() Load a list of faces (triangles) from a .face file. // +// // +/////////////////////////////////////////////////////////////////////////////// + +bool tetgenio::load_face(char* filebasename) +{ + FILE *infile; + char infilename[FILENAMESIZE]; + char inputline[INPUTLINESIZE]; + char *stringptr; + REAL attrib; + int markers, corner; + int index; + int i, j; + + strcpy(infilename, filebasename); + strcat(infilename, ".face"); + + infile = fopen(infilename, "r"); + if (infile != (FILE *) NULL) { + printf("Opening %s.\n", infilename); + } else { + return false; + } + + // Read number of faces, boundary markers. + stringptr = readnumberline(inputline, infile, infilename); + numberoftrifaces = (int) strtol (stringptr, &stringptr, 0); + stringptr = findnextnumber(stringptr); + if (mesh_dim == 2) { + // Skip a number. + stringptr = findnextnumber(stringptr); + } + if (*stringptr == '\0') { + markers = 0; // Default there is no marker per face. + } else { + markers = (int) strtol (stringptr, &stringptr, 0); + } + if (numberoftrifaces > 0) { + trifacelist = new int[numberoftrifaces * 3]; + if (trifacelist == (int *) NULL) { + terminatetetgen(NULL, 1); + } + if (markers) { + trifacemarkerlist = new int[numberoftrifaces]; + if (trifacemarkerlist == (int *) NULL) { + terminatetetgen(NULL, 1); + } + } + } + + // Read the list of faces. + index = 0; + for (i = 0; i < numberoftrifaces; i++) { + // Read face index and the face's three corners. + stringptr = readnumberline(inputline, infile, infilename); + for (j = 0; j < 3; j++) { + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + printf("Error: Face %d is missing vertex %d in %s.\n", + i + firstnumber, j + 1, infilename); + terminatetetgen(NULL, 1); + } + corner = (int) strtol(stringptr, &stringptr, 0); + if (corner < firstnumber || corner >= numberofpoints + firstnumber) { + printf("Error: Face %d has an invalid vertex index.\n", + i + firstnumber); + terminatetetgen(NULL, 1); + } + trifacelist[index++] = corner; + } + if (numberofcorners == 10) { + // Skip 3 extra vertices (generated by a previous -o2 option). + for (j = 0; j < 3; j++) { + stringptr = findnextnumber(stringptr); + } + } + // Read the boundary marker if it exists. + if (markers) { + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + attrib = 0.0; + } else { + attrib = (REAL) strtod(stringptr, &stringptr); + } + trifacemarkerlist[i] = (int) attrib; + } + } + + fclose(infile); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// load_tet() Load a list of tetrahedra from a .ele file. // +// // +/////////////////////////////////////////////////////////////////////////////// + +bool tetgenio::load_tet(char* filebasename) +{ + FILE *infile; + char infilename[FILENAMESIZE]; + char inputline[INPUTLINESIZE]; + char *stringptr; + REAL attrib; + int corner; + int index, attribindex; + int i, j; + + strcpy(infilename, filebasename); + strcat(infilename, ".ele"); + + infile = fopen(infilename, "r"); + if (infile != (FILE *) NULL) { + printf("Opening %s.\n", infilename); + } else { + return false; + } + + // Read number of elements, number of corners (4 or 10), number of + // element attributes. + stringptr = readnumberline(inputline, infile, infilename); + numberoftetrahedra = (int) strtol (stringptr, &stringptr, 0); + if (numberoftetrahedra <= 0) { + printf("Error: Invalid number of tetrahedra.\n"); + fclose(infile); + return false; + } + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + numberofcorners = 4; // Default read 4 nodes per element. + } else { + numberofcorners = (int) strtol(stringptr, &stringptr, 0); + } + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + numberoftetrahedronattributes = 0; // Default no attribute. + } else { + numberoftetrahedronattributes = (int) strtol(stringptr, &stringptr, 0); + } + if (numberofcorners != 4 && numberofcorners != 10) { + printf("Error: Wrong number of corners %d (should be 4 or 10).\n", + numberofcorners); + fclose(infile); + return false; + } + + // Allocate memory for tetrahedra. + tetrahedronlist = new int[numberoftetrahedra * numberofcorners]; + if (tetrahedronlist == (int *) NULL) { + terminatetetgen(NULL, 1); + } + // Allocate memory for output tetrahedron attributes if necessary. + if (numberoftetrahedronattributes > 0) { + tetrahedronattributelist = new REAL[numberoftetrahedra * + numberoftetrahedronattributes]; + if (tetrahedronattributelist == (REAL *) NULL) { + terminatetetgen(NULL, 1); + } + } + + // Read the list of tetrahedra. + index = 0; + attribindex = 0; + for (i = 0; i < numberoftetrahedra; i++) { + // Read tetrahedron index and the tetrahedron's corners. + stringptr = readnumberline(inputline, infile, infilename); + for (j = 0; j < numberofcorners; j++) { + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + printf("Error: Tetrahedron %d is missing vertex %d in %s.\n", + i + firstnumber, j + 1, infilename); + terminatetetgen(NULL, 1); + } + corner = (int) strtol(stringptr, &stringptr, 0); + if (corner < firstnumber || corner >= numberofpoints + firstnumber) { + printf("Error: Tetrahedron %d has an invalid vertex index.\n", + i + firstnumber); + terminatetetgen(NULL, 1); + } + tetrahedronlist[index++] = corner; + } + // Read the tetrahedron's attributes. + for (j = 0; j < numberoftetrahedronattributes; j++) { + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + attrib = 0.0; + } else { + attrib = (REAL) strtod(stringptr, &stringptr); + } + tetrahedronattributelist[attribindex++] = attrib; + } + } + + fclose(infile); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// load_vol() Load a list of volume constraints from a .vol file. // +// // +/////////////////////////////////////////////////////////////////////////////// + +bool tetgenio::load_vol(char* filebasename) +{ + FILE *infile; + char inelefilename[FILENAMESIZE]; + char infilename[FILENAMESIZE]; + char inputline[INPUTLINESIZE]; + char *stringptr; + REAL volume; + int volelements; + int i; + + strcpy(infilename, filebasename); + strcat(infilename, ".vol"); + + infile = fopen(infilename, "r"); + if (infile != (FILE *) NULL) { + printf("Opening %s.\n", infilename); + } else { + return false; + } + + // Read number of tetrahedra. + stringptr = readnumberline(inputline, infile, infilename); + volelements = (int) strtol (stringptr, &stringptr, 0); + if (volelements != numberoftetrahedra) { + strcpy(inelefilename, filebasename); + strcat(infilename, ".ele"); + printf("Warning: %s and %s disagree on number of tetrahedra.\n", + inelefilename, infilename); + fclose(infile); + return false; + } + + tetrahedronvolumelist = new REAL[volelements]; + if (tetrahedronvolumelist == (REAL *) NULL) { + terminatetetgen(NULL, 1); + } + + // Read the list of volume constraints. + for (i = 0; i < volelements; i++) { + stringptr = readnumberline(inputline, infile, infilename); + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + volume = -1.0; // No constraint on this tetrahedron. + } else { + volume = (REAL) strtod(stringptr, &stringptr); + } + tetrahedronvolumelist[i] = volume; + } + + fclose(infile); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// load_var() Load constraints applied on facets, segments, and nodes // +// from a .var file. // +// // +/////////////////////////////////////////////////////////////////////////////// + +bool tetgenio::load_var(char* filebasename) +{ + FILE *infile; + char varfilename[FILENAMESIZE]; + char inputline[INPUTLINESIZE]; + char *stringptr; + int index; + int i; + + // Variant constraints are saved in file "filename.var". + strcpy(varfilename, filebasename); + strcat(varfilename, ".var"); + infile = fopen(varfilename, "r"); + if (infile != (FILE *) NULL) { + printf("Opening %s.\n", varfilename); + } else { + return false; + } + + // Read the facet constraint section. + stringptr = readnumberline(inputline, infile, varfilename); + if (*stringptr != '\0') { + numberoffacetconstraints = (int) strtol (stringptr, &stringptr, 0); + } else { + numberoffacetconstraints = 0; + } + if (numberoffacetconstraints > 0) { + // Initialize 'facetconstraintlist'. + facetconstraintlist = new REAL[numberoffacetconstraints * 2]; + index = 0; + for (i = 0; i < numberoffacetconstraints; i++) { + stringptr = readnumberline(inputline, infile, varfilename); + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + printf("Error: facet constraint %d has no facet marker.\n", + firstnumber + i); + break; + } else { + facetconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr); + } + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + printf("Error: facet constraint %d has no maximum area bound.\n", + firstnumber + i); + break; + } else { + facetconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr); + } + } + if (i < numberoffacetconstraints) { + // This must be caused by an error. + fclose(infile); + return false; + } + } + + // Read the segment constraint section. + stringptr = readnumberline(inputline, infile, varfilename); + if (*stringptr != '\0') { + numberofsegmentconstraints = (int) strtol (stringptr, &stringptr, 0); + } else { + numberofsegmentconstraints = 0; + } + if (numberofsegmentconstraints > 0) { + // Initialize 'segmentconstraintlist'. + segmentconstraintlist = new REAL[numberofsegmentconstraints * 3]; + index = 0; + for (i = 0; i < numberofsegmentconstraints; i++) { + stringptr = readnumberline(inputline, infile, varfilename); + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + printf("Error: segment constraint %d has no frist endpoint.\n", + firstnumber + i); + break; + } else { + segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr); + } + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + printf("Error: segment constraint %d has no second endpoint.\n", + firstnumber + i); + break; + } else { + segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr); + } + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + printf("Error: segment constraint %d has no maximum length bound.\n", + firstnumber + i); + break; + } else { + segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr); + } + } + if (i < numberofsegmentconstraints) { + // This must be caused by an error. + fclose(infile); + return false; + } + } + + fclose(infile); + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// load_mtr() Load a size specification map from a .mtr file. // +// // +/////////////////////////////////////////////////////////////////////////////// + +bool tetgenio::load_mtr(char* filebasename) +{ + FILE *infile; + char mtrfilename[FILENAMESIZE]; + char inputline[INPUTLINESIZE]; + char *stringptr; + REAL mtr; + int ptnum; + int mtrindex; + int i, j; + + strcpy(mtrfilename, filebasename); + strcat(mtrfilename, ".mtr"); + infile = fopen(mtrfilename, "r"); + if (infile != (FILE *) NULL) { + printf("Opening %s.\n", mtrfilename); + } else { + return false; + } + + // Read the number of points. + stringptr = readnumberline(inputline, infile, mtrfilename); + ptnum = (int) strtol (stringptr, &stringptr, 0); + if (ptnum != numberofpoints) { + printf(" !! Point numbers are not equal. Ignored.\n"); + fclose(infile); + return false; + } + // Read the number of columns (1, 3, or 6). + stringptr = findnextnumber(stringptr); // Skip number of points. + if (*stringptr != '\0') { + numberofpointmtrs = (int) strtol (stringptr, &stringptr, 0); + } + if (numberofpointmtrs == 0) { + // Column number doesn't match. Set a default number (1). + numberofpointmtrs = 1; + } + + // Allocate space for pointmtrlist. + pointmtrlist = new REAL[numberofpoints * numberofpointmtrs]; + if (pointmtrlist == (REAL *) NULL) { + terminatetetgen(NULL, 1); + } + mtrindex = 0; + for (i = 0; i < numberofpoints; i++) { + // Read metrics. + stringptr = readnumberline(inputline, infile, mtrfilename); + for (j = 0; j < numberofpointmtrs; j++) { + if (*stringptr == '\0') { + printf("Error: Metric %d is missing value #%d in %s.\n", + i + firstnumber, j + 1, mtrfilename); + terminatetetgen(NULL, 1); + } + mtr = (REAL) strtod(stringptr, &stringptr); + pointmtrlist[mtrindex++] = mtr; + stringptr = findnextnumber(stringptr); + } + } + + fclose(infile); + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// load_poly() Load a PL complex from a .poly or a .smesh file. // +// // +/////////////////////////////////////////////////////////////////////////////// + +bool tetgenio::load_poly(char* filebasename) +{ + FILE *infile; + char inpolyfilename[FILENAMESIZE]; + char insmeshfilename[FILENAMESIZE]; + char inputline[INPUTLINESIZE]; + char *stringptr, *infilename; + int smesh, markers, uvflag, currentmarker; + int index; + int i, j, k; + + // Assembling the actual file names we want to open. + strcpy(inpolyfilename, filebasename); + strcpy(insmeshfilename, filebasename); + strcat(inpolyfilename, ".poly"); + strcat(insmeshfilename, ".smesh"); + + // First assume it is a .poly file. + smesh = 0; + // Try to open a .poly file. + infile = fopen(inpolyfilename, "r"); + if (infile == (FILE *) NULL) { + // .poly doesn't exist! Try to open a .smesh file. + infile = fopen(insmeshfilename, "r"); + if (infile == (FILE *) NULL) { + printf(" Cannot access file %s and %s.\n", + inpolyfilename, insmeshfilename); + return false; + } else { + printf("Opening %s.\n", insmeshfilename); + infilename = insmeshfilename; + } + smesh = 1; + } else { + printf("Opening %s.\n", inpolyfilename); + infilename = inpolyfilename; + } + + // Initialize the default values. + mesh_dim = 3; // Three-dimensional coordinates. + numberofpointattributes = 0; // no point attribute. + markers = 0; // no boundary marker. + uvflag = 0; // no uv parameters (required by a PSC). + + // Read number of points, number of dimensions, number of point + // attributes, and number of boundary markers. + stringptr = readnumberline(inputline, infile, infilename); + numberofpoints = (int) strtol (stringptr, &stringptr, 0); + stringptr = findnextnumber(stringptr); + if (*stringptr != '\0') { + mesh_dim = (int) strtol (stringptr, &stringptr, 0); + } + stringptr = findnextnumber(stringptr); + if (*stringptr != '\0') { + numberofpointattributes = (int) strtol (stringptr, &stringptr, 0); + } + stringptr = findnextnumber(stringptr); + if (*stringptr != '\0') { + markers = (int) strtol (stringptr, &stringptr, 0); + } + if (*stringptr != '\0') { + uvflag = (int) strtol (stringptr, &stringptr, 0); + } + + if (numberofpoints > 0) { + // Load the list of nodes. + if (!load_node_call(infile, markers, uvflag, infilename)) { + fclose(infile); + return false; + } + } else { + // If the .poly or .smesh file claims there are zero points, that + // means the points should be read from a separate .node file. + if (!load_node(filebasename)) { + fclose(infile); + return false; + } + } + + if ((mesh_dim != 3) && (mesh_dim != 2)) { + printf("Input error: TetGen only works for 2D & 3D point sets.\n"); + fclose(infile); + return false; + } + if (numberofpoints < (mesh_dim + 1)) { + printf("Input error: TetGen needs at least %d points.\n", mesh_dim + 1); + fclose(infile); + return false; + } + + facet *f; + polygon *p; + + if (mesh_dim == 3) { + + // Read number of facets and number of boundary markers. + stringptr = readnumberline(inputline, infile, infilename); + if (stringptr == NULL) { + // No facet list, return. + fclose(infile); + return true; + } + numberoffacets = (int) strtol (stringptr, &stringptr, 0); + if (numberoffacets <= 0) { + // No facet list, return. + fclose(infile); + return true; + } + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + markers = 0; // no boundary marker. + } else { + markers = (int) strtol (stringptr, &stringptr, 0); + } + + // Initialize the 'facetlist', 'facetmarkerlist'. + facetlist = new facet[numberoffacets]; + if (markers == 1) { + facetmarkerlist = new int[numberoffacets]; + } + + // Read data into 'facetlist', 'facetmarkerlist'. + if (smesh == 0) { + // Facets are in .poly file format. + for (i = 1; i <= numberoffacets; i++) { + f = &(facetlist[i - 1]); + init(f); + f->numberofholes = 0; + currentmarker = 0; + // Read number of polygons, number of holes, and a boundary marker. + stringptr = readnumberline(inputline, infile, infilename); + f->numberofpolygons = (int) strtol (stringptr, &stringptr, 0); + stringptr = findnextnumber(stringptr); + if (*stringptr != '\0') { + f->numberofholes = (int) strtol (stringptr, &stringptr, 0); + if (markers == 1) { + stringptr = findnextnumber(stringptr); + if (*stringptr != '\0') { + currentmarker = (int) strtol(stringptr, &stringptr, 0); + } + } + } + // Initialize facetmarker if it needs. + if (markers == 1) { + facetmarkerlist[i - 1] = currentmarker; + } + // Each facet should has at least one polygon. + if (f->numberofpolygons <= 0) { + printf("Error: Wrong number of polygon in %d facet.\n", i); + break; + } + // Initialize the 'f->polygonlist'. + f->polygonlist = new polygon[f->numberofpolygons]; + // Go through all polygons, read in their vertices. + for (j = 1; j <= f->numberofpolygons; j++) { + p = &(f->polygonlist[j - 1]); + init(p); + // Read number of vertices of this polygon. + stringptr = readnumberline(inputline, infile, infilename); + p->numberofvertices = (int) strtol(stringptr, &stringptr, 0); + if (p->numberofvertices < 1) { + printf("Error: Wrong polygon %d in facet %d\n", j, i); + break; + } + // Initialize 'p->vertexlist'. + p->vertexlist = new int[p->numberofvertices]; + // Read all vertices of this polygon. + for (k = 1; k <= p->numberofvertices; k++) { + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + // Try to load another non-empty line and continue to read the + // rest of vertices. + stringptr = readnumberline(inputline, infile, infilename); + if (*stringptr == '\0') { + printf("Error: Missing %d endpoints of polygon %d in facet %d", + p->numberofvertices - k, j, i); + break; + } + } + p->vertexlist[k - 1] = (int) strtol (stringptr, &stringptr, 0); + } + } + if (j <= f->numberofpolygons) { + // This must be caused by an error. However, there're j - 1 + // polygons have been read. Reset the 'f->numberofpolygon'. + if (j == 1) { + // This is the first polygon. + delete [] f->polygonlist; + } + f->numberofpolygons = j - 1; + // No hole will be read even it exists. + f->numberofholes = 0; + break; + } + // If this facet has hole pints defined, read them. + if (f->numberofholes > 0) { + // Initialize 'f->holelist'. + f->holelist = new REAL[f->numberofholes * 3]; + // Read the holes' coordinates. + index = 0; + for (j = 1; j <= f->numberofholes; j++) { + stringptr = readnumberline(inputline, infile, infilename); + for (k = 1; k <= 3; k++) { + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + printf("Error: Hole %d in facet %d has no coordinates", j, i); + break; + } + f->holelist[index++] = (REAL) strtod (stringptr, &stringptr); + } + if (k <= 3) { + // This must be caused by an error. + break; + } + } + if (j <= f->numberofholes) { + // This must be caused by an error. + break; + } + } + } + if (i <= numberoffacets) { + // This must be caused by an error. + numberoffacets = i - 1; + fclose(infile); + return false; + } + } else { // poly == 0 + // Read the facets from a .smesh file. + for (i = 1; i <= numberoffacets; i++) { + f = &(facetlist[i - 1]); + init(f); + // Initialize 'f->facetlist'. In a .smesh file, each facetlist only + // contains exactly one polygon, no hole. + f->numberofpolygons = 1; + f->polygonlist = new polygon[f->numberofpolygons]; + p = &(f->polygonlist[0]); + init(p); + // Read number of vertices of this polygon. + stringptr = readnumberline(inputline, infile, insmeshfilename); + p->numberofvertices = (int) strtol (stringptr, &stringptr, 0); + if (p->numberofvertices < 1) { + printf("Error: Wrong number of vertex in facet %d\n", i); + break; + } + // Initialize 'p->vertexlist'. + p->vertexlist = new int[p->numberofvertices]; + for (k = 1; k <= p->numberofvertices; k++) { + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + // Try to load another non-empty line and continue to read the + // rest of vertices. + stringptr = readnumberline(inputline, infile, infilename); + if (*stringptr == '\0') { + printf("Error: Missing %d endpoints in facet %d", + p->numberofvertices - k, i); + break; + } + } + p->vertexlist[k - 1] = (int) strtol (stringptr, &stringptr, 0); + } + if (k <= p->numberofvertices) { + // This must be caused by an error. + break; + } + // Read facet's boundary marker at last. + if (markers == 1) { + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + currentmarker = 0; + } else { + currentmarker = (int) strtol(stringptr, &stringptr, 0); + } + facetmarkerlist[i - 1] = currentmarker; + } + } + if (i <= numberoffacets) { + // This must be caused by an error. + numberoffacets = i - 1; + fclose(infile); + return false; + } + } + + // Read the hole section. + stringptr = readnumberline(inputline, infile, infilename); + if (stringptr == NULL) { + // No hole list, return. + fclose(infile); + return true; + } + if (*stringptr != '\0') { + numberofholes = (int) strtol (stringptr, &stringptr, 0); + } else { + numberofholes = 0; + } + if (numberofholes > 0) { + // Initialize 'holelist'. + holelist = new REAL[numberofholes * 3]; + for (i = 0; i < 3 * numberofholes; i += 3) { + stringptr = readnumberline(inputline, infile, infilename); + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + printf("Error: Hole %d has no x coord.\n", firstnumber + (i / 3)); + break; + } else { + holelist[i] = (REAL) strtod(stringptr, &stringptr); + } + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + printf("Error: Hole %d has no y coord.\n", firstnumber + (i / 3)); + break; + } else { + holelist[i + 1] = (REAL) strtod(stringptr, &stringptr); + } + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + printf("Error: Hole %d has no z coord.\n", firstnumber + (i / 3)); + break; + } else { + holelist[i + 2] = (REAL) strtod(stringptr, &stringptr); + } + } + if (i < 3 * numberofholes) { + // This must be caused by an error. + fclose(infile); + return false; + } + } + + // Read the region section. The 'region' section is optional, if we + // don't reach the end-of-file, try read it in. + stringptr = readnumberline(inputline, infile, NULL); + if (stringptr != (char *) NULL && *stringptr != '\0') { + numberofregions = (int) strtol (stringptr, &stringptr, 0); + } else { + numberofregions = 0; + } + if (numberofregions > 0) { + // Initialize 'regionlist'. + regionlist = new REAL[numberofregions * 5]; + index = 0; + for (i = 0; i < numberofregions; i++) { + stringptr = readnumberline(inputline, infile, infilename); + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + printf("Error: Region %d has no x coordinate.\n", firstnumber + i); + break; + } else { + regionlist[index++] = (REAL) strtod(stringptr, &stringptr); + } + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + printf("Error: Region %d has no y coordinate.\n", firstnumber + i); + break; + } else { + regionlist[index++] = (REAL) strtod(stringptr, &stringptr); + } + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + printf("Error: Region %d has no z coordinate.\n", firstnumber + i); + break; + } else { + regionlist[index++] = (REAL) strtod(stringptr, &stringptr); + } + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + printf("Error: Region %d has no region attrib.\n", firstnumber + i); + break; + } else { + regionlist[index++] = (REAL) strtod(stringptr, &stringptr); + } + stringptr = findnextnumber(stringptr); + if (*stringptr == '\0') { + regionlist[index] = regionlist[index - 1]; + } else { + regionlist[index] = (REAL) strtod(stringptr, &stringptr); + } + index++; + } + if (i < numberofregions) { + // This must be caused by an error. + fclose(infile); + return false; + } + } + + } else { + + // Read a PSLG from Triangle's poly file. + assert(mesh_dim == 2); + // A PSLG is a facet of a PLC. + numberoffacets = 1; + // Initialize the 'facetlist'. + facetlist = new facet[numberoffacets]; + facetmarkerlist = (int *) NULL; // No facet markers. + f = &(facetlist[0]); + init(f); + // Read number of segments. + stringptr = readnumberline(inputline, infile, infilename); + // Segments are degenerate polygons. + f->numberofpolygons = (int) strtol (stringptr, &stringptr, 0); + if (f->numberofpolygons > 0) { + f->polygonlist = new polygon[f->numberofpolygons]; + } + // Go through all segments, read in their vertices. + for (j = 0; j < f->numberofpolygons; j++) { + p = &(f->polygonlist[j]); + init(p); + // Read in a segment. + stringptr = readnumberline(inputline, infile, infilename); + stringptr = findnextnumber(stringptr); // Skip its index. + p->numberofvertices = 2; // A segment always has two vertices. + p->vertexlist = new int[p->numberofvertices]; + p->vertexlist[0] = (int) strtol (stringptr, &stringptr, 0); + stringptr = findnextnumber(stringptr); + p->vertexlist[1] = (int) strtol (stringptr, &stringptr, 0); + } + // Read number of holes. + stringptr = readnumberline(inputline, infile, infilename); + f->numberofholes = (int) strtol (stringptr, &stringptr, 0); + if (f->numberofholes > 0) { + // Initialize 'f->holelist'. + f->holelist = new REAL[f->numberofholes * 3]; + // Read the holes' coordinates. + for (j = 0; j < f->numberofholes; j++) { + // Read a 2D hole point. + stringptr = readnumberline(inputline, infile, infilename); + stringptr = findnextnumber(stringptr); // Skip its index. + f->holelist[j * 3] = (REAL) strtod (stringptr, &stringptr); + stringptr = findnextnumber(stringptr); + f->holelist[j * 3 + 1] = (REAL) strtod (stringptr, &stringptr); + f->holelist[j * 3 + 2] = 0.0; // The z-coord. + } + } + // The regions are skipped. + + } + + // End of reading poly/smesh file. + fclose(infile); + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// load_off() Load a polyhedron from a .off file. // +// // +// The .off format is one of file formats of the Geomview, an interactive // +// program for viewing and manipulating geometric objects. More information // +// is available form: http://www.geomview.org. // +// // +/////////////////////////////////////////////////////////////////////////////// + +bool tetgenio::load_off(char* filebasename) +{ + FILE *fp; + tetgenio::facet *f; + tetgenio::polygon *p; + char infilename[FILENAMESIZE]; + char buffer[INPUTLINESIZE]; + char *bufferp; + double *coord; + int nverts = 0, iverts = 0; + int nfaces = 0, ifaces = 0; + int nedges = 0; + int line_count = 0, i; + + // Default, the off file's index is from '0'. We check it by remembering the + // smallest index we found in the file. It should be either 0 or 1. + int smallestidx = 0; + + strncpy(infilename, filebasename, 1024 - 1); + infilename[FILENAMESIZE - 1] = '\0'; + if (infilename[0] == '\0') { + printf("Error: No filename.\n"); + return false; + } + if (strcmp(&infilename[strlen(infilename) - 4], ".off") != 0) { + strcat(infilename, ".off"); + } + + if (!(fp = fopen(infilename, "r"))) { + printf(" Unable to open file %s\n", infilename); + return false; + } + printf("Opening %s.\n", infilename); + + while ((bufferp = readline(buffer, fp, &line_count)) != NULL) { + // Check section + if (nverts == 0) { + // Read header + bufferp = strstr(bufferp, "OFF"); + if (bufferp != NULL) { + // Read mesh counts + bufferp = findnextnumber(bufferp); // Skip field "OFF". + if (*bufferp == '\0') { + // Read a non-empty line. + bufferp = readline(buffer, fp, &line_count); + } + if ((sscanf(bufferp, "%d%d%d", &nverts, &nfaces, &nedges) != 3) + || (nverts == 0)) { + printf("Syntax error reading header on line %d in file %s\n", + line_count, infilename); + fclose(fp); + return false; + } + // Allocate memory for 'tetgenio' + if (nverts > 0) { + numberofpoints = nverts; + pointlist = new REAL[nverts * 3]; + smallestidx = nverts + 1; // A bigger enough number. + } + if (nfaces > 0) { + numberoffacets = nfaces; + facetlist = new tetgenio::facet[nfaces]; + } + } + } else if (iverts < nverts) { + // Read vertex coordinates + coord = &pointlist[iverts * 3]; + for (i = 0; i < 3; i++) { + if (*bufferp == '\0') { + printf("Syntax error reading vertex coords on line %d in file %s\n", + line_count, infilename); + fclose(fp); + return false; + } + coord[i] = (REAL) strtod(bufferp, &bufferp); + bufferp = findnextnumber(bufferp); + } + iverts++; + } else if (ifaces < nfaces) { + // Get next face + f = &facetlist[ifaces]; + init(f); + // In .off format, each facet has one polygon, no hole. + f->numberofpolygons = 1; + f->polygonlist = new tetgenio::polygon[1]; + p = &f->polygonlist[0]; + init(p); + // Read the number of vertices, it should be greater than 0. + p->numberofvertices = (int) strtol(bufferp, &bufferp, 0); + if (p->numberofvertices == 0) { + printf("Syntax error reading polygon on line %d in file %s\n", + line_count, infilename); + fclose(fp); + return false; + } + // Allocate memory for face vertices + p->vertexlist = new int[p->numberofvertices]; + for (i = 0; i < p->numberofvertices; i++) { + bufferp = findnextnumber(bufferp); + if (*bufferp == '\0') { + printf("Syntax error reading polygon on line %d in file %s\n", + line_count, infilename); + fclose(fp); + return false; + } + p->vertexlist[i] = (int) strtol(bufferp, &bufferp, 0); + // Detect the smallest index. + if (p->vertexlist[i] < smallestidx) { + smallestidx = p->vertexlist[i]; + } + } + ifaces++; + } else { + // Should never get here + printf("Found extra text starting at line %d in file %s\n", line_count, + infilename); + break; + } + } + + // Close file + fclose(fp); + + // Decide the firstnumber of the index. + if (smallestidx == 0) { + firstnumber = 0; + } else if (smallestidx == 1) { + firstnumber = 1; + } else { + printf("A wrong smallest index (%d) was detected in file %s\n", + smallestidx, infilename); + return false; + } + + if (iverts != nverts) { + printf("Expected %d vertices, but read only %d vertices in file %s\n", + nverts, iverts, infilename); + return false; + } + if (ifaces != nfaces) { + printf("Expected %d faces, but read only %d faces in file %s\n", + nfaces, ifaces, infilename); + return false; + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// load_ply() Load a polyhedron from a .ply file. // +// // +// This is a simplified version of reading .ply files, which only reads the // +// set of vertices and the set of faces. Other informations (such as color, // +// material, texture, etc) in .ply file are ignored. Complete routines for // +// reading and writing ,ply files are available from: http://www.cc.gatech. // +// edu/projects/large_models/ply.html. Except the header section, ply file // +// format has exactly the same format for listing vertices and polygons as // +// off file format. // +// // +/////////////////////////////////////////////////////////////////////////////// + +bool tetgenio::load_ply(char* filebasename) +{ + FILE *fp; + tetgenio::facet *f; + tetgenio::polygon *p; + char infilename[FILENAMESIZE]; + char buffer[INPUTLINESIZE]; + char *bufferp, *str; + double *coord; + int endheader = 0, format = 0; + int nverts = 0, iverts = 0; + int nfaces = 0, ifaces = 0; + int line_count = 0, i; + + // Default, the ply file's index is from '0'. We check it by remembering the + // smallest index we found in the file. It should be either 0 or 1. + int smallestidx = 0; + + strncpy(infilename, filebasename, FILENAMESIZE - 1); + infilename[FILENAMESIZE - 1] = '\0'; + if (infilename[0] == '\0') { + printf("Error: No filename.\n"); + return false; + } + if (strcmp(&infilename[strlen(infilename) - 4], ".ply") != 0) { + strcat(infilename, ".ply"); + } + + if (!(fp = fopen(infilename, "r"))) { + printf("Error: Unable to open file %s\n", infilename); + return false; + } + printf("Opening %s.\n", infilename); + + while ((bufferp = readline(buffer, fp, &line_count)) != NULL) { + if (!endheader) { + // Find if it is the keyword "end_header". + str = strstr(bufferp, "end_header"); + // strstr() is case sensitive. + if (!str) str = strstr(bufferp, "End_header"); + if (!str) str = strstr(bufferp, "End_Header"); + if (str) { + // This is the end of the header section. + endheader = 1; + continue; + } + // Parse the number of vertices and the number of faces. + if (nverts == 0 || nfaces == 0) { + // Find if it si the keyword "element". + str = strstr(bufferp, "element"); + if (!str) str = strstr(bufferp, "Element"); + if (str) { + bufferp = findnextfield(str); + if (*bufferp == '\0') { + printf("Syntax error reading element type on line%d in file %s\n", + line_count, infilename); + fclose(fp); + return false; + } + if (nverts == 0) { + // Find if it is the keyword "vertex". + str = strstr(bufferp, "vertex"); + if (!str) str = strstr(bufferp, "Vertex"); + if (str) { + bufferp = findnextnumber(str); + if (*bufferp == '\0') { + printf("Syntax error reading vertex number on line"); + printf(" %d in file %s\n", line_count, infilename); + fclose(fp); + return false; + } + nverts = (int) strtol(bufferp, &bufferp, 0); + // Allocate memory for 'tetgenio' + if (nverts > 0) { + numberofpoints = nverts; + pointlist = new REAL[nverts * 3]; + smallestidx = nverts + 1; // A big enough index. + } + } + } + if (nfaces == 0) { + // Find if it is the keyword "face". + str = strstr(bufferp, "face"); + if (!str) str = strstr(bufferp, "Face"); + if (str) { + bufferp = findnextnumber(str); + if (*bufferp == '\0') { + printf("Syntax error reading face number on line"); + printf(" %d in file %s\n", line_count, infilename); + fclose(fp); + return false; + } + nfaces = (int) strtol(bufferp, &bufferp, 0); + // Allocate memory for 'tetgenio' + if (nfaces > 0) { + numberoffacets = nfaces; + facetlist = new tetgenio::facet[nfaces]; + } + } + } + } // It is not the string "element". + } + if (format == 0) { + // Find the keyword "format". + str = strstr(bufferp, "format"); + if (!str) str = strstr(bufferp, "Format"); + if (str) { + format = 1; + bufferp = findnextfield(str); + // Find if it is the string "ascii". + str = strstr(bufferp, "ascii"); + if (!str) str = strstr(bufferp, "ASCII"); + if (!str) { + printf("This routine only reads ascii format of ply files.\n"); + printf("Hint: You can convert the binary to ascii format by\n"); + printf(" using the provided ply tools:\n"); + printf(" ply2ascii < %s > ascii_%s\n", infilename, infilename); + fclose(fp); + return false; + } + } + } + } else if (iverts < nverts) { + // Read vertex coordinates + coord = &pointlist[iverts * 3]; + for (i = 0; i < 3; i++) { + if (*bufferp == '\0') { + printf("Syntax error reading vertex coords on line %d in file %s\n", + line_count, infilename); + fclose(fp); + return false; + } + coord[i] = (REAL) strtod(bufferp, &bufferp); + bufferp = findnextnumber(bufferp); + } + iverts++; + } else if (ifaces < nfaces) { + // Get next face + f = &facetlist[ifaces]; + init(f); + // In .off format, each facet has one polygon, no hole. + f->numberofpolygons = 1; + f->polygonlist = new tetgenio::polygon[1]; + p = &f->polygonlist[0]; + init(p); + // Read the number of vertices, it should be greater than 0. + p->numberofvertices = (int) strtol(bufferp, &bufferp, 0); + if (p->numberofvertices == 0) { + printf("Syntax error reading polygon on line %d in file %s\n", + line_count, infilename); + fclose(fp); + return false; + } + // Allocate memory for face vertices + p->vertexlist = new int[p->numberofvertices]; + for (i = 0; i < p->numberofvertices; i++) { + bufferp = findnextnumber(bufferp); + if (*bufferp == '\0') { + printf("Syntax error reading polygon on line %d in file %s\n", + line_count, infilename); + fclose(fp); + return false; + } + p->vertexlist[i] = (int) strtol(bufferp, &bufferp, 0); + if (p->vertexlist[i] < smallestidx) { + smallestidx = p->vertexlist[i]; + } + } + ifaces++; + } else { + // Should never get here + printf("Found extra text starting at line %d in file %s\n", line_count, + infilename); + break; + } + } + + // Close file + fclose(fp); + + // Decide the firstnumber of the index. + if (smallestidx == 0) { + firstnumber = 0; + } else if (smallestidx == 1) { + firstnumber = 1; + } else { + printf("A wrong smallest index (%d) was detected in file %s\n", + smallestidx, infilename); + return false; + } + + if (iverts != nverts) { + printf("Expected %d vertices, but read only %d vertices in file %s\n", + nverts, iverts, infilename); + return false; + } + if (ifaces != nfaces) { + printf("Expected %d faces, but read only %d faces in file %s\n", + nfaces, ifaces, infilename); + return false; + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// load_stl() Load a surface mesh from a .stl file. // +// // +// The .stl or stereolithography format is an ASCII or binary file used in // +// manufacturing. It is a list of the triangular surfaces that describe a // +// computer generated solid model. This is the standard input for most rapid // +// prototyping machines. // +// // +// Comment: A .stl file many contain many duplicated points. They will be // +// unified during the Delaunay tetrahedralization process. // +// // +/////////////////////////////////////////////////////////////////////////////// + +bool tetgenio::load_stl(char* filebasename) +{ + FILE *fp; + tetgenmesh::arraypool *plist; + tetgenio::facet *f; + tetgenio::polygon *p; + char infilename[FILENAMESIZE]; + char buffer[INPUTLINESIZE]; + char *bufferp, *str; + double *coord; + int solid = 0; + int nverts = 0, iverts = 0; + int nfaces = 0; + int line_count = 0, i; + + strncpy(infilename, filebasename, FILENAMESIZE - 1); + infilename[FILENAMESIZE - 1] = '\0'; + if (infilename[0] == '\0') { + printf("Error: No filename.\n"); + return false; + } + if (strcmp(&infilename[strlen(infilename) - 4], ".stl") != 0) { + strcat(infilename, ".stl"); + } + + if (!(fp = fopen(infilename, "r"))) { + printf("Error: Unable to open file %s\n", infilename); + return false; + } + printf("Opening %s.\n", infilename); + + // STL file has no number of points available. Use a list to read points. + plist = new tetgenmesh::arraypool(sizeof(double) * 3, 10); + + while ((bufferp = readline(buffer, fp, &line_count)) != NULL) { + // The ASCII .stl file must start with the lower case keyword solid and + // end with endsolid. + if (solid == 0) { + // Read header + bufferp = strstr(bufferp, "solid"); + if (bufferp != NULL) { + solid = 1; + } + } else { + // We're inside the block of the solid. + str = bufferp; + // Is this the end of the solid. + bufferp = strstr(bufferp, "endsolid"); + if (bufferp != NULL) { + solid = 0; + } else { + // Read the XYZ coordinates if it is a vertex. + bufferp = str; + bufferp = strstr(bufferp, "vertex"); + if (bufferp != NULL) { + plist->newindex((void **) &coord); + for (i = 0; i < 3; i++) { + bufferp = findnextnumber(bufferp); + if (*bufferp == '\0') { + printf("Syntax error reading vertex coords on line %d\n", + line_count); + delete plist; + fclose(fp); + return false; + } + coord[i] = (REAL) strtod(bufferp, &bufferp); + } + } + } + } + } + fclose(fp); + + nverts = (int) plist->objects; + // nverts should be an integer times 3 (every 3 vertices denote a face). + if (nverts == 0 || (nverts % 3 != 0)) { + printf("Error: Wrong number of vertices in file %s.\n", infilename); + delete plist; + return false; + } + numberofpoints = nverts; + pointlist = new REAL[nverts * 3]; + for (i = 0; i < nverts; i++) { + coord = (double *) fastlookup(plist, i); + iverts = i * 3; + pointlist[iverts] = (REAL) coord[0]; + pointlist[iverts + 1] = (REAL) coord[1]; + pointlist[iverts + 2] = (REAL) coord[2]; + } + + nfaces = (int) (nverts / 3); + numberoffacets = nfaces; + facetlist = new tetgenio::facet[nfaces]; + + // Default use '1' as the array starting index. + firstnumber = 1; + iverts = firstnumber; + for (i = 0; i < nfaces; i++) { + f = &facetlist[i]; + init(f); + // In .stl format, each facet has one polygon, no hole. + f->numberofpolygons = 1; + f->polygonlist = new tetgenio::polygon[1]; + p = &f->polygonlist[0]; + init(p); + // Each polygon has three vertices. + p->numberofvertices = 3; + p->vertexlist = new int[p->numberofvertices]; + p->vertexlist[0] = iverts; + p->vertexlist[1] = iverts + 1; + p->vertexlist[2] = iverts + 2; + iverts += 3; + } + + delete plist; + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// load_medit() Load a surface mesh from a .mesh file. // +// // +// The .mesh format is the file format of Medit, a user-friendly interactive // +// mesh viewer program. // +// // +/////////////////////////////////////////////////////////////////////////////// + +bool tetgenio::load_medit(char* filebasename, int istetmesh) +{ + FILE *fp; + tetgenio::facet *tmpflist, *f; + tetgenio::polygon *p; + char infilename[FILENAMESIZE]; + char buffer[INPUTLINESIZE]; + char *bufferp, *str; + double *coord; + int *tmpfmlist; + int dimension = 0; + int nverts = 0; + int nfaces = 0; + int ntets = 0; + int line_count = 0; + int corners = 0; // 3 (triangle) or 4 (quad). + int *plist; + int i, j; + + int smallestidx = 0; + + strncpy(infilename, filebasename, FILENAMESIZE - 1); + infilename[FILENAMESIZE - 1] = '\0'; + if (infilename[0] == '\0') { + printf("Error: No filename.\n"); + return false; + } + if (strcmp(&infilename[strlen(infilename) - 5], ".mesh") != 0) { + strcat(infilename, ".mesh"); + } + + if (!(fp = fopen(infilename, "r"))) { + printf("Error: Unable to open file %s\n", infilename); + return false; + } + printf("Opening %s.\n", infilename); + + while ((bufferp = readline(buffer, fp, &line_count)) != NULL) { + if (*bufferp == '#') continue; // A comment line is skipped. + if (dimension == 0) { + // Find if it is the keyword "Dimension". + str = strstr(bufferp, "Dimension"); + if (!str) str = strstr(bufferp, "dimension"); + if (!str) str = strstr(bufferp, "DIMENSION"); + if (str) { + // Read the dimensions + bufferp = findnextnumber(str); // Skip field "Dimension". + if (*bufferp == '\0') { + // Read a non-empty line. + bufferp = readline(buffer, fp, &line_count); + } + dimension = (int) strtol(bufferp, &bufferp, 0); + if (dimension != 2 && dimension != 3) { + printf("Unknown dimension in file on line %d in file %s\n", + line_count, infilename); + fclose(fp); + return false; + } + mesh_dim = dimension; + } + } + if (nverts == 0) { + // Find if it is the keyword "Vertices". + str = strstr(bufferp, "Vertices"); + if (!str) str = strstr(bufferp, "vertices"); + if (!str) str = strstr(bufferp, "VERTICES"); + if (str) { + // Read the number of vertices. + bufferp = findnextnumber(str); // Skip field "Vertices". + if (*bufferp == '\0') { + // Read a non-empty line. + bufferp = readline(buffer, fp, &line_count); + } + nverts = (int) strtol(bufferp, &bufferp, 0); + // Initialize the smallest index. + smallestidx = nverts + 1; + // Allocate memory for 'tetgenio' + if (nverts > 0) { + numberofpoints = nverts; + pointlist = new REAL[nverts * 3]; + } + // Read the follwoing node list. + for (i = 0; i < nverts; i++) { + bufferp = readline(buffer, fp, &line_count); + if (bufferp == NULL) { + printf("Unexpected end of file on line %d in file %s\n", + line_count, infilename); + fclose(fp); + return false; + } + // Read vertex coordinates + coord = &pointlist[i * 3]; + for (j = 0; j < 3; j++) { + if (*bufferp == '\0') { + printf("Syntax error reading vertex coords on line"); + printf(" %d in file %s\n", line_count, infilename); + fclose(fp); + return false; + } + if ((j < 2) || (dimension == 3)) { + coord[j] = (REAL) strtod(bufferp, &bufferp); + } else { + assert((j == 2) && (dimension == 2)); + coord[j] = 0.0; + } + bufferp = findnextnumber(bufferp); + } + } + continue; + } + } + if (ntets == 0) { + // Find if it is the keyword "Tetrahedra" + corners = 0; + str = strstr(bufferp, "Tetrahedra"); + if (!str) str = strstr(bufferp, "tetrahedra"); + if (!str) str = strstr(bufferp, "TETRAHEDRA"); + if (str) { + corners = 4; + } + if (corners == 4) { + // Read the number of tetrahedra + bufferp = findnextnumber(str); // Skip field "Tetrahedra". + if (*bufferp == '\0') { + // Read a non-empty line. + bufferp = readline(buffer, fp, &line_count); + } + ntets = strtol(bufferp, &bufferp, 0); + if (ntets > 0) { + // It is a tetrahedral mesh. + numberoftetrahedra = ntets; + numberofcorners = 4; + numberoftetrahedronattributes = 1; + tetrahedronlist = new int[ntets * 4]; + tetrahedronattributelist = new REAL[ntets]; + } + } // if (corners == 4) + // Read the list of tetrahedra. + for (i = 0; i < numberoftetrahedra; i++) { + plist = &(tetrahedronlist[i * 4]); + bufferp = readline(buffer, fp, &line_count); + if (bufferp == NULL) { + printf("Unexpected end of file on line %d in file %s\n", + line_count, infilename); + fclose(fp); + return false; + } + // Read the vertices of the tet. + for (j = 0; j < corners; j++) { + if (*bufferp == '\0') { + printf("Syntax error reading face on line %d in file %s\n", + line_count, infilename); + fclose(fp); + return false; + } + plist[j] = (int) strtol(bufferp, &bufferp, 0); + // Remember the smallest index. + if (plist[j] < smallestidx) smallestidx = plist[j]; + bufferp = findnextnumber(bufferp); + } + // Read the attribute of the tet if it exists. + tetrahedronattributelist[i] = 0; + if (*bufferp != '\0') { + tetrahedronattributelist[i] = (REAL) strtol(bufferp, &bufferp, 0); + } + } // i + } // Tetrahedra + if (nfaces == 0) { + // Find if it is the keyword "Triangles" or "Quadrilaterals". + corners = 0; + str = strstr(bufferp, "Triangles"); + if (!str) str = strstr(bufferp, "triangles"); + if (!str) str = strstr(bufferp, "TRIANGLES"); + if (str) { + corners = 3; + } else { + str = strstr(bufferp, "Quadrilaterals"); + if (!str) str = strstr(bufferp, "quadrilaterals"); + if (!str) str = strstr(bufferp, "QUADRILATERALS"); + if (str) { + corners = 4; + } + } + if (corners == 3 || corners == 4) { + // Read the number of triangles (or quadrilaterals). + bufferp = findnextnumber(str); // Skip field "Triangles". + if (*bufferp == '\0') { + // Read a non-empty line. + bufferp = readline(buffer, fp, &line_count); + } + nfaces = strtol(bufferp, &bufferp, 0); + // Allocate memory for 'tetgenio' + if (nfaces > 0) { + if (!istetmesh) { + // It is a PLC surface mesh. + if (numberoffacets > 0) { + // facetlist has already been allocated. Enlarge arrays. + // This happens when the surface mesh contains mixed cells. + tmpflist = new tetgenio::facet[numberoffacets + nfaces]; + tmpfmlist = new int[numberoffacets + nfaces]; + // Copy the data of old arrays into new arrays. + for (i = 0; i < numberoffacets; i++) { + f = &(tmpflist[i]); + tetgenio::init(f); + *f = facetlist[i]; + tmpfmlist[i] = facetmarkerlist[i]; + } + // Release old arrays. + delete [] facetlist; + delete [] facetmarkerlist; + // Remember the new arrays. + facetlist = tmpflist; + facetmarkerlist = tmpfmlist; + } else { + // This is the first time to allocate facetlist. + facetlist = new tetgenio::facet[nfaces]; + facetmarkerlist = new int[nfaces]; + } + } else { + if (corners == 3) { + // It is a surface mesh of a tetrahedral mesh. + numberoftrifaces = nfaces; + trifacelist = new int[nfaces * 3]; + trifacemarkerlist = new int[nfaces]; + } + } + } // if (nfaces > 0) + // Read the following list of faces. + if (!istetmesh) { + for (i = numberoffacets; i < numberoffacets + nfaces; i++) { + bufferp = readline(buffer, fp, &line_count); + if (bufferp == NULL) { + printf("Unexpected end of file on line %d in file %s\n", + line_count, infilename); + fclose(fp); + return false; + } + f = &facetlist[i]; + tetgenio::init(f); + // In .mesh format, each facet has one polygon, no hole. + f->numberofpolygons = 1; + f->polygonlist = new tetgenio::polygon[1]; + p = &f->polygonlist[0]; + tetgenio::init(p); + p->numberofvertices = corners; + // Allocate memory for face vertices + p->vertexlist = new int[p->numberofvertices]; + // Read the vertices of the face. + for (j = 0; j < corners; j++) { + if (*bufferp == '\0') { + printf("Syntax error reading face on line %d in file %s\n", + line_count, infilename); + fclose(fp); + return false; + } + p->vertexlist[j] = (int) strtol(bufferp, &bufferp, 0); + // Remember the smallest index. + if (p->vertexlist[j] < smallestidx) { + smallestidx = p->vertexlist[j]; + } + bufferp = findnextnumber(bufferp); + } + // Read the marker of the face if it exists. + facetmarkerlist[i] = 0; + if (*bufferp != '\0') { + facetmarkerlist[i] = (int) strtol(bufferp, &bufferp, 0); + } + } + // Have read in a list of triangles/quads. + numberoffacets += nfaces; + nfaces = 0; + } else { + // It is a surface mesh of a tetrahedral mesh. + if (corners == 3) { + for (i = 0; i < numberoftrifaces; i++) { + plist = &(trifacelist[i * 3]); + bufferp = readline(buffer, fp, &line_count); + if (bufferp == NULL) { + printf("Unexpected end of file on line %d in file %s\n", + line_count, infilename); + fclose(fp); + return false; + } + // Read the vertices of the face. + for (j = 0; j < corners; j++) { + if (*bufferp == '\0') { + printf("Syntax error reading face on line %d in file %s\n", + line_count, infilename); + fclose(fp); + return false; + } + plist[j] = (int) strtol(bufferp, &bufferp, 0); + // Remember the smallest index. + if (plist[j] < smallestidx) { + smallestidx = plist[j]; + } + bufferp = findnextnumber(bufferp); + } + // Read the marker of the face if it exists. + trifacemarkerlist[i] = 0; + if (*bufferp != '\0') { + trifacemarkerlist[i] = (int) strtol(bufferp, &bufferp, 0); + } + } // i + } // if (corners == 3) + } // if (b->refine) + } // if (corners == 3 || corners == 4) + } + } + + // Close file + fclose(fp); + + // Decide the firstnumber of the index. + if (smallestidx == 0) { + firstnumber = 0; + } else if (smallestidx == 1) { + firstnumber = 1; + } else { + printf("A wrong smallest index (%d) was detected in file %s\n", + smallestidx, infilename); + return false; + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// load_vtk() Load VTK surface mesh from file (.vtk ascii or binary). // +// // +// This function is contributed by: Bryn Lloyd, Computer Vision Laboratory, // +// ETH, Zuerich. May 7, 2007. // +// // +/////////////////////////////////////////////////////////////////////////////// + +// Two inline functions used in read/write VTK files. + +void swapBytes(unsigned char* var, int size) +{ + int i = 0; + int j = size - 1; + char c; + + while (i < j) { + c = var[i]; var[i] = var[j]; var[j] = c; + i++, j--; + } +} + +bool testIsBigEndian() +{ + short word = 0x4321; + if((*(char *)& word) != 0x21) + return true; + else + return false; +} + + +bool tetgenio::load_vtk(char* filebasename) +{ + FILE *fp; + tetgenio::facet *f; + tetgenio::polygon *p; + char infilename[FILENAMESIZE]; + char line[INPUTLINESIZE]; + char mode[128], id[256], fmt[64]; + char *bufferp; + double *coord; + float _x, _y, _z; + int nverts = 0; + int nfaces = 0; + int line_count = 0; + int dummy; + int id1, id2, id3; + int nn = -1; + int nn_old = -1; + int i, j; + bool ImALittleEndian = !testIsBigEndian(); + + int smallestidx = 0; + + strncpy(infilename, filebasename, FILENAMESIZE - 1); + infilename[FILENAMESIZE - 1] = '\0'; + if (infilename[0] == '\0') { + printf("Error: No filename.\n"); + return false; + } + if (strcmp(&infilename[strlen(infilename) - 4], ".vtk") != 0) { + strcat(infilename, ".vtk"); + } + if (!(fp = fopen(infilename, "r"))) { + printf("Error: Unable to open file %s\n", infilename); + return false; + } + printf("Opening %s.\n", infilename); + + // Default uses the index starts from '0'. + firstnumber = 0; + strcpy(mode, "BINARY"); + + while((bufferp = readline(line, fp, &line_count)) != NULL) { + if(strlen(line) == 0) continue; + //swallow lines beginning with a comment sign or white space + if(line[0] == '#' || line[0]=='\n' || line[0] == 10 || line[0] == 13 || + line[0] == 32) continue; + + sscanf(line, "%s", id); + if(!strcmp(id, "ASCII")) { + strcpy(mode, "ASCII"); + } + + if(!strcmp(id, "POINTS")) { + sscanf(line, "%s %d %s", id, &nverts, fmt); + if (nverts > 0) { + numberofpoints = nverts; + pointlist = new REAL[nverts * 3]; + smallestidx = nverts + 1; + } + + if(!strcmp(mode, "BINARY")) { + for(i = 0; i < nverts; i++) { + coord = &pointlist[i * 3]; + if(!strcmp(fmt, "double")) { + fread((char*)(&(coord[0])), sizeof(double), 1, fp); + fread((char*)(&(coord[1])), sizeof(double), 1, fp); + fread((char*)(&(coord[2])), sizeof(double), 1, fp); + if(ImALittleEndian){ + swapBytes((unsigned char *) &(coord[0]), sizeof(coord[0])); + swapBytes((unsigned char *) &(coord[1]), sizeof(coord[1])); + swapBytes((unsigned char *) &(coord[2]), sizeof(coord[2])); + } + } else if(!strcmp(fmt, "float")) { + fread((char*)(&_x), sizeof(float), 1, fp); + fread((char*)(&_y), sizeof(float), 1, fp); + fread((char*)(&_z), sizeof(float), 1, fp); + if(ImALittleEndian){ + swapBytes((unsigned char *) &_x, sizeof(_x)); + swapBytes((unsigned char *) &_y, sizeof(_y)); + swapBytes((unsigned char *) &_z, sizeof(_z)); + } + coord[0] = double(_x); + coord[1] = double(_y); + coord[2] = double(_z); + } else { + printf("Error: Only float or double formats are supported!\n"); + return false; + } + } + } else if(!strcmp(mode, "ASCII")) { + for(i = 0; i < nverts; i++){ + bufferp = readline(line, fp, &line_count); + if (bufferp == NULL) { + printf("Unexpected end of file on line %d in file %s\n", + line_count, infilename); + fclose(fp); + return false; + } + // Read vertex coordinates + coord = &pointlist[i * 3]; + for (j = 0; j < 3; j++) { + if (*bufferp == '\0') { + printf("Syntax error reading vertex coords on line"); + printf(" %d in file %s\n", line_count, infilename); + fclose(fp); + return false; + } + coord[j] = (REAL) strtod(bufferp, &bufferp); + bufferp = findnextnumber(bufferp); + } + } + } + continue; + } + + if(!strcmp(id, "POLYGONS")) { + sscanf(line, "%s %d %d", id, &nfaces, &dummy); + if (nfaces > 0) { + numberoffacets = nfaces; + facetlist = new tetgenio::facet[nfaces]; + } + + if(!strcmp(mode, "BINARY")) { + for(i = 0; i < nfaces; i++){ + fread((char*)(&nn), sizeof(int), 1, fp); + if(ImALittleEndian){ + swapBytes((unsigned char *) &nn, sizeof(nn)); + } + if (i == 0) + nn_old = nn; + if (nn != nn_old) { + printf("Error: No mixed cells are allowed.\n"); + return false; + } + + if(nn == 3){ + fread((char*)(&id1), sizeof(int), 1, fp); + fread((char*)(&id2), sizeof(int), 1, fp); + fread((char*)(&id3), sizeof(int), 1, fp); + if(ImALittleEndian){ + swapBytes((unsigned char *) &id1, sizeof(id1)); + swapBytes((unsigned char *) &id2, sizeof(id2)); + swapBytes((unsigned char *) &id3, sizeof(id3)); + } + f = &facetlist[i]; + init(f); + // In .off format, each facet has one polygon, no hole. + f->numberofpolygons = 1; + f->polygonlist = new tetgenio::polygon[1]; + p = &f->polygonlist[0]; + init(p); + // Set number of vertices + p->numberofvertices = 3; + // Allocate memory for face vertices + p->vertexlist = new int[p->numberofvertices]; + p->vertexlist[0] = id1; + p->vertexlist[1] = id2; + p->vertexlist[2] = id3; + // Detect the smallest index. + for (j = 0; j < 3; j++) { + if (p->vertexlist[j] < smallestidx) { + smallestidx = p->vertexlist[j]; + } + } + } else { + printf("Error: Only triangles are supported\n"); + return false; + } + } + } else if(!strcmp(mode, "ASCII")) { + for(i = 0; i < nfaces; i++) { + bufferp = readline(line, fp, &line_count); + nn = (int) strtol(bufferp, &bufferp, 0); + if (i == 0) + nn_old = nn; + if (nn != nn_old) { + printf("Error: No mixed cells are allowed.\n"); + return false; + } + + if (nn == 3) { + bufferp = findnextnumber(bufferp); // Skip the first field. + id1 = (int) strtol(bufferp, &bufferp, 0); + bufferp = findnextnumber(bufferp); + id2 = (int) strtol(bufferp, &bufferp, 0); + bufferp = findnextnumber(bufferp); + id3 = (int) strtol(bufferp, &bufferp, 0); + f = &facetlist[i]; + init(f); + // In .off format, each facet has one polygon, no hole. + f->numberofpolygons = 1; + f->polygonlist = new tetgenio::polygon[1]; + p = &f->polygonlist[0]; + init(p); + // Set number of vertices + p->numberofvertices = 3; + // Allocate memory for face vertices + p->vertexlist = new int[p->numberofvertices]; + p->vertexlist[0] = id1; + p->vertexlist[1] = id2; + p->vertexlist[2] = id3; + // Detect the smallest index. + for (j = 0; j < 3; j++) { + if (p->vertexlist[j] < smallestidx) { + smallestidx = p->vertexlist[j]; + } + } + } else { + printf("Error: Only triangles are supported.\n"); + return false; + } + } + } + + fclose(fp); + + // Decide the firstnumber of the index. + if (smallestidx == 0) { + firstnumber = 0; + } else if (smallestidx == 1) { + firstnumber = 1; + } else { + printf("A wrong smallest index (%d) was detected in file %s\n", + smallestidx, infilename); + return false; + } + + return true; + } + + if(!strcmp(id,"LINES") || !strcmp(id,"CELLS")){ + printf("Warning: load_vtk(): cannot read formats LINES, CELLS.\n"); + } + } // while () + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// load_plc() Load a piecewise linear complex from file(s). // +// // +/////////////////////////////////////////////////////////////////////////////// + +bool tetgenio::load_plc(char* filebasename, int object) +{ + bool success; + + if (object == (int) tetgenbehavior::NODES) { + success = load_node(filebasename); + } else if (object == (int) tetgenbehavior::POLY) { + success = load_poly(filebasename); + } else if (object == (int) tetgenbehavior::OFF) { + success = load_off(filebasename); + } else if (object == (int) tetgenbehavior::PLY) { + success = load_ply(filebasename); + } else if (object == (int) tetgenbehavior::STL) { + success = load_stl(filebasename); + } else if (object == (int) tetgenbehavior::MEDIT) { + success = load_medit(filebasename, 0); + } else if (object == (int) tetgenbehavior::VTK) { + success = load_vtk(filebasename); + } else { + success = load_poly(filebasename); + } + + if (success) { + // Try to load the following files (.edge, .var, .mtr). + load_edge(filebasename); + load_var(filebasename); + load_mtr(filebasename); + } + + return success; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// load_mesh() Load a tetrahedral mesh from file(s). // +// // +/////////////////////////////////////////////////////////////////////////////// + +bool tetgenio::load_tetmesh(char* filebasename, int object) +{ + bool success; + + if (object == (int) tetgenbehavior::MEDIT) { + success = load_medit(filebasename, 1); + } else { + success = load_node(filebasename); + if (success) { + success = load_tet(filebasename); + } + if (success) { + // Try to load the following files (.face, .edge, .vol). + load_face(filebasename); + load_edge(filebasename); + load_vol(filebasename); + } + } + + if (success) { + // Try to load the following files (.var, .mtr). + load_var(filebasename); + load_mtr(filebasename); + } + + return success; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// save_nodes() Save points to a .node file. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenio::save_nodes(char* filebasename) +{ + FILE *fout; + char outnodefilename[FILENAMESIZE]; + char outmtrfilename[FILENAMESIZE]; + int i, j; + + sprintf(outnodefilename, "%s.node", filebasename); + printf("Saving nodes to %s\n", outnodefilename); + fout = fopen(outnodefilename, "w"); + fprintf(fout, "%d %d %d %d\n", numberofpoints, mesh_dim, + numberofpointattributes, pointmarkerlist != NULL ? 1 : 0); + for (i = 0; i < numberofpoints; i++) { + if (mesh_dim == 2) { + fprintf(fout, "%d %.16g %.16g", i + firstnumber, pointlist[i * 3], + pointlist[i * 3 + 1]); + } else { + fprintf(fout, "%d %.16g %.16g %.16g", i + firstnumber, + pointlist[i * 3], pointlist[i * 3 + 1], pointlist[i * 3 + 2]); + } + for (j = 0; j < numberofpointattributes; j++) { + fprintf(fout, " %.16g", + pointattributelist[i * numberofpointattributes + j]); + } + if (pointmarkerlist != NULL) { + fprintf(fout, " %d", pointmarkerlist[i]); + } + fprintf(fout, "\n"); + } + fclose(fout); + + // If the point metrics exist, output them to a .mtr file. + if ((numberofpointmtrs > 0) && (pointmtrlist != (REAL *) NULL)) { + sprintf(outmtrfilename, "%s.mtr", filebasename); + printf("Saving metrics to %s\n", outmtrfilename); + fout = fopen(outmtrfilename, "w"); + fprintf(fout, "%d %d\n", numberofpoints, numberofpointmtrs); + for (i = 0; i < numberofpoints; i++) { + for (j = 0; j < numberofpointmtrs; j++) { + fprintf(fout, "%.16g ", pointmtrlist[i * numberofpointmtrs + j]); + } + fprintf(fout, "\n"); + } + fclose(fout); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// save_elements() Save elements to a .ele file. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenio::save_elements(char* filebasename) +{ + FILE *fout; + char outelefilename[FILENAMESIZE]; + int i, j; + + sprintf(outelefilename, "%s.ele", filebasename); + printf("Saving elements to %s\n", outelefilename); + fout = fopen(outelefilename, "w"); + if (mesh_dim == 3) { + fprintf(fout, "%d %d %d\n", numberoftetrahedra, numberofcorners, + numberoftetrahedronattributes); + for (i = 0; i < numberoftetrahedra; i++) { + fprintf(fout, "%d", i + firstnumber); + for (j = 0; j < numberofcorners; j++) { + fprintf(fout, " %5d", tetrahedronlist[i * numberofcorners + j]); + } + for (j = 0; j < numberoftetrahedronattributes; j++) { + fprintf(fout, " %g", + tetrahedronattributelist[i * numberoftetrahedronattributes + j]); + } + fprintf(fout, "\n"); + } + } else { + // Save a two-dimensional mesh. + fprintf(fout, "%d %d %d\n",numberoftrifaces,3,trifacemarkerlist ? 1 : 0); + for (i = 0; i < numberoftrifaces; i++) { + fprintf(fout, "%d", i + firstnumber); + for (j = 0; j < 3; j++) { + fprintf(fout, " %5d", trifacelist[i * 3 + j]); + } + if (trifacemarkerlist != NULL) { + fprintf(fout, " %d", trifacemarkerlist[i]); + } + fprintf(fout, "\n"); + } + } + + fclose(fout); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// save_faces() Save faces to a .face file. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenio::save_faces(char* filebasename) +{ + FILE *fout; + char outfacefilename[FILENAMESIZE]; + int i; + + sprintf(outfacefilename, "%s.face", filebasename); + printf("Saving faces to %s\n", outfacefilename); + fout = fopen(outfacefilename, "w"); + fprintf(fout, "%d %d\n", numberoftrifaces, + trifacemarkerlist != NULL ? 1 : 0); + for (i = 0; i < numberoftrifaces; i++) { + fprintf(fout, "%d %5d %5d %5d", i + firstnumber, trifacelist[i * 3], + trifacelist[i * 3 + 1], trifacelist[i * 3 + 2]); + if (trifacemarkerlist != NULL) { + fprintf(fout, " %d", trifacemarkerlist[i]); + } + fprintf(fout, "\n"); + } + + fclose(fout); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// save_edges() Save egdes to a .edge file. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenio::save_edges(char* filebasename) +{ + FILE *fout; + char outedgefilename[FILENAMESIZE]; + int i; + + sprintf(outedgefilename, "%s.edge", filebasename); + printf("Saving edges to %s\n", outedgefilename); + fout = fopen(outedgefilename, "w"); + fprintf(fout, "%d %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0); + for (i = 0; i < numberofedges; i++) { + fprintf(fout, "%d %4d %4d", i + firstnumber, edgelist[i * 2], + edgelist[i * 2 + 1]); + if (edgemarkerlist != NULL) { + fprintf(fout, " %d", edgemarkerlist[i]); + } + fprintf(fout, "\n"); + } + + fclose(fout); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// save_neighbors() Save egdes to a .neigh file. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenio::save_neighbors(char* filebasename) +{ + FILE *fout; + char outneighborfilename[FILENAMESIZE]; + int i; + + sprintf(outneighborfilename, "%s.neigh", filebasename); + printf("Saving neighbors to %s\n", outneighborfilename); + fout = fopen(outneighborfilename, "w"); + fprintf(fout, "%d %d\n", numberoftetrahedra, mesh_dim + 1); + for (i = 0; i < numberoftetrahedra; i++) { + if (mesh_dim == 2) { + fprintf(fout, "%d %5d %5d %5d", i + firstnumber, neighborlist[i * 3], + neighborlist[i * 3 + 1], neighborlist[i * 3 + 2]); + } else { + fprintf(fout, "%d %5d %5d %5d %5d", i + firstnumber, + neighborlist[i * 4], neighborlist[i * 4 + 1], + neighborlist[i * 4 + 2], neighborlist[i * 4 + 3]); + } + fprintf(fout, "\n"); + } + + fclose(fout); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// save_poly() Save segments or facets to a .poly file. // +// // +// It only save the facets, holes and regions. No .node file is saved. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenio::save_poly(char* filebasename) +{ + FILE *fout; + facet *f; + polygon *p; + char outpolyfilename[FILENAMESIZE]; + int i, j, k; + + sprintf(outpolyfilename, "%s.poly", filebasename); + printf("Saving poly to %s\n", outpolyfilename); + fout = fopen(outpolyfilename, "w"); + + // The zero indicates that the vertices are in a separate .node file. + // Followed by number of dimensions, number of vertex attributes, + // and number of boundary markers (zero or one). + fprintf(fout, "%d %d %d %d\n", 0, mesh_dim, numberofpointattributes, + pointmarkerlist != NULL ? 1 : 0); + + // Save segments or facets. + if (mesh_dim == 2) { + // Number of segments, number of boundary markers (zero or one). + fprintf(fout, "%d %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0); + for (i = 0; i < numberofedges; i++) { + fprintf(fout, "%d %4d %4d", i + firstnumber, edgelist[i * 2], + edgelist[i * 2 + 1]); + if (edgemarkerlist != NULL) { + fprintf(fout, " %d", edgemarkerlist[i]); + } + fprintf(fout, "\n"); + } + } else { + // Number of facets, number of boundary markers (zero or one). + fprintf(fout, "%d %d\n", numberoffacets, facetmarkerlist != NULL ? 1 : 0); + for (i = 0; i < numberoffacets; i++) { + f = &(facetlist[i]); + fprintf(fout, "%d %d %d # %d\n", f->numberofpolygons,f->numberofholes, + facetmarkerlist != NULL ? facetmarkerlist[i] : 0, i + firstnumber); + // Output polygons of this facet. + for (j = 0; j < f->numberofpolygons; j++) { + p = &(f->polygonlist[j]); + fprintf(fout, "%d ", p->numberofvertices); + for (k = 0; k < p->numberofvertices; k++) { + if (((k + 1) % 10) == 0) { + fprintf(fout, "\n "); + } + fprintf(fout, " %d", p->vertexlist[k]); + } + fprintf(fout, "\n"); + } + // Output holes of this facet. + for (j = 0; j < f->numberofholes; j++) { + fprintf(fout, "%d %.12g %.12g %.12g\n", j + firstnumber, + f->holelist[j * 3], f->holelist[j * 3 + 1], f->holelist[j * 3 + 2]); + } + } + } + + // Save holes. + fprintf(fout, "%d\n", numberofholes); + for (i = 0; i < numberofholes; i++) { + // Output x, y coordinates. + fprintf(fout, "%d %.12g %.12g", i + firstnumber, holelist[i * mesh_dim], + holelist[i * mesh_dim + 1]); + if (mesh_dim == 3) { + // Output z coordinate. + fprintf(fout, " %.12g", holelist[i * mesh_dim + 2]); + } + fprintf(fout, "\n"); + } + + // Save regions. + fprintf(fout, "%d\n", numberofregions); + for (i = 0; i < numberofregions; i++) { + if (mesh_dim == 2) { + // Output the index, x, y coordinates, attribute (region number) + // and maximum area constraint (maybe -1). + fprintf(fout, "%d %.12g %.12g %.12g %.12g\n", i + firstnumber, + regionlist[i * 4], regionlist[i * 4 + 1], + regionlist[i * 4 + 2], regionlist[i * 4 + 3]); + } else { + // Output the index, x, y, z coordinates, attribute (region number) + // and maximum volume constraint (maybe -1). + fprintf(fout, "%d %.12g %.12g %.12g %.12g %.12g\n", i + firstnumber, + regionlist[i * 5], regionlist[i * 5 + 1], + regionlist[i * 5 + 2], regionlist[i * 5 + 3], + regionlist[i * 5 + 4]); + } + } + + fclose(fout); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// save_faces2smesh() Save triangular faces to a .smesh file. // +// // +// It only save the facets. No holes and regions. No .node file. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenio::save_faces2smesh(char* filebasename) +{ + FILE *fout; + char outsmeshfilename[FILENAMESIZE]; + int i, j; + + sprintf(outsmeshfilename, "%s.smesh", filebasename); + printf("Saving faces to %s\n", outsmeshfilename); + fout = fopen(outsmeshfilename, "w"); + + // The zero indicates that the vertices are in a separate .node file. + // Followed by number of dimensions, number of vertex attributes, + // and number of boundary markers (zero or one). + fprintf(fout, "%d %d %d %d\n", 0, mesh_dim, numberofpointattributes, + pointmarkerlist != NULL ? 1 : 0); + + // Number of facets, number of boundary markers (zero or one). + fprintf(fout, "%d %d\n", numberoftrifaces, + trifacemarkerlist != NULL ? 1 : 0); + + // Output triangular facets. + for (i = 0; i < numberoftrifaces; i++) { + j = i * 3; + fprintf(fout, "3 %d %d %d", trifacelist[j], trifacelist[j + 1], + trifacelist[j + 2]); + if (trifacemarkerlist != NULL) { + fprintf(fout, " %d", trifacemarkerlist[i]); + } + fprintf(fout, "\n"); + } + + // No holes and regions. + fprintf(fout, "0\n"); + fprintf(fout, "0\n"); + + fclose(fout); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// readline() Read a nonempty line from a file. // +// // +// A line is considered "nonempty" if it contains something more than white // +// spaces. If a line is considered empty, it will be dropped and the next // +// line will be read, this process ends until reaching the end-of-file or a // +// non-empty line. Return NULL if it is the end-of-file, otherwise, return // +// a pointer to the first non-whitespace character of the line. // +// // +/////////////////////////////////////////////////////////////////////////////// + +char* tetgenio::readline(char *string, FILE *infile, int *linenumber) +{ + char *result; + + // Search for a non-empty line. + do { + result = fgets(string, INPUTLINESIZE - 1, infile); + if (linenumber) (*linenumber)++; + if (result == (char *) NULL) { + return (char *) NULL; + } + // Skip white spaces. + while ((*result == ' ') || (*result == '\t')) result++; + // If it's end of line, read another line and try again. + } while ((*result == '\0') || (*result == '\r') || (*result == '\n')); + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// findnextfield() Find the next field of a string. // +// // +// Jumps past the current field by searching for whitespace or a comma, then // +// jumps past the whitespace or the comma to find the next field. // +// // +/////////////////////////////////////////////////////////////////////////////// + +char* tetgenio::findnextfield(char *string) +{ + char *result; + + result = string; + // Skip the current field. Stop upon reaching whitespace or a comma. + while ((*result != '\0') && (*result != ' ') && (*result != '\t') && + (*result != ',') && (*result != ';')) { + result++; + } + // Now skip the whitespace or the comma, stop at anything else that looks + // like a character, or the end of a line. + while ((*result == ' ') || (*result == '\t') || (*result == ',') || + (*result == ';')) { + result++; + } + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// readnumberline() Read a nonempty number line from a file. // +// // +// A line is considered "nonempty" if it contains something that looks like // +// a number. Comments (prefaced by `#') are ignored. // +// // +/////////////////////////////////////////////////////////////////////////////// + +char* tetgenio::readnumberline(char *string, FILE *infile, char *infilename) +{ + char *result; + + // Search for something that looks like a number. + do { + result = fgets(string, INPUTLINESIZE, infile); + if (result == (char *) NULL) { + return result; + } + // Skip anything that doesn't look like a number, a comment, + // or the end of a line. + while ((*result != '\0') && (*result != '#') + && (*result != '.') && (*result != '+') && (*result != '-') + && ((*result < '0') || (*result > '9'))) { + result++; + } + // If it's a comment or end of line, read another line and try again. + } while ((*result == '#') || (*result == '\0')); + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// findnextnumber() Find the next field of a number string. // +// // +// Jumps past the current field by searching for whitespace or a comma, then // +// jumps past the whitespace or the comma to find the next field that looks // +// like a number. // +// // +/////////////////////////////////////////////////////////////////////////////// + +char* tetgenio::findnextnumber(char *string) +{ + char *result; + + result = string; + // Skip the current field. Stop upon reaching whitespace or a comma. + while ((*result != '\0') && (*result != '#') && (*result != ' ') && + (*result != '\t') && (*result != ',')) { + result++; + } + // Now skip the whitespace and anything else that doesn't look like a + // number, a comment, or the end of a line. + while ((*result != '\0') && (*result != '#') + && (*result != '.') && (*result != '+') && (*result != '-') + && ((*result < '0') || (*result > '9'))) { + result++; + } + // Check for a comment (prefixed with `#'). + if (*result == '#') { + *result = '\0'; + } + return result; +} + +//// //// +//// //// +//// io_cxx /////////////////////////////////////////////////////////////////// + +//// behavior_cxx ///////////////////////////////////////////////////////////// +//// //// +//// //// + +/////////////////////////////////////////////////////////////////////////////// +// // +// syntax() Print list of command line switches. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenbehavior::syntax() +{ + printf(" tetgen [-pYrq_Aa_miO_S_T_XMwcdzfenvgkJBNEFICQVh] input_file\n"); + printf(" -p Tetrahedralizes a piecewise linear complex (PLC).\n"); + printf(" -Y Preserves the input surface mesh (does not modify it).\n"); + printf(" -r Reconstructs a previously generated mesh.\n"); + printf(" -q Refines mesh (to improve mesh quality).\n"); + printf(" -R Mesh coarsening (to reduce the mesh elements).\n"); + printf(" -A Assigns attributes to tetrahedra in different regions.\n"); + printf(" -a Applies a maximum tetrahedron volume constraint.\n"); + printf(" -m Applies a mesh sizing function.\n"); + printf(" -i Inserts a list of additional points.\n"); + printf(" -O Specifies the level of mesh optimization.\n"); + printf(" -S Specifies maximum number of added points.\n"); + printf(" -T Sets a tolerance for coplanar test (default 1e-8).\n"); + printf(" -X Suppresses use of exact arithmetic.\n"); + printf(" -M No merge of coplanar facets or very close vertices.\n"); + printf(" -w Generates weighted Delaunay (regular) triangulation.\n"); + printf(" -c Retains the convex hull of the PLC.\n"); + printf(" -d Detects self-intersections of facets of the PLC.\n"); + printf(" -z Numbers all output items starting from zero.\n"); + printf(" -f Outputs all faces to .face file.\n"); + printf(" -e Outputs all edges to .edge file.\n"); + printf(" -n Outputs tetrahedra neighbors to .neigh file.\n"); + printf(" -v Outputs Voronoi diagram to files.\n"); + printf(" -g Outputs mesh to .mesh file for viewing by Medit.\n"); + printf(" -k Outputs mesh to .vtk file for viewing by Paraview.\n"); + printf(" -J No jettison of unused vertices from output .node file.\n"); + printf(" -B Suppresses output of boundary information.\n"); + printf(" -N Suppresses output of .node file.\n"); + printf(" -E Suppresses output of .ele file.\n"); + printf(" -F Suppresses output of .face and .edge file.\n"); + printf(" -I Suppresses mesh iteration numbers.\n"); + printf(" -C Checks the consistency of the final mesh.\n"); + printf(" -Q Quiet: No terminal output except errors.\n"); + printf(" -V Verbose: Detailed information, more terminal output.\n"); + printf(" -h Help: A brief instruction for using TetGen.\n"); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// usage() Print a brief instruction for using TetGen. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenbehavior::usage() +{ + printf("TetGen\n"); + printf("A Quality Tetrahedral Mesh Generator and 3D Delaunay "); + printf("Triangulator\n"); + printf("Version 1.5\n"); + printf("November 4, 2013\n"); + printf("\n"); + printf("What Can TetGen Do?\n"); + printf("\n"); + printf(" TetGen generates Delaunay tetrahedralizations, constrained\n"); + printf(" Delaunay tetrahedralizations, and quality tetrahedral meshes.\n"); + printf("\n"); + printf("Command Line Syntax:\n"); + printf("\n"); + printf(" Below is the basic command line syntax of TetGen with a list of "); + printf("short\n"); + printf(" descriptions. Underscores indicate that numbers may optionally\n"); + printf(" follow certain switches. Do not leave any space between a "); + printf("switch\n"); + printf(" and its numeric parameter. \'input_file\' contains input data\n"); + printf(" depending on the switches you supplied which may be a "); + printf(" piecewise\n"); + printf(" linear complex or a list of nodes. File formats and detailed\n"); + printf(" description of command line switches are found in user's "); + printf("manual.\n"); + printf("\n"); + syntax(); + printf("\n"); + printf("Examples of How to Use TetGen:\n"); + printf("\n"); + printf(" \'tetgen object\' reads vertices from object.node, and writes "); + printf("their\n Delaunay tetrahedralization to object.1.node, "); + printf("object.1.ele\n (tetrahedra), and object.1.face"); + printf(" (convex hull faces).\n"); + printf("\n"); + printf(" \'tetgen -p object\' reads a PLC from object.poly or object."); + printf("smesh (and\n possibly object.node) and writes its constrained "); + printf("Delaunay\n tetrahedralization to object.1.node, object.1.ele, "); + printf("object.1.face,\n"); + printf(" (boundary faces) and object.1.edge (boundary edges).\n"); + printf("\n"); + printf(" \'tetgen -pq1.414a.1 object\' reads a PLC from object.poly or\n"); + printf(" object.smesh (and possibly object.node), generates a mesh "); + printf("whose\n tetrahedra have radius-edge ratio smaller than 1.414 and "); + printf("have volume\n of 0.1 or less, and writes the mesh to "); + printf("object.1.node, object.1.ele,\n object.1.face, and object.1.edge\n"); + printf("\n"); + printf("Please send bugs/comments to Hang Si \n"); + terminatetetgen(NULL, 0); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// parse_commandline() Read the command line, identify switches, and set // +// up options and file names. // +// // +// 'argc' and 'argv' are the same parameters passed to the function main() // +// of a C/C++ program. They together represent the command line user invoked // +// from an environment in which TetGen is running. // +// // +/////////////////////////////////////////////////////////////////////////////// + +bool tetgenbehavior::parse_commandline(int argc, char **argv) +{ + int startindex; + int increment; + int meshnumber; + int i, j, k; + char workstring[1024]; + + // First determine the input style of the switches. + if (argc == 0) { + startindex = 0; // Switches are given without a dash. + argc = 1; // For running the following for-loop once. + commandline[0] = '\0'; + } else { + startindex = 1; + strcpy(commandline, argv[0]); + strcat(commandline, " "); + } + + for (i = startindex; i < argc; i++) { + // Remember the command line for output. + strcat(commandline, argv[i]); + strcat(commandline, " "); + if (startindex == 1) { + // Is this string a filename? + if (argv[i][0] != '-') { + strncpy(infilename, argv[i], 1024 - 1); + infilename[1024 - 1] = '\0'; + continue; + } + } + // Parse the individual switch from the string. + for (j = startindex; argv[i][j] != '\0'; j++) { + if (argv[i][j] == 'p') { + plc = 1; + if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.')) { + k = 0; + while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.')) { + j++; + workstring[k] = argv[i][j]; + k++; + } + workstring[k] = '\0'; + facet_ang_tol = (REAL) strtod(workstring, (char **) NULL); + } + } else if (argv[i][j] == 's') { + psc = 1; + } else if (argv[i][j] == 'Y') { + nobisect = 1; + if ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) { + nobisect_param = (argv[i][j + 1] - '0'); + j++; + } + if ((argv[i][j + 1] == '/') || (argv[i][j + 1] == ',')) { + j++; + if ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) { + addsteiner_algo = (argv[i][j + 1] - '0'); + j++; + } + } + } else if (argv[i][j] == 'r') { + refine = 1; + } else if (argv[i][j] == 'q') { + quality = 1; + if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.')) { + k = 0; + while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.')) { + j++; + workstring[k] = argv[i][j]; + k++; + } + workstring[k] = '\0'; + minratio = (REAL) strtod(workstring, (char **) NULL); + } + if ((argv[i][j + 1] == '/') || (argv[i][j + 1] == ',')) { + j++; + if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.')) { + k = 0; + while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.')) { + j++; + workstring[k] = argv[i][j]; + k++; + } + workstring[k] = '\0'; + mindihedral = (REAL) strtod(workstring, (char **) NULL); + } + } + if ((argv[i][j + 1] == '/') || (argv[i][j + 1] == ',')) { + j++; + if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.')) { + k = 0; + while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.')) { + j++; + workstring[k] = argv[i][j]; + k++; + } + workstring[k] = '\0'; + optmaxdihedral = (REAL) strtod(workstring, (char **) NULL); + } + } + } else if (argv[i][j] == 'R') { + coarsen = 1; + if ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) { + coarsen_param = (argv[i][j + 1] - '0'); + j++; + } + if ((argv[i][j + 1] == '/') || (argv[i][j + 1] == ',')) { + j++; + if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.')) { + k = 0; + while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.')) { + j++; + workstring[k] = argv[i][j]; + k++; + } + workstring[k] = '\0'; + coarsen_percent = (REAL) strtod(workstring, (char **) NULL); + } + } + } else if (argv[i][j] == 'w') { + weighted = 1; + if ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) { + weighted_param = (argv[i][j + 1] - '0'); + j++; + } + } else if (argv[i][j] == 'b') { + // -b(brio_threshold/brio_ratio/hilbert_limit/hilbert_order) + brio_hilbert = 1; + if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.')) { + k = 0; + while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.')) { + j++; + workstring[k] = argv[i][j]; + k++; + } + workstring[k] = '\0'; + brio_threshold = (int) strtol(workstring, (char **) &workstring, 0); + } + if ((argv[i][j + 1] == '/') || (argv[i][j + 1] == ',')) { + j++; + if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.')) { + k = 0; + while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.')) { + j++; + workstring[k] = argv[i][j]; + k++; + } + workstring[k] = '\0'; + brio_ratio = (REAL) strtod(workstring, (char **) NULL); + } + } + if ((argv[i][j + 1] == '/') || (argv[i][j + 1] == ',')) { + j++; + if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.') || (argv[i][j + 1] == '-')) { + k = 0; + while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.') || (argv[i][j + 1] == '-')) { + j++; + workstring[k] = argv[i][j]; + k++; + } + workstring[k] = '\0'; + hilbert_limit = (int) strtol(workstring, (char **) &workstring, 0); + } + } + if ((argv[i][j + 1] == '/') || (argv[i][j + 1] == ',')) { + j++; + if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.') || (argv[i][j + 1] == '-')) { + k = 0; + while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.') || (argv[i][j + 1] == '-')) { + j++; + workstring[k] = argv[i][j]; + k++; + } + workstring[k] = '\0'; + hilbert_order = (REAL) strtod(workstring, (char **) NULL); + } + } + if (brio_threshold == 0) { // -b0 + brio_hilbert = 0; // Turn off BRIO-Hilbert sorting. + } + if (brio_ratio >= 1.0) { // -b/1 + no_sort = 1; + brio_hilbert = 0; // Turn off BRIO-Hilbert sorting. + } + } else if (argv[i][j] == 'l') { + incrflip = 1; + } else if (argv[i][j] == 'L') { + flipinsert = 1; + } else if (argv[i][j] == 'm') { + metric = 1; + } else if (argv[i][j] == 'a') { + if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.')) { + fixedvolume = 1; + k = 0; + while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') || + (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) { + j++; + workstring[k] = argv[i][j]; + k++; + } + workstring[k] = '\0'; + maxvolume = (REAL) strtod(workstring, (char **) NULL); + } else { + varvolume = 1; + } + } else if (argv[i][j] == 'A') { + regionattrib = 1; + } else if (argv[i][j] == 'D') { + conforming = 1; + if ((argv[i][j + 1] >= '1') && (argv[i][j + 1] <= '3')) { + reflevel = (argv[i][j + 1] - '1') + 1; + j++; + } + } else if (argv[i][j] == 'i') { + insertaddpoints = 1; + } else if (argv[i][j] == 'd') { + diagnose = 1; + } else if (argv[i][j] == 'c') { + convex = 1; + } else if (argv[i][j] == 'M') { + nomergefacet = 1; + nomergevertex = 1; + if ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '1')) { + nomergefacet = (argv[i][j + 1] - '0'); + j++; + } + if ((argv[i][j + 1] == '/') || (argv[i][j + 1] == ',')) { + j++; + if ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '1')) { + nomergevertex = (argv[i][j + 1] - '0'); + j++; + } + } + } else if (argv[i][j] == 'X') { + if (argv[i][j + 1] == '1') { + nostaticfilter = 1; + j++; + } else { + noexact = 1; + } + } else if (argv[i][j] == 'z') { + zeroindex = 1; + } else if (argv[i][j] == 'f') { + facesout++; + } else if (argv[i][j] == 'e') { + edgesout++; + } else if (argv[i][j] == 'n') { + neighout++; + } else if (argv[i][j] == 'v') { + voroout = 1; + } else if (argv[i][j] == 'g') { + meditview = 1; + } else if (argv[i][j] == 'k') { + vtkview = 1; + } else if (argv[i][j] == 'J') { + nojettison = 1; + } else if (argv[i][j] == 'B') { + nobound = 1; + } else if (argv[i][j] == 'N') { + nonodewritten = 1; + } else if (argv[i][j] == 'E') { + noelewritten = 1; + } else if (argv[i][j] == 'F') { + nofacewritten = 1; + } else if (argv[i][j] == 'I') { + noiterationnum = 1; + } else if (argv[i][j] == 'S') { + if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.')) { + k = 0; + while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') || + (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) { + j++; + workstring[k] = argv[i][j]; + k++; + } + workstring[k] = '\0'; + steinerleft = (int) strtol(workstring, (char **) NULL, 0); + } + } else if (argv[i][j] == 'o') { + if (argv[i][j + 1] == '2') { + order = 2; + j++; + } + if ((argv[i][j + 1] == '/') || (argv[i][j + 1] == ',')) { + j++; + if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.')) { + k = 0; + while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.')) { + j++; + workstring[k] = argv[i][j]; + k++; + } + workstring[k] = '\0'; + optmaxdihedral = (REAL) strtod(workstring, (char **) NULL); + } + } + } else if (argv[i][j] == 'O') { + if ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) { + optlevel = (argv[i][j + 1] - '0'); + j++; + } + if ((argv[i][j + 1] == '/') || (argv[i][j + 1] == ',')) { + j++; + if ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '7')) { + optscheme = (argv[i][j + 1] - '0'); + j++; + } + } + } else if (argv[i][j] == 'T') { + if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.')) { + k = 0; + while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') || + (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) { + j++; + workstring[k] = argv[i][j]; + k++; + } + workstring[k] = '\0'; + epsilon = (REAL) strtod(workstring, (char **) NULL); + } + } else if (argv[i][j] == 'R') { + reversetetori = 1; + } else if (argv[i][j] == 'C') { + docheck++; + } else if (argv[i][j] == 'Q') { + quiet = 1; + } else if (argv[i][j] == 'V') { + verbose++; + } else if (argv[i][j] == 'x') { + if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.')) { + k = 0; + while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || + (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') || + (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) { + j++; + workstring[k] = argv[i][j]; + k++; + } + workstring[k] = '\0'; + tetrahedraperblock = (int) strtol(workstring, (char **) NULL, 0); + if (tetrahedraperblock > 8188) { + vertexperblock = tetrahedraperblock / 2; + shellfaceperblock = vertexperblock / 2; + } else { + tetrahedraperblock = 8188; + } + } + } else if ((argv[i][j] == 'h') || (argv[i][j] == 'H') || + (argv[i][j] == '?')) { + usage(); + } else { + printf("Warning: Unknown switch -%c.\n", argv[i][j]); + } + } + } + + if (startindex == 0) { + // Set a temporary filename for debugging output. + strcpy(infilename, "tetgen-tmpfile"); + } else { + if (infilename[0] == '\0') { + // No input file name. Print the syntax and exit. + syntax(); + terminatetetgen(NULL, 0); + } + // Recognize the object from file extension if it is available. + if (!strcmp(&infilename[strlen(infilename) - 5], ".node")) { + infilename[strlen(infilename) - 5] = '\0'; + object = NODES; + } else if (!strcmp(&infilename[strlen(infilename) - 5], ".poly")) { + infilename[strlen(infilename) - 5] = '\0'; + object = POLY; + plc = 1; + } else if (!strcmp(&infilename[strlen(infilename) - 6], ".smesh")) { + infilename[strlen(infilename) - 6] = '\0'; + object = POLY; + plc = 1; + } else if (!strcmp(&infilename[strlen(infilename) - 4], ".off")) { + infilename[strlen(infilename) - 4] = '\0'; + object = OFF; + plc = 1; + } else if (!strcmp(&infilename[strlen(infilename) - 4], ".ply")) { + infilename[strlen(infilename) - 4] = '\0'; + object = PLY; + plc = 1; + } else if (!strcmp(&infilename[strlen(infilename) - 4], ".stl")) { + infilename[strlen(infilename) - 4] = '\0'; + object = STL; + plc = 1; + } else if (!strcmp(&infilename[strlen(infilename) - 5], ".mesh")) { + infilename[strlen(infilename) - 5] = '\0'; + object = MEDIT; + if (!refine) plc = 1; + } else if (!strcmp(&infilename[strlen(infilename) - 4], ".vtk")) { + infilename[strlen(infilename) - 4] = '\0'; + object = VTK; + plc = 1; + } else if (!strcmp(&infilename[strlen(infilename) - 4], ".ele")) { + infilename[strlen(infilename) - 4] = '\0'; + object = MESH; + refine = 1; + } + } + + if (nobisect && (!plc && !refine)) { // -Y + plc = 1; // Default -p option. + } + if (quality && (!plc && !refine)) { // -q + plc = 1; // Default -p option. + } + if (diagnose && !plc) { // -d + plc = 1; + } + if (refine && !quality) { // -r only + // Reconstruct a mesh, no mesh optimization. + optlevel = 0; + } + if (insertaddpoints && (optlevel == 0)) { // with -i option + optlevel = 2; + } + if (coarsen && (optlevel == 0)) { // with -R option + optlevel = 2; + } + + // Detect improper combinations of switches. + if ((refine || plc) && weighted) { + printf("Error: Switches -w cannot use together with -p or -r.\n"); + return false; + } + + if (convex) { // -c + if (plc && !regionattrib) { + // -A (region attribute) is needed for marking exterior tets (-1). + regionattrib = 1; + } + } + + // Note: -A must not used together with -r option. + // Be careful not to add an extra attribute to each element unless the + // input supports it (PLC in, but not refining a preexisting mesh). + if (refine || !plc) { + regionattrib = 0; + } + // Be careful not to allocate space for element area constraints that + // will never be assigned any value (other than the default -1.0). + if (!refine && !plc) { + varvolume = 0; + } + // If '-a' or '-aa' is in use, enable '-q' option too. + if (fixedvolume || varvolume) { + if (quality == 0) { + quality = 1; + if (!plc && !refine) { + plc = 1; // enable -p. + } + } + } + // No user-specified dihedral angle bound. Use default ones. + if (!quality) { + if (optmaxdihedral < 179.0) { + if (nobisect) { // with -Y option + optmaxdihedral = 179.0; + } else { // -p only + optmaxdihedral = 179.999; + } + } + if (optminsmtdihed < 179.999) { + optminsmtdihed = 179.999; + } + if (optminslidihed < 179.999) { + optminslidihed = 179.999; + } + } + + increment = 0; + strcpy(workstring, infilename); + j = 1; + while (workstring[j] != '\0') { + if ((workstring[j] == '.') && (workstring[j + 1] != '\0')) { + increment = j + 1; + } + j++; + } + meshnumber = 0; + if (increment > 0) { + j = increment; + do { + if ((workstring[j] >= '0') && (workstring[j] <= '9')) { + meshnumber = meshnumber * 10 + (int) (workstring[j] - '0'); + } else { + increment = 0; + } + j++; + } while (workstring[j] != '\0'); + } + if (noiterationnum) { + strcpy(outfilename, infilename); + } else if (increment == 0) { + strcpy(outfilename, infilename); + strcat(outfilename, ".1"); + } else { + workstring[increment] = '%'; + workstring[increment + 1] = 'd'; + workstring[increment + 2] = '\0'; + sprintf(outfilename, workstring, meshnumber + 1); + } + // Additional input file name has the end ".a". + strcpy(addinfilename, infilename); + strcat(addinfilename, ".a"); + // Background filename has the form "*.b.ele", "*.b.node", ... + strcpy(bgmeshfilename, infilename); + strcat(bgmeshfilename, ".b"); + + return true; +} + +//// //// +//// //// +//// behavior_cxx ///////////////////////////////////////////////////////////// + +//// mempool_cxx ////////////////////////////////////////////////////////////// +//// //// +//// //// + +// Initialize fast lookup tables for mesh maniplulation primitives. + +int tetgenmesh::bondtbl[12][12] = {{0,},}; +int tetgenmesh::enexttbl[12] = {0,}; +int tetgenmesh::eprevtbl[12] = {0,}; +int tetgenmesh::enextesymtbl[12] = {0,}; +int tetgenmesh::eprevesymtbl[12] = {0,}; +int tetgenmesh::eorgoppotbl[12] = {0,}; +int tetgenmesh::edestoppotbl[12] = {0,}; +int tetgenmesh::fsymtbl[12][12] = {{0,},}; +int tetgenmesh::facepivot1[12] = {0,}; +int tetgenmesh::facepivot2[12][12] = {{0,},}; +int tetgenmesh::tsbondtbl[12][6] = {{0,},}; +int tetgenmesh::stbondtbl[12][6] = {{0,},}; +int tetgenmesh::tspivottbl[12][6] = {{0,},}; +int tetgenmesh::stpivottbl[12][6] = {{0,},}; + +// Table 'esymtbl' takes an directed edge (version) as input, returns the +// inversed edge (version) of it. + +int tetgenmesh::esymtbl[12] = {9, 6, 11, 4, 3, 7, 1, 5, 10, 0, 8, 2}; + +// The following four tables give the 12 permutations of the set {0,1,2,3}. +// An offset 4 is added to each element for a direct access of the points +// in the tetrahedron data structure. + +int tetgenmesh:: orgpivot[12] = {7, 7, 5, 5, 6, 4, 4, 6, 5, 6, 7, 4}; +int tetgenmesh::destpivot[12] = {6, 4, 4, 6, 5, 6, 7, 4, 7, 7, 5, 5}; +int tetgenmesh::apexpivot[12] = {5, 6, 7, 4, 7, 7, 5, 5, 6, 4, 4, 6}; +int tetgenmesh::oppopivot[12] = {4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7}; + +// The twelve versions correspond to six undirected edges. The following two +// tables map a version to an undirected edge and vice versa. + +int tetgenmesh::ver2edge[12] = {0, 1, 2, 3, 3, 5, 1, 5, 4, 0, 4, 2}; +int tetgenmesh::edge2ver[ 6] = {0, 1, 2, 3, 8, 5}; + +// Edge versions whose apex or opposite may be dummypoint. + +int tetgenmesh::epivot[12] = {4, 5, 2, 11, 4, 5, 2, 11, 4, 5, 2, 11}; + + +// Table 'snextpivot' takes an edge version as input, returns the next edge +// version in the same edge ring. + +int tetgenmesh::snextpivot[6] = {2, 5, 4, 1, 0, 3}; + +// The following three tables give the 6 permutations of the set {0,1,2}. +// An offset 3 is added to each element for a direct access of the points +// in the triangle data structure. + +int tetgenmesh::sorgpivot [6] = {3, 4, 4, 5, 5, 3}; +int tetgenmesh::sdestpivot[6] = {4, 3, 5, 4, 3, 5}; +int tetgenmesh::sapexpivot[6] = {5, 5, 3, 3, 4, 4}; + +/////////////////////////////////////////////////////////////////////////////// +// // +// inittable() Initialize the look-up tables. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::inittables() +{ + int i, j; + + + // i = t1.ver; j = t2.ver; + for (i = 0; i < 12; i++) { + for (j = 0; j < 12; j++) { + bondtbl[i][j] = (j & 3) + (((i & 12) + (j & 12)) % 12); + } + } + + + // i = t1.ver; j = t2.ver + for (i = 0; i < 12; i++) { + for (j = 0; j < 12; j++) { + fsymtbl[i][j] = (j + 12 - (i & 12)) % 12; + } + } + + + for (i = 0; i < 12; i++) { + facepivot1[i] = (esymtbl[i] & 3); + } + + for (i = 0; i < 12; i++) { + for (j = 0; j < 12; j++) { + facepivot2[i][j] = fsymtbl[esymtbl[i]][j]; + } + } + + for (i = 0; i < 12; i++) { + enexttbl[i] = (i + 4) % 12; + eprevtbl[i] = (i + 8) % 12; + } + + for (i = 0; i < 12; i++) { + enextesymtbl[i] = esymtbl[enexttbl[i]]; + eprevesymtbl[i] = esymtbl[eprevtbl[i]]; + } + + for (i = 0; i < 12; i++) { + eorgoppotbl [i] = eprevtbl[esymtbl[enexttbl[i]]]; + edestoppotbl[i] = enexttbl[esymtbl[eprevtbl[i]]]; + } + + int soffset, toffset; + + // i = t.ver, j = s.shver + for (i = 0; i < 12; i++) { + for (j = 0; j < 6; j++) { + if ((j & 1) == 0) { + soffset = (6 - ((i & 12) >> 1)) % 6; + toffset = (12 - ((j & 6) << 1)) % 12; + } else { + soffset = (i & 12) >> 1; + toffset = (j & 6) << 1; + } + tsbondtbl[i][j] = (j & 1) + (((j & 6) + soffset) % 6); + stbondtbl[i][j] = (i & 3) + (((i & 12) + toffset) % 12); + } + } + + + // i = t.ver, j = s.shver + for (i = 0; i < 12; i++) { + for (j = 0; j < 6; j++) { + if ((j & 1) == 0) { + soffset = (i & 12) >> 1; + toffset = (j & 6) << 1; + } else { + soffset = (6 - ((i & 12) >> 1)) % 6; + toffset = (12 - ((j & 6) << 1)) % 12; + } + tspivottbl[i][j] = (j & 1) + (((j & 6) + soffset) % 6); + stpivottbl[i][j] = (i & 3) + (((i & 12) + toffset) % 12); + } + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// restart() Deallocate all objects in this pool. // +// // +// The pool returns to a fresh state, like after it was initialized, except // +// that no memory is freed to the operating system. Rather, the previously // +// allocated blocks are ready to be used. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::arraypool::restart() +{ + objects = 0l; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// poolinit() Initialize an arraypool for allocation of objects. // +// // +// Before the pool may be used, it must be initialized by this procedure. // +// After initialization, memory can be allocated and freed in this pool. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::arraypool::poolinit(int sizeofobject, int log2objperblk) +{ + // Each object must be at least one byte long. + objectbytes = sizeofobject > 1 ? sizeofobject : 1; + + log2objectsperblock = log2objperblk; + // Compute the number of objects in each block. + objectsperblock = ((int) 1) << log2objectsperblock; + objectsperblockmark = objectsperblock - 1; + + // No memory has been allocated. + totalmemory = 0l; + // The top array has not been allocated yet. + toparray = (char **) NULL; + toparraylen = 0; + + // Ready all indices to be allocated. + restart(); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// arraypool() The constructor and destructor. // +// // +/////////////////////////////////////////////////////////////////////////////// + +tetgenmesh::arraypool::arraypool(int sizeofobject, int log2objperblk) +{ + poolinit(sizeofobject, log2objperblk); +} + +tetgenmesh::arraypool::~arraypool() +{ + int i; + + // Has anything been allocated at all? + if (toparray != (char **) NULL) { + // Walk through the top array. + for (i = 0; i < toparraylen; i++) { + // Check every pointer; NULLs may be scattered randomly. + if (toparray[i] != (char *) NULL) { + // Free an allocated block. + free((void *) toparray[i]); + } + } + // Free the top array. + free((void *) toparray); + } + + // The top array is no longer allocated. + toparray = (char **) NULL; + toparraylen = 0; + objects = 0; + totalmemory = 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// getblock() Return (and perhaps create) the block containing the object // +// with a given index. // +// // +// This function takes care of allocating or resizing the top array if nece- // +// ssary, and of allocating the block if it hasn't yet been allocated. // +// // +// Return a pointer to the beginning of the block (NOT the object). // +// // +/////////////////////////////////////////////////////////////////////////////// + +char* tetgenmesh::arraypool::getblock(int objectindex) +{ + char **newarray; + char *block; + int newsize; + int topindex; + int i; + + // Compute the index in the top array (upper bits). + topindex = objectindex >> log2objectsperblock; + // Does the top array need to be allocated or resized? + if (toparray == (char **) NULL) { + // Allocate the top array big enough to hold 'topindex', and NULL out + // its contents. + newsize = topindex + 128; + toparray = (char **) malloc((size_t) (newsize * sizeof(char *))); + toparraylen = newsize; + for (i = 0; i < newsize; i++) { + toparray[i] = (char *) NULL; + } + // Account for the memory. + totalmemory = newsize * (uintptr_t) sizeof(char *); + } else if (topindex >= toparraylen) { + // Resize the top array, making sure it holds 'topindex'. + newsize = 3 * toparraylen; + if (topindex >= newsize) { + newsize = topindex + 128; + } + // Allocate the new array, copy the contents, NULL out the rest, and + // free the old array. + newarray = (char **) malloc((size_t) (newsize * sizeof(char *))); + for (i = 0; i < toparraylen; i++) { + newarray[i] = toparray[i]; + } + for (i = toparraylen; i < newsize; i++) { + newarray[i] = (char *) NULL; + } + free(toparray); + // Account for the memory. + totalmemory += (newsize - toparraylen) * sizeof(char *); + toparray = newarray; + toparraylen = newsize; + } + + // Find the block, or learn that it hasn't been allocated yet. + block = toparray[topindex]; + if (block == (char *) NULL) { + // Allocate a block at this index. + block = (char *) malloc((size_t) (objectsperblock * objectbytes)); + toparray[topindex] = block; + // Account for the memory. + totalmemory += objectsperblock * objectbytes; + } + + // Return a pointer to the block. + return block; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// lookup() Return the pointer to the object with a given index, or NULL // +// if the object's block doesn't exist yet. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void* tetgenmesh::arraypool::lookup(int objectindex) +{ + char *block; + int topindex; + + // Has the top array been allocated yet? + if (toparray == (char **) NULL) { + return (void *) NULL; + } + + // Compute the index in the top array (upper bits). + topindex = objectindex >> log2objectsperblock; + // Does the top index fit in the top array? + if (topindex >= toparraylen) { + return (void *) NULL; + } + + // Find the block, or learn that it hasn't been allocated yet. + block = toparray[topindex]; + if (block == (char *) NULL) { + return (void *) NULL; + } + + // Compute a pointer to the object with the given index. Note that + // 'objectsperblock' is a power of two, so the & operation is a bit mask + // that preserves the lower bits. + return (void *)(block + (objectindex & (objectsperblock - 1)) * objectbytes); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// newindex() Allocate space for a fresh object from the pool. // +// // +// 'newptr' returns a pointer to the new object (it must not be a NULL). // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::arraypool::newindex(void **newptr) +{ + // Allocate an object at index 'firstvirgin'. + int newindex = objects; + *newptr = (void *) (getblock(objects) + + (objects & (objectsperblock - 1)) * objectbytes); + objects++; + + return newindex; +} + + +/////////////////////////////////////////////////////////////////////////////// +// // +// memorypool() The constructors of memorypool. // +// // +/////////////////////////////////////////////////////////////////////////////// + +tetgenmesh::memorypool::memorypool() +{ + firstblock = nowblock = (void **) NULL; + nextitem = (void *) NULL; + deaditemstack = (void *) NULL; + pathblock = (void **) NULL; + pathitem = (void *) NULL; + alignbytes = 0; + itembytes = itemwords = 0; + itemsperblock = 0; + items = maxitems = 0l; + unallocateditems = 0; + pathitemsleft = 0; +} + +tetgenmesh::memorypool::memorypool(int bytecount, int itemcount, int wsize, + int alignment) +{ + poolinit(bytecount, itemcount, wsize, alignment); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// ~memorypool() Free to the operating system all memory taken by a pool. // +// // +/////////////////////////////////////////////////////////////////////////////// + +tetgenmesh::memorypool::~memorypool() +{ + while (firstblock != (void **) NULL) { + nowblock = (void **) *(firstblock); + free(firstblock); + firstblock = nowblock; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// poolinit() Initialize a pool of memory for allocation of items. // +// // +// A `pool' is created whose records have size at least `bytecount'. Items // +// will be allocated in `itemcount'-item blocks. Each item is assumed to be // +// a collection of words, and either pointers or floating-point values are // +// assumed to be the "primary" word type. (The "primary" word type is used // +// to determine alignment of items.) If `alignment' isn't zero, all items // +// will be `alignment'-byte aligned in memory. `alignment' must be either a // +// multiple or a factor of the primary word size; powers of two are safe. // +// `alignment' is normally used to create a few unused bits at the bottom of // +// each item's pointer, in which information may be stored. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::memorypool::poolinit(int bytecount,int itemcount,int wordsize, + int alignment) +{ + // Find the proper alignment, which must be at least as large as: + // - The parameter `alignment'. + // - The primary word type, to avoid unaligned accesses. + // - sizeof(void *), so the stack of dead items can be maintained + // without unaligned accesses. + if (alignment > wordsize) { + alignbytes = alignment; + } else { + alignbytes = wordsize; + } + if ((int) sizeof(void *) > alignbytes) { + alignbytes = (int) sizeof(void *); + } + itemwords = ((bytecount + alignbytes - 1) / alignbytes) + * (alignbytes / wordsize); + itembytes = itemwords * wordsize; + itemsperblock = itemcount; + + // Allocate a block of items. Space for `itemsperblock' items and one + // pointer (to point to the next block) are allocated, as well as space + // to ensure alignment of the items. + firstblock = (void **) malloc(itemsperblock * itembytes + sizeof(void *) + + alignbytes); + if (firstblock == (void **) NULL) { + terminatetetgen(NULL, 1); + } + // Set the next block pointer to NULL. + *(firstblock) = (void *) NULL; + restart(); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// restart() Deallocate all items in this pool. // +// // +// The pool is returned to its starting state, except that no memory is // +// freed to the operating system. Rather, the previously allocated blocks // +// are ready to be reused. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::memorypool::restart() +{ + uintptr_t alignptr; + + items = 0; + maxitems = 0; + + // Set the currently active block. + nowblock = firstblock; + // Find the first item in the pool. Increment by the size of (void *). + alignptr = (uintptr_t) (nowblock + 1); + // Align the item on an `alignbytes'-byte boundary. + nextitem = (void *) + (alignptr + (uintptr_t) alignbytes - + (alignptr % (uintptr_t) alignbytes)); + // There are lots of unallocated items left in this block. + unallocateditems = itemsperblock; + // The stack of deallocated items is empty. + deaditemstack = (void *) NULL; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// alloc() Allocate space for an item. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void* tetgenmesh::memorypool::alloc() +{ + void *newitem; + void **newblock; + uintptr_t alignptr; + + // First check the linked list of dead items. If the list is not + // empty, allocate an item from the list rather than a fresh one. + if (deaditemstack != (void *) NULL) { + newitem = deaditemstack; // Take first item in list. + deaditemstack = * (void **) deaditemstack; + } else { + // Check if there are any free items left in the current block. + if (unallocateditems == 0) { + // Check if another block must be allocated. + if (*nowblock == (void *) NULL) { + // Allocate a new block of items, pointed to by the previous block. + newblock = (void **) malloc(itemsperblock * itembytes + sizeof(void *) + + alignbytes); + if (newblock == (void **) NULL) { + terminatetetgen(NULL, 1); + } + *nowblock = (void *) newblock; + // The next block pointer is NULL. + *newblock = (void *) NULL; + } + // Move to the new block. + nowblock = (void **) *nowblock; + // Find the first item in the block. + // Increment by the size of (void *). + alignptr = (uintptr_t) (nowblock + 1); + // Align the item on an `alignbytes'-byte boundary. + nextitem = (void *) + (alignptr + (uintptr_t) alignbytes - + (alignptr % (uintptr_t) alignbytes)); + // There are lots of unallocated items left in this block. + unallocateditems = itemsperblock; + } + // Allocate a new item. + newitem = nextitem; + // Advance `nextitem' pointer to next free item in block. + nextitem = (void *) ((uintptr_t) nextitem + itembytes); + unallocateditems--; + maxitems++; + } + items++; + return newitem; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// dealloc() Deallocate space for an item. // +// // +// The deallocated space is stored in a queue for later reuse. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::memorypool::dealloc(void *dyingitem) +{ + // Push freshly killed item onto stack. + *((void **) dyingitem) = deaditemstack; + deaditemstack = dyingitem; + items--; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// traversalinit() Prepare to traverse the entire list of items. // +// // +// This routine is used in conjunction with traverse(). // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::memorypool::traversalinit() +{ + uintptr_t alignptr; + + // Begin the traversal in the first block. + pathblock = firstblock; + // Find the first item in the block. Increment by the size of (void *). + alignptr = (uintptr_t) (pathblock + 1); + // Align with item on an `alignbytes'-byte boundary. + pathitem = (void *) + (alignptr + (uintptr_t) alignbytes - + (alignptr % (uintptr_t) alignbytes)); + // Set the number of items left in the current block. + pathitemsleft = itemsperblock; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// traverse() Find the next item in the list. // +// // +// This routine is used in conjunction with traversalinit(). Be forewarned // +// that this routine successively returns all items in the list, including // +// deallocated ones on the deaditemqueue. It's up to you to figure out which // +// ones are actually dead. It can usually be done more space-efficiently by // +// a routine that knows something about the structure of the item. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void* tetgenmesh::memorypool::traverse() +{ + void *newitem; + uintptr_t alignptr; + + // Stop upon exhausting the list of items. + if (pathitem == nextitem) { + return (void *) NULL; + } + // Check whether any untraversed items remain in the current block. + if (pathitemsleft == 0) { + // Find the next block. + pathblock = (void **) *pathblock; + // Find the first item in the block. Increment by the size of (void *). + alignptr = (uintptr_t) (pathblock + 1); + // Align with item on an `alignbytes'-byte boundary. + pathitem = (void *) + (alignptr + (uintptr_t) alignbytes - + (alignptr % (uintptr_t) alignbytes)); + // Set the number of items left in the current block. + pathitemsleft = itemsperblock; + } + newitem = pathitem; + // Find the next item in the block. + pathitem = (void *) ((uintptr_t) pathitem + itembytes); + pathitemsleft--; + return newitem; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// makeindex2pointmap() Create a map from index to vertices. // +// // +// 'idx2verlist' returns the created map. Traverse all vertices, a pointer // +// to each vertex is set into the array. The pointer to the first vertex is // +// saved in 'idx2verlist[in->firstnumber]'. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::makeindex2pointmap(point*& idx2verlist) +{ + point pointloop; + int idx; + + if (b->verbose > 1) { + printf(" Constructing mapping from indices to points.\n"); + } + + idx2verlist = new point[points->items + 1]; + + points->traversalinit(); + pointloop = pointtraverse(); + idx = in->firstnumber; + while (pointloop != (point) NULL) { + idx2verlist[idx++] = pointloop; + pointloop = pointtraverse(); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// makesubfacemap() Create a map from vertex to subfaces incident at it. // +// // +// The map is returned in two arrays 'idx2faclist' and 'facperverlist'. All // +// subfaces incident at i-th vertex (i is counted from 0) are found in the // +// array facperverlist[j], where idx2faclist[i] <= j < idx2faclist[i + 1]. // +// Each entry in facperverlist[j] is a subface whose origin is the vertex. // +// // +// NOTE: These two arrays will be created inside this routine, don't forget // +// to free them after using. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::makepoint2submap(memorypool* pool, int*& idx2faclist, + face*& facperverlist) +{ + face shloop; + int i, j, k; + + if (b->verbose > 1) { + printf(" Making a map from points to subfaces.\n"); + } + + // Initialize 'idx2faclist'. + idx2faclist = new int[points->items + 1]; + for (i = 0; i < points->items + 1; i++) idx2faclist[i] = 0; + + // Loop all subfaces, counter the number of subfaces incident at a vertex. + pool->traversalinit(); + shloop.sh = shellfacetraverse(pool); + while (shloop.sh != (shellface *) NULL) { + // Increment the number of incident subfaces for each vertex. + j = pointmark((point) shloop.sh[3]) - in->firstnumber; + idx2faclist[j]++; + j = pointmark((point) shloop.sh[4]) - in->firstnumber; + idx2faclist[j]++; + // Skip the third corner if it is a segment. + if (shloop.sh[5] != NULL) { + j = pointmark((point) shloop.sh[5]) - in->firstnumber; + idx2faclist[j]++; + } + shloop.sh = shellfacetraverse(pool); + } + + // Calculate the total length of array 'facperverlist'. + j = idx2faclist[0]; + idx2faclist[0] = 0; // Array starts from 0 element. + for (i = 0; i < points->items; i++) { + k = idx2faclist[i + 1]; + idx2faclist[i + 1] = idx2faclist[i] + j; + j = k; + } + + // The total length is in the last unit of idx2faclist. + facperverlist = new face[idx2faclist[i]]; + + // Loop all subfaces again, remember the subfaces at each vertex. + pool->traversalinit(); + shloop.sh = shellfacetraverse(pool); + while (shloop.sh != (shellface *) NULL) { + j = pointmark((point) shloop.sh[3]) - in->firstnumber; + shloop.shver = 0; // save the origin. + facperverlist[idx2faclist[j]] = shloop; + idx2faclist[j]++; + // Is it a subface or a subsegment? + if (shloop.sh[5] != NULL) { + j = pointmark((point) shloop.sh[4]) - in->firstnumber; + shloop.shver = 2; // save the origin. + facperverlist[idx2faclist[j]] = shloop; + idx2faclist[j]++; + j = pointmark((point) shloop.sh[5]) - in->firstnumber; + shloop.shver = 4; // save the origin. + facperverlist[idx2faclist[j]] = shloop; + idx2faclist[j]++; + } else { + j = pointmark((point) shloop.sh[4]) - in->firstnumber; + shloop.shver = 1; // save the origin. + facperverlist[idx2faclist[j]] = shloop; + idx2faclist[j]++; + } + shloop.sh = shellfacetraverse(pool); + } + + // Contents in 'idx2faclist' are shifted, now shift them back. + for (i = points->items - 1; i >= 0; i--) { + idx2faclist[i + 1] = idx2faclist[i]; + } + idx2faclist[0] = 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// tetrahedrondealloc() Deallocate space for a tet., marking it dead. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::tetrahedrondealloc(tetrahedron *dyingtetrahedron) +{ + // Set tetrahedron's vertices to NULL. This makes it possible to detect + // dead tetrahedra when traversing the list of all tetrahedra. + dyingtetrahedron[4] = (tetrahedron) NULL; + + // Dealloc the space to subfaces/subsegments. + if (dyingtetrahedron[8] != NULL) { + tet2segpool->dealloc((shellface *) dyingtetrahedron[8]); + } + if (dyingtetrahedron[9] != NULL) { + tet2subpool->dealloc((shellface *) dyingtetrahedron[9]); + } + + tetrahedrons->dealloc((void *) dyingtetrahedron); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// tetrahedrontraverse() Traverse the tetrahedra, skipping dead ones. // +// // +/////////////////////////////////////////////////////////////////////////////// + +tetgenmesh::tetrahedron* tetgenmesh::tetrahedrontraverse() +{ + tetrahedron *newtetrahedron; + + do { + newtetrahedron = (tetrahedron *) tetrahedrons->traverse(); + if (newtetrahedron == (tetrahedron *) NULL) { + return (tetrahedron *) NULL; + } + } while ((newtetrahedron[4] == (tetrahedron) NULL) || + ((point) newtetrahedron[7] == dummypoint)); + return newtetrahedron; +} + +tetgenmesh::tetrahedron* tetgenmesh::alltetrahedrontraverse() +{ + tetrahedron *newtetrahedron; + + do { + newtetrahedron = (tetrahedron *) tetrahedrons->traverse(); + if (newtetrahedron == (tetrahedron *) NULL) { + return (tetrahedron *) NULL; + } + } while (newtetrahedron[4] == (tetrahedron) NULL); // Skip dead ones. + return newtetrahedron; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// shellfacedealloc() Deallocate space for a shellface, marking it dead. // +// Used both for dealloc a subface and subsegment. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::shellfacedealloc(memorypool *pool, shellface *dyingsh) +{ + // Set shellface's vertices to NULL. This makes it possible to detect dead + // shellfaces when traversing the list of all shellfaces. + dyingsh[3] = (shellface) NULL; + pool->dealloc((void *) dyingsh); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// shellfacetraverse() Traverse the subfaces, skipping dead ones. Used // +// for both subfaces and subsegments pool traverse. // +// // +/////////////////////////////////////////////////////////////////////////////// + +tetgenmesh::shellface* tetgenmesh::shellfacetraverse(memorypool *pool) +{ + shellface *newshellface; + + do { + newshellface = (shellface *) pool->traverse(); + if (newshellface == (shellface *) NULL) { + return (shellface *) NULL; + } + } while (newshellface[3] == (shellface) NULL); // Skip dead ones. + return newshellface; +} + + +/////////////////////////////////////////////////////////////////////////////// +// // +// pointdealloc() Deallocate space for a point, marking it dead. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::pointdealloc(point dyingpoint) +{ + // Mark the point as dead. This makes it possible to detect dead points + // when traversing the list of all points. + setpointtype(dyingpoint, DEADVERTEX); + points->dealloc((void *) dyingpoint); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// pointtraverse() Traverse the points, skipping dead ones. // +// // +/////////////////////////////////////////////////////////////////////////////// + +tetgenmesh::point tetgenmesh::pointtraverse() +{ + point newpoint; + + do { + newpoint = (point) points->traverse(); + if (newpoint == (point) NULL) { + return (point) NULL; + } + } while (pointtype(newpoint) == DEADVERTEX); // Skip dead ones. + return newpoint; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// maketetrahedron() Create a new tetrahedron. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::maketetrahedron(triface *newtet) +{ + newtet->tet = (tetrahedron *) tetrahedrons->alloc(); + + // Initialize the four adjoining tetrahedra to be "outer space". + newtet->tet[0] = NULL; + newtet->tet[1] = NULL; + newtet->tet[2] = NULL; + newtet->tet[3] = NULL; + // Four NULL vertices. + newtet->tet[4] = NULL; + newtet->tet[5] = NULL; + newtet->tet[6] = NULL; + newtet->tet[7] = NULL; + // No attached segments and subfaces yet. + newtet->tet[8] = NULL; + newtet->tet[9] = NULL; + // Initialize the marker (clear all flags). + setelemmarker(newtet->tet, 0); + for (int i = 0; i < numelemattrib; i++) { + setelemattribute(newtet->tet, i, 0.0); + } + if (b->varvolume) { + setvolumebound(newtet->tet, -1.0); + } + + // Initialize the version to be Zero. + newtet->ver = 11; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// makeshellface() Create a new shellface with version zero. Used for // +// both subfaces and subsegments. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::makeshellface(memorypool *pool, face *newface) +{ + newface->sh = (shellface *) pool->alloc(); + + // No adjointing subfaces. + newface->sh[0] = NULL; + newface->sh[1] = NULL; + newface->sh[2] = NULL; + // Three NULL vertices. + newface->sh[3] = NULL; + newface->sh[4] = NULL; + newface->sh[5] = NULL; + // No adjoining subsegments. + newface->sh[6] = NULL; + newface->sh[7] = NULL; + newface->sh[8] = NULL; + // No adjoining tetrahedra. + newface->sh[9] = NULL; + newface->sh[10] = NULL; + if (checkconstraints) { + // Initialize the maximum area bound. + setareabound(*newface, 0.0); + } + // Clear the infection and marktest bits. + ((int *) (newface->sh))[shmarkindex + 1] = 0; + if (useinsertradius) { + setfacetindex(*newface, 0); + } + // Set the boundary marker to zero. + setshellmark(*newface, 0); + + newface->shver = 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// makepoint() Create a new point. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::makepoint(point* pnewpoint, enum verttype vtype) +{ + int i; + + *pnewpoint = (point) points->alloc(); + + // Initialize the point attributes. + for (i = 0; i < numpointattrib; i++) { + (*pnewpoint)[3 + i] = 0.0; + } + // Initialize the metric tensor. + for (i = 0; i < sizeoftensor; i++) { + (*pnewpoint)[pointmtrindex + i] = 0.0; + } + setpoint2tet(*pnewpoint, NULL); + setpoint2ppt(*pnewpoint, NULL); + if (b->plc || b->refine) { + // Initialize the point-to-simplex field. + setpoint2sh(*pnewpoint, NULL); + if (b->metric && (bgm != NULL)) { + setpoint2bgmtet(*pnewpoint, NULL); + } + } + // Initialize the point marker (starting from in->firstnumber). + setpointmark(*pnewpoint, (int) (points->items) - (!in->firstnumber)); + // Clear all flags. + ((int *) (*pnewpoint))[pointmarkindex + 1] = 0; + // Initialize (set) the point type. + setpointtype(*pnewpoint, vtype); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// initializepools() Calculate the sizes of the point, tetrahedron, and // +// subface. Initialize their memory pools. // +// // +// This routine also computes the indices 'pointmarkindex', 'point2simindex',// +// 'point2pbcptindex', 'elemattribindex', and 'volumeboundindex'. They are // +// used to find values within each point and tetrahedron, respectively. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::initializepools() +{ + int pointsize = 0, elesize = 0, shsize = 0; + int i; + + if (b->verbose) { + printf(" Initializing memorypools.\n"); + printf(" tetrahedron per block: %d.\n", b->tetrahedraperblock); + } + + inittables(); + + // There are three input point lists available, which are in, addin, + // and bgm->in. These point lists may have different number of + // attributes. Decide the maximum number. + numpointattrib = in->numberofpointattributes; + if (bgm != NULL) { + if (bgm->in->numberofpointattributes > numpointattrib) { + numpointattrib = bgm->in->numberofpointattributes; + } + } + if (addin != NULL) { + if (addin->numberofpointattributes > numpointattrib) { + numpointattrib = addin->numberofpointattributes; + } + } + if (b->weighted || b->flipinsert) { // -w or -L. + // The internal number of point attribute needs to be at least 1 + // (for storing point weights). + if (numpointattrib == 0) { + numpointattrib = 1; + } + } + + // Default varconstraint = 0; + if (in->segmentconstraintlist || in->facetconstraintlist) { + checkconstraints = 1; + } + if (b->plc || b->refine) { + // Save the insertion radius for Steiner points if boundaries + // are allowed be split. + if (!b->nobisect || checkconstraints) { + useinsertradius = 1; + } + } + + // The index within each point at which its metric tensor is found. + // Each vertex has three coordinates. + if (b->psc) { + // '-s' option (PSC), the u,v coordinates are provided. + pointmtrindex = 5 + numpointattrib; + // The index within each point at which its u, v coordinates are found. + // Comment: They are saved after the list of point attributes. + pointparamindex = pointmtrindex - 2; + } else { + pointmtrindex = 3 + numpointattrib; + } + // For '-m' option. A tensor field is provided (*.mtr or *.b.mtr file). + if (b->metric) { + // Decide the size (1, 3, or 6) of the metric tensor. + if (bgm != (tetgenmesh *) NULL) { + // A background mesh is allocated. It may not exist though. + sizeoftensor = (bgm->in != (tetgenio *) NULL) ? + bgm->in->numberofpointmtrs : in->numberofpointmtrs; + } else { + // No given background mesh - Itself is a background mesh. + sizeoftensor = in->numberofpointmtrs; + } + // Make sure sizeoftensor is at least 1. + sizeoftensor = (sizeoftensor > 0) ? sizeoftensor : 1; + } else { + // For '-q' option. Make sure to have space for saving a scalar value. + sizeoftensor = b->quality ? 1 : 0; + } + if (useinsertradius) { + // Increase a space (REAL) for saving point insertion radius, it is + // saved directly after the metric. + sizeoftensor++; + } + // The index within each point at which an element pointer is found, where + // the index is measured in pointers. Ensure the index is aligned to a + // sizeof(tetrahedron)-byte address. + point2simindex = ((pointmtrindex + sizeoftensor) * sizeof(REAL) + + sizeof(tetrahedron) - 1) / sizeof(tetrahedron); + if (b->plc || b->refine || b->voroout) { + // Increase the point size by three pointers, which are: + // - a pointer to a tet, read by point2tet(); + // - a pointer to a parent point, read by point2ppt()). + // - a pointer to a subface or segment, read by point2sh(); + if (b->metric && (bgm != (tetgenmesh *) NULL)) { + // Increase one pointer into the background mesh, point2bgmtet(). + pointsize = (point2simindex + 4) * sizeof(tetrahedron); + } else { + pointsize = (point2simindex + 3) * sizeof(tetrahedron); + } + } else { + // Increase the point size by two pointer, which are: + // - a pointer to a tet, read by point2tet(); + // - a pointer to a parent point, read by point2ppt()). -- Used by btree. + pointsize = (point2simindex + 2) * sizeof(tetrahedron); + } + // The index within each point at which the boundary marker is found, + // Ensure the point marker is aligned to a sizeof(int)-byte address. + pointmarkindex = (pointsize + sizeof(int) - 1) / sizeof(int); + // Now point size is the ints (indicated by pointmarkindex) plus: + // - an integer for boundary marker; + // - an integer for vertex type; + // - an integer for geometry tag (optional, -s option). + pointsize = (pointmarkindex + 2 + (b->psc ? 1 : 0)) * sizeof(tetrahedron); + + // Initialize the pool of vertices. + points = new memorypool(pointsize, b->vertexperblock, sizeof(REAL), 0); + + if (b->verbose) { + printf(" Size of a point: %d bytes.\n", points->itembytes); + } + + // Initialize the infinite vertex. + dummypoint = (point) new char[pointsize]; + // Initialize all fields of this point. + dummypoint[0] = 0.0; + dummypoint[1] = 0.0; + dummypoint[2] = 0.0; + for (i = 0; i < numpointattrib; i++) { + dummypoint[3 + i] = 0.0; + } + // Initialize the metric tensor. + for (i = 0; i < sizeoftensor; i++) { + dummypoint[pointmtrindex + i] = 0.0; + } + setpoint2tet(dummypoint, NULL); + setpoint2ppt(dummypoint, NULL); + if (b->plc || b->psc || b->refine) { + // Initialize the point-to-simplex field. + setpoint2sh(dummypoint, NULL); + if (b->metric && (bgm != NULL)) { + setpoint2bgmtet(dummypoint, NULL); + } + } + // Initialize the point marker (starting from in->firstnumber). + setpointmark(dummypoint, -1); // The unique marker for dummypoint. + // Clear all flags. + ((int *) (dummypoint))[pointmarkindex + 1] = 0; + // Initialize (set) the point type. + setpointtype(dummypoint, UNUSEDVERTEX); // Does not matter. + + // The number of bytes occupied by a tetrahedron is varying by the user- + // specified options. The contents of the first 12 pointers are listed + // in the following table: + // [0] |__ neighbor at f0 __| + // [1] |__ neighbor at f1 __| + // [2] |__ neighbor at f2 __| + // [3] |__ neighbor at f3 __| + // [4] |_____ vertex p0 ____| + // [5] |_____ vertex p1 ____| + // [6] |_____ vertex p2 ____| + // [7] |_____ vertex p3 ____| + // [8] |__ segments array __| (used by -p) + // [9] |__ subfaces array __| (used by -p) + // [10] |_____ reserved _____| + // [11] |___ elem marker ____| (used as an integer) + + elesize = 12 * sizeof(tetrahedron); + + // The index to find the element markers. An integer containing varies + // flags and element counter. + assert(sizeof(int) <= sizeof(tetrahedron)); + assert((sizeof(tetrahedron) % sizeof(int)) == 0); + elemmarkerindex = (elesize - sizeof(tetrahedron)) / sizeof(int); + + // The actual number of element attributes. Note that if the + // `b->regionattrib' flag is set, an additional attribute will be added. + numelemattrib = in->numberoftetrahedronattributes + (b->regionattrib > 0); + + // The index within each element at which its attributes are found, where + // the index is measured in REALs. + elemattribindex = (elesize + sizeof(REAL) - 1) / sizeof(REAL); + // The index within each element at which the maximum volume bound is + // found, where the index is measured in REALs. + volumeboundindex = elemattribindex + numelemattrib; + // If element attributes or an constraint are needed, increase the number + // of bytes occupied by an element. + if (b->varvolume) { + elesize = (volumeboundindex + 1) * sizeof(REAL); + } else if (numelemattrib > 0) { + elesize = volumeboundindex * sizeof(REAL); + } + + + // Having determined the memory size of an element, initialize the pool. + tetrahedrons = new memorypool(elesize, b->tetrahedraperblock, sizeof(void *), + 16); + + if (b->verbose) { + printf(" Size of a tetrahedron: %d (%d) bytes.\n", elesize, + tetrahedrons->itembytes); + } + + if (b->plc || b->refine) { // if (b->useshelles) { + // The number of bytes occupied by a subface. The list of pointers + // stored in a subface are: three to other subfaces, three to corners, + // three to subsegments, two to tetrahedra. + shsize = 11 * sizeof(shellface); + // The index within each subface at which the maximum area bound is + // found, where the index is measured in REALs. + areaboundindex = (shsize + sizeof(REAL) - 1) / sizeof(REAL); + // If -q switch is in use, increase the number of bytes occupied by + // a subface for saving maximum area bound. + if (checkconstraints) { + shsize = (areaboundindex + 1) * sizeof(REAL); + } else { + shsize = areaboundindex * sizeof(REAL); + } + // The index within subface at which the facet marker is found. Ensure + // the marker is aligned to a sizeof(int)-byte address. + shmarkindex = (shsize + sizeof(int) - 1) / sizeof(int); + // Increase the number of bytes by two or three integers, one for facet + // marker, one for shellface type, and optionally one for pbc group. + shsize = (shmarkindex + 2) * sizeof(shellface); + if (useinsertradius) { + // Increase the number of byte by one integer for storing facet index. + // set/read by setfacetindex() and getfacetindex. + shsize = (shmarkindex + 3) * sizeof(shellface); + } + + // Initialize the pool of subfaces. Each subface record is eight-byte + // aligned so it has room to store an edge version (from 0 to 5) in + // the least three bits. + subfaces = new memorypool(shsize, b->shellfaceperblock, sizeof(void *), 8); + + if (b->verbose) { + printf(" Size of a shellface: %d (%d) bytes.\n", shsize, + subfaces->itembytes); + } + + // Initialize the pool of subsegments. The subsegment's record is same + // with subface. + subsegs = new memorypool(shsize, b->shellfaceperblock, sizeof(void *), 8); + + // Initialize the pool for tet-subseg connections. + tet2segpool = new memorypool(6 * sizeof(shellface), b->shellfaceperblock, + sizeof(void *), 0); + // Initialize the pool for tet-subface connections. + tet2subpool = new memorypool(4 * sizeof(shellface), b->shellfaceperblock, + sizeof(void *), 0); + + // Initialize arraypools for segment & facet recovery. + subsegstack = new arraypool(sizeof(face), 10); + subfacstack = new arraypool(sizeof(face), 10); + subvertstack = new arraypool(sizeof(point), 8); + + // Initialize arraypools for surface point insertion/deletion. + caveshlist = new arraypool(sizeof(face), 8); + caveshbdlist = new arraypool(sizeof(face), 8); + cavesegshlist = new arraypool(sizeof(face), 4); + + cavetetshlist = new arraypool(sizeof(face), 8); + cavetetseglist = new arraypool(sizeof(face), 8); + caveencshlist = new arraypool(sizeof(face), 8); + caveencseglist = new arraypool(sizeof(face), 8); + } + + // Initialize the pools for flips. + flippool = new memorypool(sizeof(badface), 1024, sizeof(void *), 0); + unflipqueue = new arraypool(sizeof(badface), 10); + + // Initialize the arraypools for point insertion. + cavetetlist = new arraypool(sizeof(triface), 10); + cavebdrylist = new arraypool(sizeof(triface), 10); + caveoldtetlist = new arraypool(sizeof(triface), 10); + cavetetvertlist = new arraypool(sizeof(point), 10); +} + +//// //// +//// //// +//// mempool_cxx ////////////////////////////////////////////////////////////// + +//// geom_cxx ///////////////////////////////////////////////////////////////// +//// //// +//// //// + +// PI is the ratio of a circle's circumference to its diameter. +REAL tetgenmesh::PI = 3.14159265358979323846264338327950288419716939937510582; + +/////////////////////////////////////////////////////////////////////////////// +// // +// insphere_s() Insphere test with symbolic perturbation. // +// // +// Given four points pa, pb, pc, and pd, test if the point pe lies inside or // +// outside the circumscribed sphere of the four points. // +// // +// Here we assume that the 3d orientation of the point sequence {pa, pb, pc, // +// pd} is positive (NOT zero), i.e., pd lies above the plane passing through // +// points pa, pb, and pc. Otherwise, the returned sign is flipped. // +// // +// Return a positive value (> 0) if pe lies inside, a negative value (< 0) // +// if pe lies outside the sphere, the returned value will not be zero. // +// // +/////////////////////////////////////////////////////////////////////////////// + +REAL tetgenmesh::insphere_s(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe) +{ + REAL sign; + + sign = insphere(pa, pb, pc, pd, pe); + if (sign != 0.0) { + return sign; + } + + // Symbolic perturbation. + point pt[5], swappt; + REAL oriA, oriB; + int swaps, count; + int n, i; + + pt[0] = pa; + pt[1] = pb; + pt[2] = pc; + pt[3] = pd; + pt[4] = pe; + + // Sort the five points such that their indices are in the increasing + // order. An optimized bubble sort algorithm is used, i.e., it has + // the worst case O(n^2) runtime, but it is usually much faster. + swaps = 0; // Record the total number of swaps. + n = 5; + do { + count = 0; + n = n - 1; + for (i = 0; i < n; i++) { + if (pointmark(pt[i]) > pointmark(pt[i+1])) { + swappt = pt[i]; pt[i] = pt[i+1]; pt[i+1] = swappt; + count++; + } + } + swaps += count; + } while (count > 0); // Continue if some points are swapped. + + oriA = orient3d(pt[1], pt[2], pt[3], pt[4]); + if (oriA != 0.0) { + // Flip the sign if there are odd number of swaps. + if ((swaps % 2) != 0) oriA = -oriA; + return oriA; + } + + oriB = -orient3d(pt[0], pt[2], pt[3], pt[4]); + assert(oriB != 0.0); // SELF_CHECK + // Flip the sign if there are odd number of swaps. + if ((swaps % 2) != 0) oriB = -oriB; + return oriB; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// orient4d_s() 4d orientation test with symbolic perturbation. // +// // +// Given four lifted points pa', pb', pc', and pd' in R^4,test if the lifted // +// point pe' in R^4 lies below or above the hyperplane passing through the // +// four points pa', pb', pc', and pd'. // +// // +// Here we assume that the 3d orientation of the point sequence {pa, pb, pc, // +// pd} is positive (NOT zero), i.e., pd lies above the plane passing through // +// the points pa, pb, and pc. Otherwise, the returned sign is flipped. // +// // +// Return a positive value (> 0) if pe' lies below, a negative value (< 0) // +// if pe' lies above the hyperplane, the returned value should not be zero. // +// // +/////////////////////////////////////////////////////////////////////////////// + +REAL tetgenmesh::orient4d_s(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe, + REAL aheight, REAL bheight, REAL cheight, + REAL dheight, REAL eheight) +{ + REAL sign; + + sign = orient4d(pa, pb, pc, pd, pe, + aheight, bheight, cheight, dheight, eheight); + if (sign != 0.0) { + return sign; + } + + // Symbolic perturbation. + point pt[5], swappt; + REAL oriA, oriB; + int swaps, count; + int n, i; + + pt[0] = pa; + pt[1] = pb; + pt[2] = pc; + pt[3] = pd; + pt[4] = pe; + + // Sort the five points such that their indices are in the increasing + // order. An optimized bubble sort algorithm is used, i.e., it has + // the worst case O(n^2) runtime, but it is usually much faster. + swaps = 0; // Record the total number of swaps. + n = 5; + do { + count = 0; + n = n - 1; + for (i = 0; i < n; i++) { + if (pointmark(pt[i]) > pointmark(pt[i+1])) { + swappt = pt[i]; pt[i] = pt[i+1]; pt[i+1] = swappt; + count++; + } + } + swaps += count; + } while (count > 0); // Continue if some points are swapped. + + oriA = orient3d(pt[1], pt[2], pt[3], pt[4]); + if (oriA != 0.0) { + // Flip the sign if there are odd number of swaps. + if ((swaps % 2) != 0) oriA = -oriA; + return oriA; + } + + oriB = -orient3d(pt[0], pt[2], pt[3], pt[4]); + assert(oriB != 0.0); // SELF_CHECK + // Flip the sign if there are odd number of swaps. + if ((swaps % 2) != 0) oriB = -oriB; + return oriB; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// tri_edge_test() Triangle-edge intersection test. // +// // +// This routine takes a triangle T (with vertices A, B, C) and an edge E (P, // +// Q) in 3D, and tests if they intersect each other. // +// // +// If the point 'R' is not NULL, it lies strictly above the plane defined by // +// A, B, C. It is used in test when T and E are coplanar. // +// // +// If T and E intersect each other, they may intersect in different ways. If // +// 'level' > 0, their intersection type will be reported 'types' and 'pos'. // +// // +// The return value indicates one of the following cases: // +// - 0, T and E are disjoint. // +// - 1, T and E intersect each other. // +// - 2, T and E are not coplanar. They intersect at a single point. // +// - 4, T and E are coplanar. They intersect at a single point or a line // +// segment (if types[1] != DISJOINT). // +// // +/////////////////////////////////////////////////////////////////////////////// + +#define SETVECTOR3(V, a0, a1, a2) (V)[0] = (a0); (V)[1] = (a1); (V)[2] = (a2) + +#define SWAP2(a0, a1, tmp) (tmp) = (a0); (a0) = (a1); (a1) = (tmp) + +int tetgenmesh::tri_edge_2d(point A, point B, point C, point P, point Q, + point R, int level, int *types, int *pos) +{ + point U[3], V[3]; // The permuted vectors of points. + int pu[3], pv[3]; // The original positions of points. + REAL abovept[3]; + REAL sA, sB, sC; + REAL s1, s2, s3, s4; + int z1; + + if (R == NULL) { + // Calculate a lift point. + if (1) { + REAL n[3], len; + // Calculate a lift point, saved in dummypoint. + facenormal(A, B, C, n, 1, NULL); + len = sqrt(dot(n, n)); + if (len != 0) { + n[0] /= len; + n[1] /= len; + n[2] /= len; + len = distance(A, B); + len += distance(B, C); + len += distance(C, A); + len /= 3.0; + R = abovept; //dummypoint; + R[0] = A[0] + len * n[0]; + R[1] = A[1] + len * n[1]; + R[2] = A[2] + len * n[2]; + } else { + // The triangle [A,B,C] is (nearly) degenerate, i.e., it is (close) + // to a line. We need a line-line intersection test. + //assert(0); + // !!! A non-save return value.!!! + return 0; // DISJOINT + } + } + } + + // Test A's, B's, and C's orientations wrt plane PQR. + sA = orient3d(P, Q, R, A); + sB = orient3d(P, Q, R, B); + sC = orient3d(P, Q, R, C); + + + if (sA < 0) { + if (sB < 0) { + if (sC < 0) { // (---). + return 0; + } else { + if (sC > 0) { // (--+). + // All points are in the right positions. + SETVECTOR3(U, A, B, C); // I3 + SETVECTOR3(V, P, Q, R); // I2 + SETVECTOR3(pu, 0, 1, 2); + SETVECTOR3(pv, 0, 1, 2); + z1 = 0; + } else { // (--0). + SETVECTOR3(U, A, B, C); // I3 + SETVECTOR3(V, P, Q, R); // I2 + SETVECTOR3(pu, 0, 1, 2); + SETVECTOR3(pv, 0, 1, 2); + z1 = 1; + } + } + } else { + if (sB > 0) { + if (sC < 0) { // (-+-). + SETVECTOR3(U, C, A, B); // PT = ST + SETVECTOR3(V, P, Q, R); // I2 + SETVECTOR3(pu, 2, 0, 1); + SETVECTOR3(pv, 0, 1, 2); + z1 = 0; + } else { + if (sC > 0) { // (-++). + SETVECTOR3(U, B, C, A); // PT = ST x ST + SETVECTOR3(V, Q, P, R); // PL = SL + SETVECTOR3(pu, 1, 2, 0); + SETVECTOR3(pv, 1, 0, 2); + z1 = 0; + } else { // (-+0). + SETVECTOR3(U, C, A, B); // PT = ST + SETVECTOR3(V, P, Q, R); // I2 + SETVECTOR3(pu, 2, 0, 1); + SETVECTOR3(pv, 0, 1, 2); + z1 = 2; + } + } + } else { + if (sC < 0) { // (-0-). + SETVECTOR3(U, C, A, B); // PT = ST + SETVECTOR3(V, P, Q, R); // I2 + SETVECTOR3(pu, 2, 0, 1); + SETVECTOR3(pv, 0, 1, 2); + z1 = 1; + } else { + if (sC > 0) { // (-0+). + SETVECTOR3(U, B, C, A); // PT = ST x ST + SETVECTOR3(V, Q, P, R); // PL = SL + SETVECTOR3(pu, 1, 2, 0); + SETVECTOR3(pv, 1, 0, 2); + z1 = 2; + } else { // (-00). + SETVECTOR3(U, B, C, A); // PT = ST x ST + SETVECTOR3(V, Q, P, R); // PL = SL + SETVECTOR3(pu, 1, 2, 0); + SETVECTOR3(pv, 1, 0, 2); + z1 = 3; + } + } + } + } + } else { + if (sA > 0) { + if (sB < 0) { + if (sC < 0) { // (+--). + SETVECTOR3(U, B, C, A); // PT = ST x ST + SETVECTOR3(V, P, Q, R); // I2 + SETVECTOR3(pu, 1, 2, 0); + SETVECTOR3(pv, 0, 1, 2); + z1 = 0; + } else { + if (sC > 0) { // (+-+). + SETVECTOR3(U, C, A, B); // PT = ST + SETVECTOR3(V, Q, P, R); // PL = SL + SETVECTOR3(pu, 2, 0, 1); + SETVECTOR3(pv, 1, 0, 2); + z1 = 0; + } else { // (+-0). + SETVECTOR3(U, C, A, B); // PT = ST + SETVECTOR3(V, Q, P, R); // PL = SL + SETVECTOR3(pu, 2, 0, 1); + SETVECTOR3(pv, 1, 0, 2); + z1 = 2; + } + } + } else { + if (sB > 0) { + if (sC < 0) { // (++-). + SETVECTOR3(U, A, B, C); // I3 + SETVECTOR3(V, Q, P, R); // PL = SL + SETVECTOR3(pu, 0, 1, 2); + SETVECTOR3(pv, 1, 0, 2); + z1 = 0; + } else { + if (sC > 0) { // (+++). + return 0; + } else { // (++0). + SETVECTOR3(U, A, B, C); // I3 + SETVECTOR3(V, Q, P, R); // PL = SL + SETVECTOR3(pu, 0, 1, 2); + SETVECTOR3(pv, 1, 0, 2); + z1 = 1; + } + } + } else { // (+0#) + if (sC < 0) { // (+0-). + SETVECTOR3(U, B, C, A); // PT = ST x ST + SETVECTOR3(V, P, Q, R); // I2 + SETVECTOR3(pu, 1, 2, 0); + SETVECTOR3(pv, 0, 1, 2); + z1 = 2; + } else { + if (sC > 0) { // (+0+). + SETVECTOR3(U, C, A, B); // PT = ST + SETVECTOR3(V, Q, P, R); // PL = SL + SETVECTOR3(pu, 2, 0, 1); + SETVECTOR3(pv, 1, 0, 2); + z1 = 1; + } else { // (+00). + SETVECTOR3(U, B, C, A); // PT = ST x ST + SETVECTOR3(V, P, Q, R); // I2 + SETVECTOR3(pu, 1, 2, 0); + SETVECTOR3(pv, 0, 1, 2); + z1 = 3; + } + } + } + } + } else { + if (sB < 0) { + if (sC < 0) { // (0--). + SETVECTOR3(U, B, C, A); // PT = ST x ST + SETVECTOR3(V, P, Q, R); // I2 + SETVECTOR3(pu, 1, 2, 0); + SETVECTOR3(pv, 0, 1, 2); + z1 = 1; + } else { + if (sC > 0) { // (0-+). + SETVECTOR3(U, A, B, C); // I3 + SETVECTOR3(V, P, Q, R); // I2 + SETVECTOR3(pu, 0, 1, 2); + SETVECTOR3(pv, 0, 1, 2); + z1 = 2; + } else { // (0-0). + SETVECTOR3(U, C, A, B); // PT = ST + SETVECTOR3(V, Q, P, R); // PL = SL + SETVECTOR3(pu, 2, 0, 1); + SETVECTOR3(pv, 1, 0, 2); + z1 = 3; + } + } + } else { + if (sB > 0) { + if (sC < 0) { // (0+-). + SETVECTOR3(U, A, B, C); // I3 + SETVECTOR3(V, Q, P, R); // PL = SL + SETVECTOR3(pu, 0, 1, 2); + SETVECTOR3(pv, 1, 0, 2); + z1 = 2; + } else { + if (sC > 0) { // (0++). + SETVECTOR3(U, B, C, A); // PT = ST x ST + SETVECTOR3(V, Q, P, R); // PL = SL + SETVECTOR3(pu, 1, 2, 0); + SETVECTOR3(pv, 1, 0, 2); + z1 = 1; + } else { // (0+0). + SETVECTOR3(U, C, A, B); // PT = ST + SETVECTOR3(V, P, Q, R); // I2 + SETVECTOR3(pu, 2, 0, 1); + SETVECTOR3(pv, 0, 1, 2); + z1 = 3; + } + } + } else { // (00#) + if (sC < 0) { // (00-). + SETVECTOR3(U, A, B, C); // I3 + SETVECTOR3(V, Q, P, R); // PL = SL + SETVECTOR3(pu, 0, 1, 2); + SETVECTOR3(pv, 1, 0, 2); + z1 = 3; + } else { + if (sC > 0) { // (00+). + SETVECTOR3(U, A, B, C); // I3 + SETVECTOR3(V, P, Q, R); // I2 + SETVECTOR3(pu, 0, 1, 2); + SETVECTOR3(pv, 0, 1, 2); + z1 = 3; + } else { // (000) + // Not possible unless ABC is degenerate. + // Avoiding compiler warnings. + SETVECTOR3(U, A, B, C); // I3 + SETVECTOR3(V, P, Q, R); // I2 + SETVECTOR3(pu, 0, 1, 2); + SETVECTOR3(pv, 0, 1, 2); + z1 = 4; + } + } + } + } + } + } + + s1 = orient3d(U[0], U[2], R, V[1]); // A, C, R, Q + s2 = orient3d(U[1], U[2], R, V[0]); // B, C, R, P + + if (s1 > 0) { + return 0; + } + if (s2 < 0) { + return 0; + } + + if (level == 0) { + return 1; // They are intersected. + } + + assert(z1 != 4); // SELF_CHECK + + if (z1 == 1) { + if (s1 == 0) { // (0###) + // C = Q. + types[0] = (int) SHAREVERT; + pos[0] = pu[2]; // C + pos[1] = pv[1]; // Q + types[1] = (int) DISJOINT; + } else { + if (s2 == 0) { // (#0##) + // C = P. + types[0] = (int) SHAREVERT; + pos[0] = pu[2]; // C + pos[1] = pv[0]; // P + types[1] = (int) DISJOINT; + } else { // (-+##) + // C in [P, Q]. + types[0] = (int) ACROSSVERT; + pos[0] = pu[2]; // C + pos[1] = pv[0]; // [P, Q] + types[1] = (int) DISJOINT; + } + } + return 4; + } + + s3 = orient3d(U[0], U[2], R, V[0]); // A, C, R, P + s4 = orient3d(U[1], U[2], R, V[1]); // B, C, R, Q + + if (z1 == 0) { // (tritri-03) + if (s1 < 0) { + if (s3 > 0) { + assert(s2 > 0); // SELF_CHECK + if (s4 > 0) { + // [P, Q] overlaps [k, l] (-+++). + types[0] = (int) ACROSSEDGE; + pos[0] = pu[2]; // [C, A] + pos[1] = pv[0]; // [P, Q] + types[1] = (int) TOUCHFACE; + pos[2] = 3; // [A, B, C] + pos[3] = pv[1]; // Q + } else { + if (s4 == 0) { + // Q = l, [P, Q] contains [k, l] (-++0). + types[0] = (int) ACROSSEDGE; + pos[0] = pu[2]; // [C, A] + pos[1] = pv[0]; // [P, Q] + types[1] = (int) TOUCHEDGE; + pos[2] = pu[1]; // [B, C] + pos[3] = pv[1]; // Q + } else { // s4 < 0 + // [P, Q] contains [k, l] (-++-). + types[0] = (int) ACROSSEDGE; + pos[0] = pu[2]; // [C, A] + pos[1] = pv[0]; // [P, Q] + types[1] = (int) ACROSSEDGE; + pos[2] = pu[1]; // [B, C] + pos[3] = pv[0]; // [P, Q] + } + } + } else { + if (s3 == 0) { + assert(s2 > 0); // SELF_CHECK + if (s4 > 0) { + // P = k, [P, Q] in [k, l] (-+0+). + types[0] = (int) TOUCHEDGE; + pos[0] = pu[2]; // [C, A] + pos[1] = pv[0]; // P + types[1] = (int) TOUCHFACE; + pos[2] = 3; // [A, B, C] + pos[3] = pv[1]; // Q + } else { + if (s4 == 0) { + // [P, Q] = [k, l] (-+00). + types[0] = (int) TOUCHEDGE; + pos[0] = pu[2]; // [C, A] + pos[1] = pv[0]; // P + types[1] = (int) TOUCHEDGE; + pos[2] = pu[1]; // [B, C] + pos[3] = pv[1]; // Q + } else { + // P = k, [P, Q] contains [k, l] (-+0-). + types[0] = (int) TOUCHEDGE; + pos[0] = pu[2]; // [C, A] + pos[1] = pv[0]; // P + types[1] = (int) ACROSSEDGE; + pos[2] = pu[1]; // [B, C] + pos[3] = pv[0]; // [P, Q] + } + } + } else { // s3 < 0 + if (s2 > 0) { + if (s4 > 0) { + // [P, Q] in [k, l] (-+-+). + types[0] = (int) TOUCHFACE; + pos[0] = 3; // [A, B, C] + pos[1] = pv[0]; // P + types[1] = (int) TOUCHFACE; + pos[2] = 3; // [A, B, C] + pos[3] = pv[1]; // Q + } else { + if (s4 == 0) { + // Q = l, [P, Q] in [k, l] (-+-0). + types[0] = (int) TOUCHFACE; + pos[0] = 3; // [A, B, C] + pos[1] = pv[0]; // P + types[1] = (int) TOUCHEDGE; + pos[2] = pu[1]; // [B, C] + pos[3] = pv[1]; // Q + } else { // s4 < 0 + // [P, Q] overlaps [k, l] (-+--). + types[0] = (int) TOUCHFACE; + pos[0] = 3; // [A, B, C] + pos[1] = pv[0]; // P + types[1] = (int) ACROSSEDGE; + pos[2] = pu[1]; // [B, C] + pos[3] = pv[0]; // [P, Q] + } + } + } else { // s2 == 0 + // P = l (#0##). + types[0] = (int) TOUCHEDGE; + pos[0] = pu[1]; // [B, C] + pos[1] = pv[0]; // P + types[1] = (int) DISJOINT; + } + } + } + } else { // s1 == 0 + // Q = k (0####) + types[0] = (int) TOUCHEDGE; + pos[0] = pu[2]; // [C, A] + pos[1] = pv[1]; // Q + types[1] = (int) DISJOINT; + } + } else if (z1 == 2) { // (tritri-23) + if (s1 < 0) { + if (s3 > 0) { + assert(s2 > 0); // SELF_CHECK + if (s4 > 0) { + // [P, Q] overlaps [A, l] (-+++). + types[0] = (int) ACROSSVERT; + pos[0] = pu[0]; // A + pos[1] = pv[0]; // [P, Q] + types[1] = (int) TOUCHFACE; + pos[2] = 3; // [A, B, C] + pos[3] = pv[1]; // Q + } else { + if (s4 == 0) { + // Q = l, [P, Q] contains [A, l] (-++0). + types[0] = (int) ACROSSVERT; + pos[0] = pu[0]; // A + pos[1] = pv[0]; // [P, Q] + types[1] = (int) TOUCHEDGE; + pos[2] = pu[1]; // [B, C] + pos[3] = pv[1]; // Q + } else { // s4 < 0 + // [P, Q] contains [A, l] (-++-). + types[0] = (int) ACROSSVERT; + pos[0] = pu[0]; // A + pos[1] = pv[0]; // [P, Q] + types[1] = (int) ACROSSEDGE; + pos[2] = pu[1]; // [B, C] + pos[3] = pv[0]; // [P, Q] + } + } + } else { + if (s3 == 0) { + assert(s2 > 0); // SELF_CHECK + if (s4 > 0) { + // P = A, [P, Q] in [A, l] (-+0+). + types[0] = (int) SHAREVERT; + pos[0] = pu[0]; // A + pos[1] = pv[0]; // P + types[1] = (int) TOUCHFACE; + pos[2] = 3; // [A, B, C] + pos[3] = pv[1]; // Q + } else { + if (s4 == 0) { + // [P, Q] = [A, l] (-+00). + types[0] = (int) SHAREVERT; + pos[0] = pu[0]; // A + pos[1] = pv[0]; // P + types[1] = (int) TOUCHEDGE; + pos[2] = pu[1]; // [B, C] + pos[3] = pv[1]; // Q + } else { // s4 < 0 + // Q = l, [P, Q] in [A, l] (-+0-). + types[0] = (int) SHAREVERT; + pos[0] = pu[0]; // A + pos[1] = pv[0]; // P + types[1] = (int) ACROSSEDGE; + pos[2] = pu[1]; // [B, C] + pos[3] = pv[0]; // [P, Q] + } + } + } else { // s3 < 0 + if (s2 > 0) { + if (s4 > 0) { + // [P, Q] in [A, l] (-+-+). + types[0] = (int) TOUCHFACE; + pos[0] = 3; // [A, B, C] + pos[1] = pv[0]; // P + types[0] = (int) TOUCHFACE; + pos[0] = 3; // [A, B, C] + pos[1] = pv[1]; // Q + } else { + if (s4 == 0) { + // Q = l, [P, Q] in [A, l] (-+-0). + types[0] = (int) TOUCHFACE; + pos[0] = 3; // [A, B, C] + pos[1] = pv[0]; // P + types[0] = (int) TOUCHEDGE; + pos[0] = pu[1]; // [B, C] + pos[1] = pv[1]; // Q + } else { // s4 < 0 + // [P, Q] overlaps [A, l] (-+--). + types[0] = (int) TOUCHFACE; + pos[0] = 3; // [A, B, C] + pos[1] = pv[0]; // P + types[0] = (int) ACROSSEDGE; + pos[0] = pu[1]; // [B, C] + pos[1] = pv[0]; // [P, Q] + } + } + } else { // s2 == 0 + // P = l (#0##). + types[0] = (int) TOUCHEDGE; + pos[0] = pu[1]; // [B, C] + pos[1] = pv[0]; // P + types[1] = (int) DISJOINT; + } + } + } + } else { // s1 == 0 + // Q = A (0###). + types[0] = (int) SHAREVERT; + pos[0] = pu[0]; // A + pos[1] = pv[1]; // Q + types[1] = (int) DISJOINT; + } + } else if (z1 == 3) { // (tritri-33) + if (s1 < 0) { + if (s3 > 0) { + assert(s2 > 0); // SELF_CHECK + if (s4 > 0) { + // [P, Q] overlaps [A, B] (-+++). + types[0] = (int) ACROSSVERT; + pos[0] = pu[0]; // A + pos[1] = pv[0]; // [P, Q] + types[1] = (int) TOUCHEDGE; + pos[2] = pu[0]; // [A, B] + pos[3] = pv[1]; // Q + } else { + if (s4 == 0) { + // Q = B, [P, Q] contains [A, B] (-++0). + types[0] = (int) ACROSSVERT; + pos[0] = pu[0]; // A + pos[1] = pv[0]; // [P, Q] + types[1] = (int) SHAREVERT; + pos[2] = pu[1]; // B + pos[3] = pv[1]; // Q + } else { // s4 < 0 + // [P, Q] contains [A, B] (-++-). + types[0] = (int) ACROSSVERT; + pos[0] = pu[0]; // A + pos[1] = pv[0]; // [P, Q] + types[1] = (int) ACROSSVERT; + pos[2] = pu[1]; // B + pos[3] = pv[0]; // [P, Q] + } + } + } else { + if (s3 == 0) { + assert(s2 > 0); // SELF_CHECK + if (s4 > 0) { + // P = A, [P, Q] in [A, B] (-+0+). + types[0] = (int) SHAREVERT; + pos[0] = pu[0]; // A + pos[1] = pv[0]; // P + types[1] = (int) TOUCHEDGE; + pos[2] = pu[0]; // [A, B] + pos[3] = pv[1]; // Q + } else { + if (s4 == 0) { + // [P, Q] = [A, B] (-+00). + types[0] = (int) SHAREEDGE; + pos[0] = pu[0]; // [A, B] + pos[1] = pv[0]; // [P, Q] + types[1] = (int) DISJOINT; + } else { // s4 < 0 + // P= A, [P, Q] in [A, B] (-+0-). + types[0] = (int) SHAREVERT; + pos[0] = pu[0]; // A + pos[1] = pv[0]; // P + types[1] = (int) ACROSSVERT; + pos[2] = pu[1]; // B + pos[3] = pv[0]; // [P, Q] + } + } + } else { // s3 < 0 + if (s2 > 0) { + if (s4 > 0) { + // [P, Q] in [A, B] (-+-+). + types[0] = (int) TOUCHEDGE; + pos[0] = pu[0]; // [A, B] + pos[1] = pv[0]; // P + types[1] = (int) TOUCHEDGE; + pos[2] = pu[0]; // [A, B] + pos[3] = pv[1]; // Q + } else { + if (s4 == 0) { + // Q = B, [P, Q] in [A, B] (-+-0). + types[0] = (int) TOUCHEDGE; + pos[0] = pu[0]; // [A, B] + pos[1] = pv[0]; // P + types[1] = (int) SHAREVERT; + pos[2] = pu[1]; // B + pos[3] = pv[1]; // Q + } else { // s4 < 0 + // [P, Q] overlaps [A, B] (-+--). + types[0] = (int) TOUCHEDGE; + pos[0] = pu[0]; // [A, B] + pos[1] = pv[0]; // P + types[1] = (int) ACROSSVERT; + pos[2] = pu[1]; // B + pos[3] = pv[0]; // [P, Q] + } + } + } else { // s2 == 0 + // P = B (#0##). + types[0] = (int) SHAREVERT; + pos[0] = pu[1]; // B + pos[1] = pv[0]; // P + types[1] = (int) DISJOINT; + } + } + } + } else { // s1 == 0 + // Q = A (0###). + types[0] = (int) SHAREVERT; + pos[0] = pu[0]; // A + pos[1] = pv[1]; // Q + types[1] = (int) DISJOINT; + } + } + + return 4; +} + +int tetgenmesh::tri_edge_tail(point A,point B,point C,point P,point Q,point R, + REAL sP,REAL sQ,int level,int *types,int *pos) +{ + point U[3], V[3]; //, Ptmp; + int pu[3], pv[3]; //, itmp; + REAL s1, s2, s3; + int z1; + + + if (sP < 0) { + if (sQ < 0) { // (--) disjoint + return 0; + } else { + if (sQ > 0) { // (-+) + SETVECTOR3(U, A, B, C); + SETVECTOR3(V, P, Q, R); + SETVECTOR3(pu, 0, 1, 2); + SETVECTOR3(pv, 0, 1, 2); + z1 = 0; + } else { // (-0) + SETVECTOR3(U, A, B, C); + SETVECTOR3(V, P, Q, R); + SETVECTOR3(pu, 0, 1, 2); + SETVECTOR3(pv, 0, 1, 2); + z1 = 1; + } + } + } else { + if (sP > 0) { // (+-) + if (sQ < 0) { + SETVECTOR3(U, A, B, C); + SETVECTOR3(V, Q, P, R); // P and Q are flipped. + SETVECTOR3(pu, 0, 1, 2); + SETVECTOR3(pv, 1, 0, 2); + z1 = 0; + } else { + if (sQ > 0) { // (++) disjoint + return 0; + } else { // (+0) + SETVECTOR3(U, B, A, C); // A and B are flipped. + SETVECTOR3(V, P, Q, R); + SETVECTOR3(pu, 1, 0, 2); + SETVECTOR3(pv, 0, 1, 2); + z1 = 1; + } + } + } else { // sP == 0 + if (sQ < 0) { // (0-) + SETVECTOR3(U, A, B, C); + SETVECTOR3(V, Q, P, R); // P and Q are flipped. + SETVECTOR3(pu, 0, 1, 2); + SETVECTOR3(pv, 1, 0, 2); + z1 = 1; + } else { + if (sQ > 0) { // (0+) + SETVECTOR3(U, B, A, C); // A and B are flipped. + SETVECTOR3(V, Q, P, R); // P and Q are flipped. + SETVECTOR3(pu, 1, 0, 2); + SETVECTOR3(pv, 1, 0, 2); + z1 = 1; + } else { // (00) + // A, B, C, P, and Q are coplanar. + z1 = 2; + } + } + } + } + + if (z1 == 2) { + // The triangle and the edge are coplanar. + return tri_edge_2d(A, B, C, P, Q, R, level, types, pos); + } + + s1 = orient3d(U[0], U[1], V[0], V[1]); + if (s1 < 0) { + return 0; + } + + s2 = orient3d(U[1], U[2], V[0], V[1]); + if (s2 < 0) { + return 0; + } + + s3 = orient3d(U[2], U[0], V[0], V[1]); + if (s3 < 0) { + return 0; + } + + if (level == 0) { + return 1; // The are intersected. + } + + types[1] = (int) DISJOINT; // No second intersection point. + + if (z1 == 0) { + if (s1 > 0) { + if (s2 > 0) { + if (s3 > 0) { // (+++) + // [P, Q] passes interior of [A, B, C]. + types[0] = (int) ACROSSFACE; + pos[0] = 3; // interior of [A, B, C] + pos[1] = 0; // [P, Q] + } else { // s3 == 0 (++0) + // [P, Q] intersects [C, A]. + types[0] = (int) ACROSSEDGE; + pos[0] = pu[2]; // [C, A] + pos[1] = 0; // [P, Q] + } + } else { // s2 == 0 + if (s3 > 0) { // (+0+) + // [P, Q] intersects [B, C]. + types[0] = (int) ACROSSEDGE; + pos[0] = pu[1]; // [B, C] + pos[1] = 0; // [P, Q] + } else { // s3 == 0 (+00) + // [P, Q] passes C. + types[0] = (int) ACROSSVERT; + pos[0] = pu[2]; // C + pos[1] = 0; // [P, Q] + } + } + } else { // s1 == 0 + if (s2 > 0) { + if (s3 > 0) { // (0++) + // [P, Q] intersects [A, B]. + types[0] = (int) ACROSSEDGE; + pos[0] = pu[0]; // [A, B] + pos[1] = 0; // [P, Q] + } else { // s3 == 0 (0+0) + // [P, Q] passes A. + types[0] = (int) ACROSSVERT; + pos[0] = pu[0]; // A + pos[1] = 0; // [P, Q] + } + } else { // s2 == 0 + if (s3 > 0) { // (00+) + // [P, Q] passes B. + types[0] = (int) ACROSSVERT; + pos[0] = pu[1]; // B + pos[1] = 0; // [P, Q] + } else { // s3 == 0 (000) + // Impossible. + assert(0); + } + } + } + } else { // z1 == 1 + if (s1 > 0) { + if (s2 > 0) { + if (s3 > 0) { // (+++) + // Q lies in [A, B, C]. + types[0] = (int) TOUCHFACE; + pos[0] = 0; // [A, B, C] + pos[1] = pv[1]; // Q + } else { // s3 == 0 (++0) + // Q lies on [C, A]. + types[0] = (int) TOUCHEDGE; + pos[0] = pu[2]; // [C, A] + pos[1] = pv[1]; // Q + } + } else { // s2 == 0 + if (s3 > 0) { // (+0+) + // Q lies on [B, C]. + types[0] = (int) TOUCHEDGE; + pos[0] = pu[1]; // [B, C] + pos[1] = pv[1]; // Q + } else { // s3 == 0 (+00) + // Q = C. + types[0] = (int) SHAREVERT; + pos[0] = pu[2]; // C + pos[1] = pv[1]; // Q + } + } + } else { // s1 == 0 + if (s2 > 0) { + if (s3 > 0) { // (0++) + // Q lies on [A, B]. + types[0] = (int) TOUCHEDGE; + pos[0] = pu[0]; // [A, B] + pos[1] = pv[1]; // Q + } else { // s3 == 0 (0+0) + // Q = A. + types[0] = (int) SHAREVERT; + pos[0] = pu[0]; // A + pos[1] = pv[1]; // Q + } + } else { // s2 == 0 + if (s3 > 0) { // (00+) + // Q = B. + types[0] = (int) SHAREVERT; + pos[0] = pu[1]; // B + pos[1] = pv[1]; // Q + } else { // s3 == 0 (000) + // Impossible. + assert(0); + } + } + } + } + + // T and E intersect in a single point. + return 2; +} + +int tetgenmesh::tri_edge_test(point A, point B, point C, point P, point Q, + point R, int level, int *types, int *pos) +{ + REAL sP, sQ; + + // Test the locations of P and Q with respect to ABC. + sP = orient3d(A, B, C, P); + sQ = orient3d(A, B, C, Q); + + return tri_edge_tail(A, B, C, P, Q, R, sP, sQ, level, types, pos); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// tri_tri_inter() Test whether two triangle (abc) and (opq) are // +// intersecting or not. // +// // +// Return 0 if they are disjoint. Otherwise, return 1. 'type' returns one of // +// the four cases: SHAREVERTEX, SHAREEDGE, SHAREFACE, and INTERSECT. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::tri_edge_inter_tail(REAL* A, REAL* B, REAL* C, REAL* P, + REAL* Q, REAL s_p, REAL s_q) +{ + int types[2], pos[4]; + int ni; // =0, 2, 4 + + ni = tri_edge_tail(A, B, C, P, Q, NULL, s_p, s_q, 1, types, pos); + + if (ni > 0) { + if (ni == 2) { + // Get the intersection type. + if (types[0] == (int) SHAREVERT) { + return (int) SHAREVERT; + } else { + return (int) INTERSECT; + } + } else if (ni == 4) { + // There may be two intersections. + if (types[0] == (int) SHAREVERT) { + if (types[1] == (int) DISJOINT) { + return (int) SHAREVERT; + } else { + assert(types[1] != (int) SHAREVERT); + return (int) INTERSECT; + } + } else { + if (types[0] == (int) SHAREEDGE) { + return (int) SHAREEDGE; + } else { + return (int) INTERSECT; + } + } + } else { + assert(0); + } + } + + return (int) DISJOINT; +} + +int tetgenmesh::tri_tri_inter(REAL* A,REAL* B,REAL* C,REAL* O,REAL* P,REAL* Q) +{ + REAL s_o, s_p, s_q; + REAL s_a, s_b, s_c; + + s_o = orient3d(A, B, C, O); + s_p = orient3d(A, B, C, P); + s_q = orient3d(A, B, C, Q); + if ((s_o * s_p > 0.0) && (s_o * s_q > 0.0)) { + // o, p, q are all in the same halfspace of ABC. + return 0; // DISJOINT; + } + + s_a = orient3d(O, P, Q, A); + s_b = orient3d(O, P, Q, B); + s_c = orient3d(O, P, Q, C); + if ((s_a * s_b > 0.0) && (s_a * s_c > 0.0)) { + // a, b, c are all in the same halfspace of OPQ. + return 0; // DISJOINT; + } + + int abcop, abcpq, abcqo; + int shareedge = 0; + + abcop = tri_edge_inter_tail(A, B, C, O, P, s_o, s_p); + if (abcop == (int) INTERSECT) { + return (int) INTERSECT; + } else if (abcop == (int) SHAREEDGE) { + shareedge++; + } + abcpq = tri_edge_inter_tail(A, B, C, P, Q, s_p, s_q); + if (abcpq == (int) INTERSECT) { + return (int) INTERSECT; + } else if (abcpq == (int) SHAREEDGE) { + shareedge++; + } + abcqo = tri_edge_inter_tail(A, B, C, Q, O, s_q, s_o); + if (abcqo == (int) INTERSECT) { + return (int) INTERSECT; + } else if (abcqo == (int) SHAREEDGE) { + shareedge++; + } + if (shareedge == 3) { + // opq are coincident with abc. + return (int) SHAREFACE; + } + + // It is only possible either no share edge or one. + assert(shareedge == 0 || shareedge == 1); + + // Continue to detect whether opq and abc are intersecting or not. + int opqab, opqbc, opqca; + + opqab = tri_edge_inter_tail(O, P, Q, A, B, s_a, s_b); + if (opqab == (int) INTERSECT) { + return (int) INTERSECT; + } + opqbc = tri_edge_inter_tail(O, P, Q, B, C, s_b, s_c); + if (opqbc == (int) INTERSECT) { + return (int) INTERSECT; + } + opqca = tri_edge_inter_tail(O, P, Q, C, A, s_c, s_a); + if (opqca == (int) INTERSECT) { + return (int) INTERSECT; + } + + // At this point, two triangles are not intersecting and not coincident. + // They may be share an edge, or share a vertex, or disjoint. + if (abcop == (int) SHAREEDGE) { + assert((abcpq == (int) SHAREVERT) && (abcqo == (int) SHAREVERT)); + // op is coincident with an edge of abc. + return (int) SHAREEDGE; + } + if (abcpq == (int) SHAREEDGE) { + assert((abcop == (int) SHAREVERT) && (abcqo == (int) SHAREVERT)); + // pq is coincident with an edge of abc. + return (int) SHAREEDGE; + } + if (abcqo == (int) SHAREEDGE) { + assert((abcop == (int) SHAREVERT) && (abcpq == (int) SHAREVERT)); + // qo is coincident with an edge of abc. + return (int) SHAREEDGE; + } + + // They may share a vertex or disjoint. + if (abcop == (int) SHAREVERT) { + // o or p is coincident with a vertex of abc. + if (abcpq == (int) SHAREVERT) { + // p is the coincident vertex. + assert(abcqo != (int) SHAREVERT); + } else { + // o is the coincident vertex. + assert(abcqo == (int) SHAREVERT); + } + return (int) SHAREVERT; + } + if (abcpq == (int) SHAREVERT) { + // q is the coincident vertex. + assert(abcqo == (int) SHAREVERT); + return (int) SHAREVERT; + } + + // They are disjoint. + return (int) DISJOINT; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// lu_decmp() Compute the LU decomposition of a matrix. // +// // +// Compute the LU decomposition of a (non-singular) square matrix A using // +// partial pivoting and implicit row exchanges. The result is: // +// A = P * L * U, // +// where P is a permutation matrix, L is unit lower triangular, and U is // +// upper triangular. The factored form of A is used in combination with // +// 'lu_solve()' to solve linear equations: Ax = b, or invert a matrix. // +// // +// The inputs are a square matrix 'lu[N..n+N-1][N..n+N-1]', it's size is 'n'.// +// On output, 'lu' is replaced by the LU decomposition of a rowwise permuta- // +// tion of itself, 'ps[N..n+N-1]' is an output vector that records the row // +// permutation effected by the partial pivoting, effectively, 'ps' array // +// tells the user what the permutation matrix P is; 'd' is output as +1/-1 // +// depending on whether the number of row interchanges was even or odd, // +// respectively. // +// // +// Return true if the LU decomposition is successfully computed, otherwise, // +// return false in case that A is a singular matrix. // +// // +/////////////////////////////////////////////////////////////////////////////// + +bool tetgenmesh::lu_decmp(REAL lu[4][4], int n, int* ps, REAL* d, int N) +{ + REAL scales[4]; + REAL pivot, biggest, mult, tempf; + int pivotindex = 0; + int i, j, k; + + *d = 1.0; // No row interchanges yet. + + for (i = N; i < n + N; i++) { // For each row. + // Find the largest element in each row for row equilibration + biggest = 0.0; + for (j = N; j < n + N; j++) + if (biggest < (tempf = fabs(lu[i][j]))) + biggest = tempf; + if (biggest != 0.0) + scales[i] = 1.0 / biggest; + else { + scales[i] = 0.0; + return false; // Zero row: singular matrix. + } + ps[i] = i; // Initialize pivot sequence. + } + + for (k = N; k < n + N - 1; k++) { // For each column. + // Find the largest element in each column to pivot around. + biggest = 0.0; + for (i = k; i < n + N; i++) { + if (biggest < (tempf = fabs(lu[ps[i]][k]) * scales[ps[i]])) { + biggest = tempf; + pivotindex = i; + } + } + if (biggest == 0.0) { + return false; // Zero column: singular matrix. + } + if (pivotindex != k) { // Update pivot sequence. + j = ps[k]; + ps[k] = ps[pivotindex]; + ps[pivotindex] = j; + *d = -(*d); // ...and change the parity of d. + } + + // Pivot, eliminating an extra variable each time + pivot = lu[ps[k]][k]; + for (i = k + 1; i < n + N; i++) { + lu[ps[i]][k] = mult = lu[ps[i]][k] / pivot; + if (mult != 0.0) { + for (j = k + 1; j < n + N; j++) + lu[ps[i]][j] -= mult * lu[ps[k]][j]; + } + } + } + + // (lu[ps[n + N - 1]][n + N - 1] == 0.0) ==> A is singular. + return lu[ps[n + N - 1]][n + N - 1] != 0.0; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// lu_solve() Solves the linear equation: Ax = b, after the matrix A // +// has been decomposed into the lower and upper triangular // +// matrices L and U, where A = LU. // +// // +// 'lu[N..n+N-1][N..n+N-1]' is input, not as the matrix 'A' but rather as // +// its LU decomposition, computed by the routine 'lu_decmp'; 'ps[N..n+N-1]' // +// is input as the permutation vector returned by 'lu_decmp'; 'b[N..n+N-1]' // +// is input as the right-hand side vector, and returns with the solution // +// vector. 'lu', 'n', and 'ps' are not modified by this routine and can be // +// left in place for successive calls with different right-hand sides 'b'. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::lu_solve(REAL lu[4][4], int n, int* ps, REAL* b, int N) +{ + int i, j; + REAL X[4], dot; + + for (i = N; i < n + N; i++) X[i] = 0.0; + + // Vector reduction using U triangular matrix. + for (i = N; i < n + N; i++) { + dot = 0.0; + for (j = N; j < i + N; j++) + dot += lu[ps[i]][j] * X[j]; + X[i] = b[ps[i]] - dot; + } + + // Back substitution, in L triangular matrix. + for (i = n + N - 1; i >= N; i--) { + dot = 0.0; + for (j = i + 1; j < n + N; j++) + dot += lu[ps[i]][j] * X[j]; + X[i] = (X[i] - dot) / lu[ps[i]][i]; + } + + for (i = N; i < n + N; i++) b[i] = X[i]; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// incircle3d() 3D in-circle test. // +// // +// Return a negative value if pd is inside the circumcircle of the triangle // +// pa, pb, and pc. // +// // +// IMPORTANT: It assumes that [a,b] is the common edge, i.e., the two input // +// triangles are [a,b,c] and [b,a,d]. // +// // +/////////////////////////////////////////////////////////////////////////////// + +REAL tetgenmesh::incircle3d(point pa, point pb, point pc, point pd) +{ + REAL area2[2], n1[3], n2[3], c[3]; + REAL sign, r, d; + + // Calculate the areas of the two triangles [a, b, c] and [b, a, d]. + facenormal(pa, pb, pc, n1, 1, NULL); + area2[0] = dot(n1, n1); + facenormal(pb, pa, pd, n2, 1, NULL); + area2[1] = dot(n2, n2); + + if (area2[0] > area2[1]) { + // Choose [a, b, c] as the base triangle. + circumsphere(pa, pb, pc, NULL, c, &r); + d = distance(c, pd); + } else { + // Choose [b, a, d] as the base triangle. + if (area2[1] > 0) { + circumsphere(pb, pa, pd, NULL, c, &r); + d = distance(c, pc); + } else { + // The four points are collinear. This case only happens on the boundary. + return 0; // Return "not inside". + } + } + + sign = d - r; + if (fabs(sign) / r < b->epsilon) { + sign = 0; + } + + return sign; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// facenormal() Calculate the normal of the face. // +// // +// The normal of the face abc can be calculated by the cross product of 2 of // +// its 3 edge vectors. A better choice of two edge vectors will reduce the // +// numerical error during the calculation. Burdakov proved that the optimal // +// basis problem is equivalent to the minimum spanning tree problem with the // +// edge length be the functional, see Burdakov, "A greedy algorithm for the // +// optimal basis problem", BIT 37:3 (1997), 591-599. If 'pivot' > 0, the two // +// short edges in abc are chosen for the calculation. // +// // +// If 'lav' is not NULL and if 'pivot' is set, the average edge length of // +// the edges of the face [a,b,c] is returned. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::facenormal(point pa, point pb, point pc, REAL *n, int pivot, + REAL* lav) +{ + REAL v1[3], v2[3], v3[3], *pv1, *pv2; + REAL L1, L2, L3; + + v1[0] = pb[0] - pa[0]; // edge vector v1: a->b + v1[1] = pb[1] - pa[1]; + v1[2] = pb[2] - pa[2]; + v2[0] = pa[0] - pc[0]; // edge vector v2: c->a + v2[1] = pa[1] - pc[1]; + v2[2] = pa[2] - pc[2]; + + // Default, normal is calculated by: v1 x (-v2) (see Fig. fnormal). + if (pivot > 0) { + // Choose edge vectors by Burdakov's algorithm. + v3[0] = pc[0] - pb[0]; // edge vector v3: b->c + v3[1] = pc[1] - pb[1]; + v3[2] = pc[2] - pb[2]; + L1 = dot(v1, v1); + L2 = dot(v2, v2); + L3 = dot(v3, v3); + // Sort the three edge lengths. + if (L1 < L2) { + if (L2 < L3) { + pv1 = v1; pv2 = v2; // n = v1 x (-v2). + } else { + pv1 = v3; pv2 = v1; // n = v3 x (-v1). + } + } else { + if (L1 < L3) { + pv1 = v1; pv2 = v2; // n = v1 x (-v2). + } else { + pv1 = v2; pv2 = v3; // n = v2 x (-v3). + } + } + if (lav) { + // return the average edge length. + *lav = (sqrt(L1) + sqrt(L2) + sqrt(L3)) / 3.0; + } + } else { + pv1 = v1; pv2 = v2; // n = v1 x (-v2). + } + + // Calculate the face normal. + cross(pv1, pv2, n); + // Inverse the direction; + n[0] = -n[0]; + n[1] = -n[1]; + n[2] = -n[2]; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// shortdistance() Returns the shortest distance from point p to a line // +// defined by two points e1 and e2. // +// // +// First compute the projection length l_p of the vector v1 = p - e1 along // +// the vector v2 = e2 - e1. Then Pythagoras' Theorem is used to compute the // +// shortest distance. // +// // +// This routine allows that p is collinear with the line. In this case, the // +// return value is zero. The two points e1 and e2 should not be identical. // +// // +/////////////////////////////////////////////////////////////////////////////// + +REAL tetgenmesh::shortdistance(REAL* p, REAL* e1, REAL* e2) +{ + REAL v1[3], v2[3]; + REAL len, l_p; + + v1[0] = e2[0] - e1[0]; + v1[1] = e2[1] - e1[1]; + v1[2] = e2[2] - e1[2]; + v2[0] = p[0] - e1[0]; + v2[1] = p[1] - e1[1]; + v2[2] = p[2] - e1[2]; + + len = sqrt(dot(v1, v1)); + assert(len != 0.0); + + v1[0] /= len; + v1[1] /= len; + v1[2] /= len; + l_p = dot(v1, v2); + + return sqrt(dot(v2, v2) - l_p * l_p); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// triarea() Return the area of a triangle. // +// // +/////////////////////////////////////////////////////////////////////////////// + +REAL tetgenmesh::triarea(REAL* pa, REAL* pb, REAL* pc) +{ + REAL A[4][4]; + + // Compute the coefficient matrix A (3x3). + A[0][0] = pb[0] - pa[0]; + A[0][1] = pb[1] - pa[1]; + A[0][2] = pb[2] - pa[2]; // vector V1 (pa->pb) + A[1][0] = pc[0] - pa[0]; + A[1][1] = pc[1] - pa[1]; + A[1][2] = pc[2] - pa[2]; // vector V2 (pa->pc) + + cross(A[0], A[1], A[2]); // vector V3 (V1 X V2) + + return 0.5 * sqrt(dot(A[2], A[2])); // The area of [a,b,c]. +} + +REAL tetgenmesh::orient3dfast(REAL *pa, REAL *pb, REAL *pc, REAL *pd) +{ + REAL adx, bdx, cdx; + REAL ady, bdy, cdy; + REAL adz, bdz, cdz; + + adx = pa[0] - pd[0]; + bdx = pb[0] - pd[0]; + cdx = pc[0] - pd[0]; + ady = pa[1] - pd[1]; + bdy = pb[1] - pd[1]; + cdy = pc[1] - pd[1]; + adz = pa[2] - pd[2]; + bdz = pb[2] - pd[2]; + cdz = pc[2] - pd[2]; + + return adx * (bdy * cdz - bdz * cdy) + + bdx * (cdy * adz - cdz * ady) + + cdx * (ady * bdz - adz * bdy); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// interiorangle() Return the interior angle (0 - 2 * PI) between vectors // +// o->p1 and o->p2. // +// // +// 'n' is the normal of the plane containing face (o, p1, p2). The interior // +// angle is the total angle rotating from o->p1 around n to o->p2. Exchange // +// the position of p1 and p2 will get the complement angle of the other one. // +// i.e., interiorangle(o, p1, p2) = 2 * PI - interiorangle(o, p2, p1). Set // +// 'n' be NULL if you only want the interior angle between 0 - PI. // +// // +/////////////////////////////////////////////////////////////////////////////// + +REAL tetgenmesh::interiorangle(REAL* o, REAL* p1, REAL* p2, REAL* n) +{ + REAL v1[3], v2[3], np[3]; + REAL theta, costheta, lenlen; + REAL ori, len1, len2; + + // Get the interior angle (0 - PI) between o->p1, and o->p2. + v1[0] = p1[0] - o[0]; + v1[1] = p1[1] - o[1]; + v1[2] = p1[2] - o[2]; + v2[0] = p2[0] - o[0]; + v2[1] = p2[1] - o[1]; + v2[2] = p2[2] - o[2]; + len1 = sqrt(dot(v1, v1)); + len2 = sqrt(dot(v2, v2)); + lenlen = len1 * len2; + assert(lenlen != 0.0); + + costheta = dot(v1, v2) / lenlen; + if (costheta > 1.0) { + costheta = 1.0; // Roundoff. + } else if (costheta < -1.0) { + costheta = -1.0; // Roundoff. + } + theta = acos(costheta); + if (n != NULL) { + // Get a point above the face (o, p1, p2); + np[0] = o[0] + n[0]; + np[1] = o[1] + n[1]; + np[2] = o[2] + n[2]; + // Adjust theta (0 - 2 * PI). + ori = orient3d(p1, o, np, p2); + if (ori > 0.0) { + theta = 2 * PI - theta; + } + } + + return theta; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// projpt2edge() Return the projection point from a point to an edge. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::projpt2edge(REAL* p, REAL* e1, REAL* e2, REAL* prj) +{ + REAL v1[3], v2[3]; + REAL len, l_p; + + v1[0] = e2[0] - e1[0]; + v1[1] = e2[1] - e1[1]; + v1[2] = e2[2] - e1[2]; + v2[0] = p[0] - e1[0]; + v2[1] = p[1] - e1[1]; + v2[2] = p[2] - e1[2]; + + len = sqrt(dot(v1, v1)); + assert(len != 0.0); + v1[0] /= len; + v1[1] /= len; + v1[2] /= len; + l_p = dot(v1, v2); + + prj[0] = e1[0] + l_p * v1[0]; + prj[1] = e1[1] + l_p * v1[1]; + prj[2] = e1[2] + l_p * v1[2]; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// projpt2face() Return the projection point from a point to a face. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::projpt2face(REAL* p, REAL* f1, REAL* f2, REAL* f3, REAL* prj) +{ + REAL fnormal[3], v1[3]; + REAL len, dist; + + // Get the unit face normal. + facenormal(f1, f2, f3, fnormal, 1, NULL); + len = sqrt(fnormal[0]*fnormal[0] + fnormal[1]*fnormal[1] + + fnormal[2]*fnormal[2]); + fnormal[0] /= len; + fnormal[1] /= len; + fnormal[2] /= len; + // Get the vector v1 = |p - f1|. + v1[0] = p[0] - f1[0]; + v1[1] = p[1] - f1[1]; + v1[2] = p[2] - f1[2]; + // Get the project distance. + dist = dot(fnormal, v1); + + // Get the project point. + prj[0] = p[0] - dist * fnormal[0]; + prj[1] = p[1] - dist * fnormal[1]; + prj[2] = p[2] - dist * fnormal[2]; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// facedihedral() Return the dihedral angle (in radian) between two // +// adjoining faces. // +// // +// 'pa', 'pb' are the shared edge of these two faces, 'pc1', and 'pc2' are // +// apexes of these two faces. Return the angle (between 0 to 2*pi) between // +// the normal of face (pa, pb, pc1) and normal of face (pa, pb, pc2). // +// // +/////////////////////////////////////////////////////////////////////////////// + +REAL tetgenmesh::facedihedral(REAL* pa, REAL* pb, REAL* pc1, REAL* pc2) +{ + REAL n1[3], n2[3]; + REAL n1len, n2len; + REAL costheta, ori; + REAL theta; + + facenormal(pa, pb, pc1, n1, 1, NULL); + facenormal(pa, pb, pc2, n2, 1, NULL); + n1len = sqrt(dot(n1, n1)); + n2len = sqrt(dot(n2, n2)); + costheta = dot(n1, n2) / (n1len * n2len); + // Be careful rounding error! + if (costheta > 1.0) { + costheta = 1.0; + } else if (costheta < -1.0) { + costheta = -1.0; + } + theta = acos(costheta); + ori = orient3d(pa, pb, pc1, pc2); + if (ori > 0.0) { + theta = 2 * PI - theta; + } + + return theta; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// tetalldihedral() Get all (six) dihedral angles of a tet. // +// // +// If 'cosdd' is not NULL, it returns the cosines of the 6 dihedral angles, // +// the edge indices are given in the global array 'edge2ver'. If 'cosmaxd' // +// (or 'cosmind') is not NULL, it returns the cosine of the maximal (or // +// minimal) dihedral angle. // +// // +/////////////////////////////////////////////////////////////////////////////// + +bool tetgenmesh::tetalldihedral(point pa, point pb, point pc, point pd, + REAL* cosdd, REAL* cosmaxd, REAL* cosmind) +{ + REAL N[4][3], vol, cosd, len; + int f1 = 0, f2 = 0, i, j; + + vol = 0; // Check if the tet is valid or not. + + // Get four normals of faces of the tet. + tetallnormal(pa, pb, pc, pd, N, &vol); + + if (vol > 0) { + // Normalize the normals. + for (i = 0; i < 4; i++) { + len = sqrt(dot(N[i], N[i])); + if (len != 0.0) { + for (j = 0; j < 3; j++) N[i][j] /= len; + } else { + // There are degeneracies, such as duplicated vertices. + vol = 0; //assert(0); + } + } + } + + if (vol <= 0) { // if (vol == 0.0) { + // A degenerated tet or an inverted tet. + facenormal(pc, pb, pd, N[0], 1, NULL); + facenormal(pa, pc, pd, N[1], 1, NULL); + facenormal(pb, pa, pd, N[2], 1, NULL); + facenormal(pa, pb, pc, N[3], 1, NULL); + // Normalize the normals. + for (i = 0; i < 4; i++) { + len = sqrt(dot(N[i], N[i])); + if (len != 0.0) { + for (j = 0; j < 3; j++) N[i][j] /= len; + } else { + // There are degeneracies, such as duplicated vertices. + break; // Not a valid normal. + } + } + if (i < 4) { + // Do not calculate dihedral angles. + // Set all angles be 0 degree. There will be no quality optimization for + // this tet! Use volume optimization to correct it. + if (cosdd != NULL) { + for (i = 0; i < 6; i++) { + cosdd[i] = -1.0; // 180 degree. + } + } + // This tet has zero volume. + if (cosmaxd != NULL) { + *cosmaxd = -1.0; // 180 degree. + } + if (cosmind != NULL) { + *cosmind = -1.0; // 180 degree. + } + return false; + } + } + + // Calculate the cosine of the dihedral angles of the edges. + for (i = 0; i < 6; i++) { + switch (i) { + case 0: f1 = 0; f2 = 1; break; // [c,d]. + case 1: f1 = 1; f2 = 2; break; // [a,d]. + case 2: f1 = 2; f2 = 3; break; // [a,b]. + case 3: f1 = 0; f2 = 3; break; // [b,c]. + case 4: f1 = 2; f2 = 0; break; // [b,d]. + case 5: f1 = 1; f2 = 3; break; // [a,c]. + } + cosd = -dot(N[f1], N[f2]); + if (cosd < -1.0) cosd = -1.0; // Rounding. + if (cosd > 1.0) cosd = 1.0; // Rounding. + if (cosdd) cosdd[i] = cosd; + if (cosmaxd || cosmind) { + if (i == 0) { + if (cosmaxd) *cosmaxd = cosd; + if (cosmind) *cosmind = cosd; + } else { + if (cosmaxd) *cosmaxd = cosd < *cosmaxd ? cosd : *cosmaxd; + if (cosmind) *cosmind = cosd > *cosmind ? cosd : *cosmind; + } + } + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// tetallnormal() Get the in-normals of the four faces of a given tet. // +// // +// Let tet be abcd. N[4][3] returns the four normals, which are: N[0] cbd, // +// N[1] acd, N[2] bad, N[3] abc (exactly corresponding to the face indices // +// of the mesh data structure). These normals are unnormalized. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::tetallnormal(point pa, point pb, point pc, point pd, + REAL N[4][3], REAL* volume) +{ + REAL A[4][4], rhs[4], D; + int indx[4]; + int i, j; + + // get the entries of A[3][3]. + for (i = 0; i < 3; i++) A[0][i] = pa[i] - pd[i]; // d->a vec + for (i = 0; i < 3; i++) A[1][i] = pb[i] - pd[i]; // d->b vec + for (i = 0; i < 3; i++) A[2][i] = pc[i] - pd[i]; // d->c vec + + // Compute the inverse of matrix A, to get 3 normals of the 4 faces. + if (lu_decmp(A, 3, indx, &D, 0)) { // Decompose the matrix just once. + if (volume != NULL) { + // Get the volume of the tet. + *volume = fabs((A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2])) / 6.0; + } + for (j = 0; j < 3; j++) { + for (i = 0; i < 3; i++) rhs[i] = 0.0; + rhs[j] = 1.0; // Positive means the inside direction + lu_solve(A, 3, indx, rhs, 0); + for (i = 0; i < 3; i++) N[j][i] = rhs[i]; + } + // Get the fourth normal by summing up the first three. + for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i]; + } else { + // The tet is degenerated. + if (volume != NULL) { + *volume = 0; + } + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// tetaspectratio() Calculate the aspect ratio of the tetrahedron. // +// // +// The aspect ratio of a tet is R/h, where R is the circumradius and h is // +// the shortest height of the tet. // +// // +/////////////////////////////////////////////////////////////////////////////// + +REAL tetgenmesh::tetaspectratio(point pa, point pb, point pc, point pd) +{ + REAL vda[3], vdb[3], vdc[3]; + REAL N[4][3], A[4][4], rhs[4], D; + REAL H[4], volume, radius2, minheightinv; + int indx[4]; + int i, j; + + // Set the matrix A = [vda, vdb, vdc]^T. + for (i = 0; i < 3; i++) A[0][i] = vda[i] = pa[i] - pd[i]; + for (i = 0; i < 3; i++) A[1][i] = vdb[i] = pb[i] - pd[i]; + for (i = 0; i < 3; i++) A[2][i] = vdc[i] = pc[i] - pd[i]; + // Lu-decompose the matrix A. + lu_decmp(A, 3, indx, &D, 0); + // Get the volume of abcd. + volume = (A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0; + // Check if it is zero. + if (volume == 0.0) return 1.0e+200; // A degenerate tet. + // if (volume < 0.0) volume = -volume; + // Check the radiu-edge ratio of the tet. + rhs[0] = 0.5 * dot(vda, vda); + rhs[1] = 0.5 * dot(vdb, vdb); + rhs[2] = 0.5 * dot(vdc, vdc); + lu_solve(A, 3, indx, rhs, 0); + // Get the circumcenter. + // for (i = 0; i < 3; i++) circumcent[i] = pd[i] + rhs[i]; + // Get the square of the circumradius. + radius2 = dot(rhs, rhs); + + // Compute the 4 face normals (N[0], ..., N[3]). + for (j = 0; j < 3; j++) { + for (i = 0; i < 3; i++) rhs[i] = 0.0; + rhs[j] = 1.0; // Positive means the inside direction + lu_solve(A, 3, indx, rhs, 0); + for (i = 0; i < 3; i++) N[j][i] = rhs[i]; + } + // Get the fourth normal by summing up the first three. + for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i]; + // Normalized the normals. + for (i = 0; i < 4; i++) { + // H[i] is the inverse of the height of its corresponding face. + H[i] = sqrt(dot(N[i], N[i])); + // if (H[i] > 0.0) { + // for (j = 0; j < 3; j++) N[i][j] /= H[i]; + // } + } + // Get the radius of the inscribed sphere. + // insradius = 1.0 / (H[0] + H[1] + H[2] + H[3]); + // Get the biggest H[i] (corresponding to the smallest height). + minheightinv = H[0]; + for (i = 1; i < 3; i++) { + if (H[i] > minheightinv) minheightinv = H[i]; + } + + return sqrt(radius2) * minheightinv; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// circumsphere() Calculate the smallest circumsphere (center and radius) // +// of the given three or four points. // +// // +// The circumsphere of four points (a tetrahedron) is unique if they are not // +// degenerate. If 'pd = NULL', the smallest circumsphere of three points is // +// the diametral sphere of the triangle if they are not degenerate. // +// // +// Return TRUE if the input points are not degenerate and the circumcenter // +// and circumradius are returned in 'cent' and 'radius' respectively if they // +// are not NULLs. Otherwise, return FALSE, the four points are co-planar. // +// // +/////////////////////////////////////////////////////////////////////////////// + +bool tetgenmesh::circumsphere(REAL* pa, REAL* pb, REAL* pc, REAL* pd, + REAL* cent, REAL* radius) +{ + REAL A[4][4], rhs[4], D; + int indx[4]; + + // Compute the coefficient matrix A (3x3). + A[0][0] = pb[0] - pa[0]; + A[0][1] = pb[1] - pa[1]; + A[0][2] = pb[2] - pa[2]; + A[1][0] = pc[0] - pa[0]; + A[1][1] = pc[1] - pa[1]; + A[1][2] = pc[2] - pa[2]; + if (pd != NULL) { + A[2][0] = pd[0] - pa[0]; + A[2][1] = pd[1] - pa[1]; + A[2][2] = pd[2] - pa[2]; + } else { + cross(A[0], A[1], A[2]); + } + + // Compute the right hand side vector b (3x1). + rhs[0] = 0.5 * dot(A[0], A[0]); + rhs[1] = 0.5 * dot(A[1], A[1]); + if (pd != NULL) { + rhs[2] = 0.5 * dot(A[2], A[2]); + } else { + rhs[2] = 0.0; + } + + // Solve the 3 by 3 equations use LU decomposition with partial pivoting + // and backward and forward substitute.. + if (!lu_decmp(A, 3, indx, &D, 0)) { + if (radius != (REAL *) NULL) *radius = 0.0; + return false; + } + lu_solve(A, 3, indx, rhs, 0); + if (cent != (REAL *) NULL) { + cent[0] = pa[0] + rhs[0]; + cent[1] = pa[1] + rhs[1]; + cent[2] = pa[2] + rhs[2]; + } + if (radius != (REAL *) NULL) { + *radius = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]); + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// orthosphere() Calulcate the orthosphere of four weighted points. // +// // +// A weighted point (p, P^2) can be interpreted as a sphere centered at the // +// point 'p' with a radius 'P'. The 'height' of 'p' is pheight = p[0]^2 + // +// p[1]^2 + p[2]^2 - P^2. // +// // +/////////////////////////////////////////////////////////////////////////////// + +bool tetgenmesh::orthosphere(REAL* pa, REAL* pb, REAL* pc, REAL* pd, + REAL aheight, REAL bheight, REAL cheight, + REAL dheight, REAL* orthocent, REAL* radius) +{ + REAL A[4][4], rhs[4], D; + int indx[4]; + + // Set the coefficient matrix A (4 x 4). + A[0][0] = 1.0; A[0][1] = pa[0]; A[0][2] = pa[1]; A[0][3] = pa[2]; + A[1][0] = 1.0; A[1][1] = pb[0]; A[1][2] = pb[1]; A[1][3] = pb[2]; + A[2][0] = 1.0; A[2][1] = pc[0]; A[2][2] = pc[1]; A[2][3] = pc[2]; + A[3][0] = 1.0; A[3][1] = pd[0]; A[3][2] = pd[1]; A[3][3] = pd[2]; + + // Set the right hand side vector (4 x 1). + rhs[0] = 0.5 * aheight; + rhs[1] = 0.5 * bheight; + rhs[2] = 0.5 * cheight; + rhs[3] = 0.5 * dheight; + + // Solve the 4 by 4 equations use LU decomposition with partial pivoting + // and backward and forward substitute.. + if (!lu_decmp(A, 4, indx, &D, 0)) { + if (radius != (REAL *) NULL) *radius = 0.0; + return false; + } + lu_solve(A, 4, indx, rhs, 0); + + if (orthocent != (REAL *) NULL) { + orthocent[0] = rhs[1]; + orthocent[1] = rhs[2]; + orthocent[2] = rhs[3]; + } + if (radius != (REAL *) NULL) { + // rhs[0] = - rheight / 2; + // rheight = - 2 * rhs[0]; + // = r[0]^2 + r[1]^2 + r[2]^2 - radius^2 + // radius^2 = r[0]^2 + r[1]^2 + r[2]^2 -rheight + // = r[0]^2 + r[1]^2 + r[2]^2 + 2 * rhs[0] + *radius = sqrt(rhs[1] * rhs[1] + rhs[2] * rhs[2] + rhs[3] * rhs[3] + + 2.0 * rhs[0]); + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// planelineint() Calculate the intersection of a line and a plane. // +// // +// The equation of a plane (points P are on the plane with normal N and P3 // +// on the plane) can be written as: N dot (P - P3) = 0. The equation of the // +// line (points P on the line passing through P1 and P2) can be written as: // +// P = P1 + u (P2 - P1). The intersection of these two occurs when: // +// N dot (P1 + u (P2 - P1)) = N dot P3. // +// Solving for u gives: // +// N dot (P3 - P1) // +// u = ------------------. // +// N dot (P2 - P1) // +// If the denominator is 0 then N (the normal to the plane) is perpendicular // +// to the line. Thus the line is either parallel to the plane and there are // +// no solutions or the line is on the plane in which case there are an infi- // +// nite number of solutions. // +// // +// The plane is given by three points pa, pb, and pc, e1 and e2 defines the // +// line. If u is non-zero, The intersection point (if exists) returns in ip. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::planelineint(REAL* pa, REAL* pb, REAL* pc, REAL* e1, REAL* e2, + REAL* ip, REAL* u) +{ + REAL n[3], det, det1; + + // Calculate N. + facenormal(pa, pb, pc, n, 1, NULL); + // Calculate N dot (e2 - e1). + det = n[0] * (e2[0] - e1[0]) + n[1] * (e2[1] - e1[1]) + + n[2] * (e2[2] - e1[2]); + if (det != 0.0) { + // Calculate N dot (pa - e1) + det1 = n[0] * (pa[0] - e1[0]) + n[1] * (pa[1] - e1[1]) + + n[2] * (pa[2] - e1[2]); + *u = det1 / det; + ip[0] = e1[0] + *u * (e2[0] - e1[0]); + ip[1] = e1[1] + *u * (e2[1] - e1[1]); + ip[2] = e1[2] + *u * (e2[2] - e1[2]); + } else { + *u = 0.0; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// linelineint() Calculate the intersection(s) of two line segments. // +// // +// Calculate the line segment [P, Q] that is the shortest route between two // +// lines from A to B and C to D. Calculate also the values of tp and tq // +// where: P = A + tp (B - A), and Q = C + tq (D - C). // +// // +// Return 1 if the line segment exists. Otherwise, return 0. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::linelineint(REAL* A, REAL* B, REAL* C, REAL* D, REAL* P, + REAL* Q, REAL* tp, REAL* tq) +{ + REAL vab[3], vcd[3], vca[3]; + REAL vab_vab, vcd_vcd, vab_vcd; + REAL vca_vab, vca_vcd; + REAL det, eps; + int i; + + for (i = 0; i < 3; i++) { + vab[i] = B[i] - A[i]; + vcd[i] = D[i] - C[i]; + vca[i] = A[i] - C[i]; + } + + vab_vab = dot(vab, vab); + vcd_vcd = dot(vcd, vcd); + vab_vcd = dot(vab, vcd); + + det = vab_vab * vcd_vcd - vab_vcd * vab_vcd; + // Round the result. + eps = det / (fabs(vab_vab * vcd_vcd) + fabs(vab_vcd * vab_vcd)); + if (eps < b->epsilon) { + return 0; + } + + vca_vab = dot(vca, vab); + vca_vcd = dot(vca, vcd); + + *tp = (vcd_vcd * (- vca_vab) + vab_vcd * vca_vcd) / det; + *tq = (vab_vcd * (- vca_vab) + vab_vab * vca_vcd) / det; + + for (i = 0; i < 3; i++) P[i] = A[i] + (*tp) * vab[i]; + for (i = 0; i < 3; i++) Q[i] = C[i] + (*tq) * vcd[i]; + + return 1; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// tetprismvol() Calculate the volume of a tetrahedral prism in 4D. // +// // +// A tetrahedral prism is a convex uniform polychoron (four dimensional poly-// +// tope). It has 6 polyhedral cells: 2 tetrahedra connected by 4 triangular // +// prisms. It has 14 faces: 8 triangular and 6 square. It has 16 edges and 8 // +// vertices. (Wikipedia). // +// // +// Let 'p0', ..., 'p3' be four affinely independent points in R^3. They form // +// the lower tetrahedral facet of the prism. The top tetrahedral facet is // +// formed by four vertices, 'p4', ..., 'p7' in R^4, which is obtained by // +// lifting each vertex of the lower facet into R^4 by a weight (height). A // +// canonical choice of the weights is the square of Euclidean norm of of the // +// points (vectors). // +// // +// // +// The return value is (4!) 24 times of the volume of the tetrahedral prism. // +// // +/////////////////////////////////////////////////////////////////////////////// + +REAL tetgenmesh::tetprismvol(REAL* p0, REAL* p1, REAL* p2, REAL* p3) +{ + REAL *p4, *p5, *p6, *p7; + REAL w4, w5, w6, w7; + REAL vol[4]; + + p4 = p0; + p5 = p1; + p6 = p2; + p7 = p3; + + // TO DO: these weights can be pre-calculated! + w4 = dot(p0, p0); + w5 = dot(p1, p1); + w6 = dot(p2, p2); + w7 = dot(p3, p3); + + // Calculate the volume of the tet-prism. + vol[0] = orient4d(p5, p6, p4, p3, p7, w5, w6, w4, 0, w7); + vol[1] = orient4d(p3, p6, p2, p0, p1, 0, w6, 0, 0, 0); + vol[2] = orient4d(p4, p6, p3, p0, p1, w4, w6, 0, 0, 0); + vol[3] = orient4d(p6, p5, p4, p3, p1, w6, w5, w4, 0, 0); + + return fabs(vol[0]) + fabs(vol[1]) + fabs(vol[2]) + fabs(vol[3]); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// calculateabovepoint() Calculate a point above a facet in 'dummypoint'. // +// // +/////////////////////////////////////////////////////////////////////////////// + +bool tetgenmesh::calculateabovepoint(arraypool *facpoints, point *ppa, + point *ppb, point *ppc) +{ + point *ppt, pa, pb, pc; + REAL v1[3], v2[3], n[3]; + REAL lab, len, A, area; + REAL x, y, z; + int i; + + ppt = (point *) fastlookup(facpoints, 0); + pa = *ppt; // a is the first point. + pb = pc = NULL; // Avoid compiler warnings. + + // Get a point b s.t. the length of [a, b] is maximal. + lab = 0; + for (i = 1; i < facpoints->objects; i++) { + ppt = (point *) fastlookup(facpoints, i); + x = (*ppt)[0] - pa[0]; + y = (*ppt)[1] - pa[1]; + z = (*ppt)[2] - pa[2]; + len = x * x + y * y + z * z; + if (len > lab) { + lab = len; + pb = *ppt; + } + } + lab = sqrt(lab); + if (lab == 0) { + if (!b->quiet) { + printf("Warning: All points of a facet are coincident with %d.\n", + pointmark(pa)); + } + return false; + } + + // Get a point c s.t. the area of [a, b, c] is maximal. + v1[0] = pb[0] - pa[0]; + v1[1] = pb[1] - pa[1]; + v1[2] = pb[2] - pa[2]; + A = 0; + for (i = 1; i < facpoints->objects; i++) { + ppt = (point *) fastlookup(facpoints, i); + v2[0] = (*ppt)[0] - pa[0]; + v2[1] = (*ppt)[1] - pa[1]; + v2[2] = (*ppt)[2] - pa[2]; + cross(v1, v2, n); + area = dot(n, n); + if (area > A) { + A = area; + pc = *ppt; + } + } + if (A == 0) { + // All points are collinear. No above point. + if (!b->quiet) { + printf("Warning: All points of a facet are collinaer with [%d, %d].\n", + pointmark(pa), pointmark(pb)); + } + return false; + } + + // Calculate an above point of this facet. + facenormal(pa, pb, pc, n, 1, NULL); + len = sqrt(dot(n, n)); + n[0] /= len; + n[1] /= len; + n[2] /= len; + lab /= 2.0; // Half the maximal length. + dummypoint[0] = pa[0] + lab * n[0]; + dummypoint[1] = pa[1] + lab * n[1]; + dummypoint[2] = pa[2] + lab * n[2]; + + if (ppa != NULL) { + // Return the three points. + *ppa = pa; + *ppb = pb; + *ppc = pc; + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// Calculate an above point. It lies above the plane containing the subface // +// [a,b,c], and save it in dummypoint. Moreover, the vector pa->dummypoint // +// is the normal of the plane. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::calculateabovepoint4(point pa, point pb, point pc, point pd) +{ + REAL n1[3], n2[3], *norm; + REAL len, len1, len2; + + // Select a base. + facenormal(pa, pb, pc, n1, 1, NULL); + len1 = sqrt(dot(n1, n1)); + facenormal(pa, pb, pd, n2, 1, NULL); + len2 = sqrt(dot(n2, n2)); + if (len1 > len2) { + norm = n1; + len = len1; + } else { + norm = n2; + len = len2; + } + assert(len > 0); + norm[0] /= len; + norm[1] /= len; + norm[2] /= len; + len = distance(pa, pb); + dummypoint[0] = pa[0] + len * norm[0]; + dummypoint[1] = pa[1] + len * norm[1]; + dummypoint[2] = pa[2] + len * norm[2]; +} + +//// //// +//// //// +//// geom_cxx ///////////////////////////////////////////////////////////////// + +//// flip_cxx ///////////////////////////////////////////////////////////////// +//// //// +//// //// + +/////////////////////////////////////////////////////////////////////////////// +// // +// flip23() Perform a 2-to-3 flip (face-to-edge flip). // +// // +// 'fliptets' is an array of three tets (handles), where the [0] and [1] are // +// [a,b,c,d] and [b,a,c,e]. The three new tets: [e,d,a,b], [e,d,b,c], and // +// [e,d,c,a] are returned in [0], [1], and [2] of 'fliptets'. As a result, // +// The face [a,b,c] is removed, and the edge [d,e] is created. // +// // +// If 'hullflag' > 0, hull tets may be involved in this flip, i.e., one of // +// the five vertices may be 'dummypoint'. There are two canonical cases: // +// (1) d is 'dummypoint', then all three new tets are hull tets. If e is // +// 'dummypoint', we reconfigure e to d, i.e., turn it up-side down. // +// (2) c is 'dummypoint', then two new tets: [e,d,b,c] and [e,d,c,a], are // +// hull tets. If a or b is 'dummypoint', we reconfigure it to c, i.e., // +// rotate the three input tets counterclockwisely (right-hand rule) // +// until a or b is in c's position. // +// // +// If 'fc->enqflag' is set, convex hull faces will be queued for flipping. // +// In particular, if 'fc->enqflag' is 1, it is called by incrementalflip() // +// after the insertion of a new point. It is assumed that 'd' is the new // +// point. IN this case, only link faces of 'd' are queued. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::flip23(triface* fliptets, int hullflag, flipconstraints *fc) +{ + triface topcastets[3], botcastets[3]; + triface newface, casface; + point pa, pb, pc, pd, pe; + REAL attrib, volume; + int dummyflag = 0; // range = {-1, 0, 1, 2}. + int i; + + if (hullflag > 0) { + // Check if e is dummypoint. + if (oppo(fliptets[1]) == dummypoint) { + // Swap the two old tets. + newface = fliptets[0]; + fliptets[0] = fliptets[1]; + fliptets[1] = newface; + dummyflag = -1; // d is dummypoint. + } else { + // Check if either a or b is dummypoint. + if (org(fliptets[0]) == dummypoint) { + dummyflag = 1; // a is dummypoint. + enextself(fliptets[0]); + eprevself(fliptets[1]); + } else if (dest(fliptets[0]) == dummypoint) { + dummyflag = 2; // b is dummypoint. + eprevself(fliptets[0]); + enextself(fliptets[1]); + } else { + dummyflag = 0; // either c or d may be dummypoint. + } + } + } + + pa = org(fliptets[0]); + pb = dest(fliptets[0]); + pc = apex(fliptets[0]); + pd = oppo(fliptets[0]); + pe = oppo(fliptets[1]); + + flip23count++; + + // Get the outer boundary faces. + for (i = 0; i < 3; i++) { + fnext(fliptets[0], topcastets[i]); + enextself(fliptets[0]); + } + for (i = 0; i < 3; i++) { + fnext(fliptets[1], botcastets[i]); + eprevself(fliptets[1]); + } + + // Re-use fliptets[0] and fliptets[1]. + fliptets[0].ver = 11; + fliptets[1].ver = 11; + setelemmarker(fliptets[0].tet, 0); // Clear all flags. + setelemmarker(fliptets[1].tet, 0); + // NOTE: the element attributes and volume constraint remain unchanged. + if (checksubsegflag) { + // Dealloc the space to subsegments. + if (fliptets[0].tet[8] != NULL) { + tet2segpool->dealloc((shellface *) fliptets[0].tet[8]); + fliptets[0].tet[8] = NULL; + } + if (fliptets[1].tet[8] != NULL) { + tet2segpool->dealloc((shellface *) fliptets[1].tet[8]); + fliptets[1].tet[8] = NULL; + } + } + if (checksubfaceflag) { + // Dealloc the space to subfaces. + if (fliptets[0].tet[9] != NULL) { + tet2subpool->dealloc((shellface *) fliptets[0].tet[9]); + fliptets[0].tet[9] = NULL; + } + if (fliptets[1].tet[9] != NULL) { + tet2subpool->dealloc((shellface *) fliptets[1].tet[9]); + fliptets[1].tet[9] = NULL; + } + } + // Create a new tet. + maketetrahedron(&(fliptets[2])); + // The new tet have the same attributes from the old tet. + for (i = 0; i < numelemattrib; i++) { + attrib = elemattribute(fliptets[0].tet, i); + setelemattribute(fliptets[2].tet, i, attrib); + } + if (b->varvolume) { + volume = volumebound(fliptets[0].tet); + setvolumebound(fliptets[2].tet, volume); + } + + if (hullflag > 0) { + // Check if d is dummytet. + if (pd != dummypoint) { + setvertices(fliptets[0], pe, pd, pa, pb); // [e,d,a,b] * + setvertices(fliptets[1], pe, pd, pb, pc); // [e,d,b,c] * + // Check if c is dummypoint. + if (pc != dummypoint) { + setvertices(fliptets[2], pe, pd, pc, pa); // [e,d,c,a] * + } else { + setvertices(fliptets[2], pd, pe, pa, pc); // [d,e,a,c] + esymself(fliptets[2]); // [e,d,c,a] * + } + // The hullsize does not change. + } else { + // d is dummypoint. + setvertices(fliptets[0], pa, pb, pe, pd); // [a,b,e,d] + setvertices(fliptets[1], pb, pc, pe, pd); // [b,c,e,d] + setvertices(fliptets[2], pc, pa, pe, pd); // [c,a,e,d] + // Adjust the faces to [e,d,a,b], [e,d,b,c], [e,d,c,a] * + for (i = 0; i < 3; i++) { + eprevesymself(fliptets[i]); + enextself(fliptets[i]); + } + // We deleted one hull tet, and created three hull tets. + hullsize += 2; + } + } else { + setvertices(fliptets[0], pe, pd, pa, pb); // [e,d,a,b] * + setvertices(fliptets[1], pe, pd, pb, pc); // [e,d,b,c] * + setvertices(fliptets[2], pe, pd, pc, pa); // [e,d,c,a] * + } + + if (fc->remove_ndelaunay_edge) { // calc_tetprism_vol + REAL volneg[2], volpos[3], vol_diff; + if (pd != dummypoint) { + if (pc != dummypoint) { + volpos[0] = tetprismvol(pe, pd, pa, pb); + volpos[1] = tetprismvol(pe, pd, pb, pc); + volpos[2] = tetprismvol(pe, pd, pc, pa); + volneg[0] = tetprismvol(pa, pb, pc, pd); + volneg[1] = tetprismvol(pb, pa, pc, pe); + } else { // pc == dummypoint + volpos[0] = tetprismvol(pe, pd, pa, pb); + volpos[1] = 0.; + volpos[2] = 0.; + volneg[0] = 0.; + volneg[1] = 0.; + } + } else { // pd == dummypoint. + volpos[0] = 0.; + volpos[1] = 0.; + volpos[2] = 0.; + volneg[0] = 0.; + volneg[1] = tetprismvol(pb, pa, pc, pe); + } + vol_diff = volpos[0] + volpos[1] + volpos[2] - volneg[0] - volneg[1]; + fc->tetprism_vol_sum += vol_diff; // Update the total sum. + } + + // Bond three new tets together. + for (i = 0; i < 3; i++) { + esym(fliptets[i], newface); + bond(newface, fliptets[(i + 1) % 3]); + } + // Bond to top outer boundary faces (at [a,b,c,d]). + for (i = 0; i < 3; i++) { + eorgoppo(fliptets[i], newface); // At edges [b,a], [c,b], [a,c]. + bond(newface, topcastets[i]); + } + // Bond bottom outer boundary faces (at [b,a,c,e]). + for (i = 0; i < 3; i++) { + edestoppo(fliptets[i], newface); // At edges [a,b], [b,c], [c,a]. + bond(newface, botcastets[i]); + } + + if (checksubsegflag) { + // Bond subsegments if there are. + // Each new tet has 5 edges to be checked (except the edge [e,d]). + face checkseg; + // The middle three: [a,b], [b,c], [c,a]. + for (i = 0; i < 3; i++) { + if (issubseg(topcastets[i])) { + tsspivot1(topcastets[i], checkseg); + eorgoppo(fliptets[i], newface); + tssbond1(newface, checkseg); + sstbond1(checkseg, newface); + if (fc->chkencflag & 1) { + enqueuesubface(badsubsegs, &checkseg); + } + } + } + // The top three: [d,a], [d,b], [d,c]. Two tets per edge. + for (i = 0; i < 3; i++) { + eprev(topcastets[i], casface); + if (issubseg(casface)) { + tsspivot1(casface, checkseg); + enext(fliptets[i], newface); + tssbond1(newface, checkseg); + sstbond1(checkseg, newface); + esym(fliptets[(i + 2) % 3], newface); + eprevself(newface); + tssbond1(newface, checkseg); + sstbond1(checkseg, newface); + if (fc->chkencflag & 1) { + enqueuesubface(badsubsegs, &checkseg); + } + } + } + // The bot three: [a,e], [b,e], [c,e]. Two tets per edge. + for (i = 0; i < 3; i++) { + enext(botcastets[i], casface); + if (issubseg(casface)) { + tsspivot1(casface, checkseg); + eprev(fliptets[i], newface); + tssbond1(newface, checkseg); + sstbond1(checkseg, newface); + esym(fliptets[(i + 2) % 3], newface); + enextself(newface); + tssbond1(newface, checkseg); + sstbond1(checkseg, newface); + if (fc->chkencflag & 1) { + enqueuesubface(badsubsegs, &checkseg); + } + } + } + } // if (checksubsegflag) + + if (checksubfaceflag) { + // Bond 6 subfaces if there are. + face checksh; + for (i = 0; i < 3; i++) { + if (issubface(topcastets[i])) { + tspivot(topcastets[i], checksh); + eorgoppo(fliptets[i], newface); + sesymself(checksh); + tsbond(newface, checksh); + if (fc->chkencflag & 2) { + enqueuesubface(badsubfacs, &checksh); + } + } + } + for (i = 0; i < 3; i++) { + if (issubface(botcastets[i])) { + tspivot(botcastets[i], checksh); + edestoppo(fliptets[i], newface); + sesymself(checksh); + tsbond(newface, checksh); + if (fc->chkencflag & 2) { + enqueuesubface(badsubfacs, &checksh); + } + } + } + } // if (checksubfaceflag) + + if (fc->chkencflag & 4) { + // Put three new tets into check list. + for (i = 0; i < 3; i++) { + enqueuetetrahedron(&(fliptets[i])); + } + } + + // Update the point-to-tet map. + setpoint2tet(pa, (tetrahedron) fliptets[0].tet); + setpoint2tet(pb, (tetrahedron) fliptets[0].tet); + setpoint2tet(pc, (tetrahedron) fliptets[1].tet); + setpoint2tet(pd, (tetrahedron) fliptets[0].tet); + setpoint2tet(pe, (tetrahedron) fliptets[0].tet); + + if (hullflag > 0) { + if (dummyflag != 0) { + // Restore the original position of the points (for flipnm()). + if (dummyflag == -1) { + // Reverse the edge. + for (i = 0; i < 3; i++) { + esymself(fliptets[i]); + } + // Swap the last two new tets. + newface = fliptets[1]; + fliptets[1] = fliptets[2]; + fliptets[2] = newface; + } else { + // either a or b were swapped. + if (dummyflag == 1) { + // a is dummypoint. + newface = fliptets[0]; + fliptets[0] = fliptets[2]; + fliptets[2] = fliptets[1]; + fliptets[1] = newface; + } else { // dummyflag == 2 + // b is dummypoint. + newface = fliptets[0]; + fliptets[0] = fliptets[1]; + fliptets[1] = fliptets[2]; + fliptets[2] = newface; + } + } + } + } + + if (fc->enqflag > 0) { + // Queue faces which may be locally non-Delaunay. + for (i = 0; i < 3; i++) { + eprevesym(fliptets[i], newface); + flippush(flipstack, &newface); + } + if (fc->enqflag > 1) { + for (i = 0; i < 3; i++) { + enextesym(fliptets[i], newface); + flippush(flipstack, &newface); + } + } + } + + recenttet = fliptets[0]; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// flip32() Perform a 3-to-2 flip (edge-to-face flip). // +// // +// 'fliptets' is an array of three tets (handles), which are [e,d,a,b], // +// [e,d,b,c], and [e,d,c,a]. The two new tets: [a,b,c,d] and [b,a,c,e] are // +// returned in [0] and [1] of 'fliptets'. As a result, the edge [e,d] is // +// replaced by the face [a,b,c]. // +// // +// If 'hullflag' > 0, hull tets may be involved in this flip, i.e., one of // +// the five vertices may be 'dummypoint'. There are two canonical cases: // +// (1) d is 'dummypoint', then [a,b,c,d] is hull tet. If e is 'dummypoint',// +// we reconfigure e to d, i.e., turnover it. // +// (2) c is 'dummypoint' then both [a,b,c,d] and [b,a,c,e] are hull tets. // +// If a or b is 'dummypoint', we reconfigure it to c, i.e., rotate the // +// three old tets counterclockwisely (right-hand rule) until a or b // +// is in c's position. // +// // +// If 'fc->enqflag' is set, convex hull faces will be queued for flipping. // +// In particular, if 'fc->enqflag' is 1, it is called by incrementalflip() // +// after the insertion of a new point. It is assumed that 'a' is the new // +// point. In this case, only link faces of 'a' are queued. // +// // +// If 'checksubfaceflag' is on (global variable), and assume [e,d] is not a // +// segment. There may be two (interior) subfaces sharing at [e,d], which are // +// [e,d,p] and [e,d,q], where the pair (p,q) may be either (a,b), or (b,c), // +// or (c,a) In such case, a 2-to-2 flip is performed on these two subfaces // +// and two new subfaces [p,q,e] and [p,q,d] are created. They are inserted // +// back into the tetrahedralization. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::flip32(triface* fliptets, int hullflag, flipconstraints *fc) +{ + triface topcastets[3], botcastets[3]; + triface newface, casface; + face flipshs[3]; + face checkseg; + point pa, pb, pc, pd, pe; + REAL attrib, volume; + int dummyflag = 0; // Rangle = {-1, 0, 1, 2} + int spivot = -1, scount = 0; // for flip22() + int t1ver; + int i, j; + + if (hullflag > 0) { + // Check if e is 'dummypoint'. + if (org(fliptets[0]) == dummypoint) { + // Reverse the edge. + for (i = 0; i < 3; i++) { + esymself(fliptets[i]); + } + // Swap the last two tets. + newface = fliptets[1]; + fliptets[1] = fliptets[2]; + fliptets[2] = newface; + dummyflag = -1; // e is dummypoint. + } else { + // Check if a or b is the 'dummypoint'. + if (apex(fliptets[0]) == dummypoint) { + dummyflag = 1; // a is dummypoint. + newface = fliptets[0]; + fliptets[0] = fliptets[1]; + fliptets[1] = fliptets[2]; + fliptets[2] = newface; + } else if (apex(fliptets[1]) == dummypoint) { + dummyflag = 2; // b is dummypoint. + newface = fliptets[0]; + fliptets[0] = fliptets[2]; + fliptets[2] = fliptets[1]; + fliptets[1] = newface; + } else { + dummyflag = 0; // either c or d may be dummypoint. + } + } + } + + pa = apex(fliptets[0]); + pb = apex(fliptets[1]); + pc = apex(fliptets[2]); + pd = dest(fliptets[0]); + pe = org(fliptets[0]); + + flip32count++; + + // Get the outer boundary faces. + for (i = 0; i < 3; i++) { + eorgoppo(fliptets[i], casface); + fsym(casface, topcastets[i]); + } + for (i = 0; i < 3; i++) { + edestoppo(fliptets[i], casface); + fsym(casface, botcastets[i]); + } + + if (checksubfaceflag) { + // Check if there are interior subfaces at the edge [e,d]. + for (i = 0; i < 3; i++) { + tspivot(fliptets[i], flipshs[i]); + if (flipshs[i].sh != NULL) { + // Found an interior subface. + stdissolve(flipshs[i]); // Disconnect the sub-tet bond. + scount++; + } else { + spivot = i; + } + } + } + + // Re-use fliptets[0] and fliptets[1]. + fliptets[0].ver = 11; + fliptets[1].ver = 11; + setelemmarker(fliptets[0].tet, 0); // Clear all flags. + setelemmarker(fliptets[1].tet, 0); + if (checksubsegflag) { + // Dealloc the space to subsegments. + if (fliptets[0].tet[8] != NULL) { + tet2segpool->dealloc((shellface *) fliptets[0].tet[8]); + fliptets[0].tet[8] = NULL; + } + if (fliptets[1].tet[8] != NULL) { + tet2segpool->dealloc((shellface *) fliptets[1].tet[8]); + fliptets[1].tet[8] = NULL; + } + } + if (checksubfaceflag) { + // Dealloc the space to subfaces. + if (fliptets[0].tet[9] != NULL) { + tet2subpool->dealloc((shellface *) fliptets[0].tet[9]); + fliptets[0].tet[9] = NULL; + } + if (fliptets[1].tet[9] != NULL) { + tet2subpool->dealloc((shellface *) fliptets[1].tet[9]); + fliptets[1].tet[9] = NULL; + } + } + if (checksubfaceflag) { + if (scount > 0) { + // The element attributes and volume constraint must be set correctly. + // There are two subfaces involved in this flip. The three tets are + // separated into two different regions, one may be exterior. The + // first region has two tets, and the second region has only one. + // The two created tets must be in the same region as the first region. + // The element attributes and volume constraint must be set correctly. + //assert(spivot != -1); + // The tet fliptets[spivot] is in the first region. + for (j = 0; j < 2; j++) { + for (i = 0; i < numelemattrib; i++) { + attrib = elemattribute(fliptets[spivot].tet, i); + setelemattribute(fliptets[j].tet, i, attrib); + } + if (b->varvolume) { + volume = volumebound(fliptets[spivot].tet); + setvolumebound(fliptets[j].tet, volume); + } + } + } + } + // Delete an old tet. + tetrahedrondealloc(fliptets[2].tet); + + if (hullflag > 0) { + // Check if c is dummypointc. + if (pc != dummypoint) { + // Check if d is dummypoint. + if (pd != dummypoint) { + // No hull tet is involved. + } else { + // We deleted three hull tets, and created one hull tet. + hullsize -= 2; + } + setvertices(fliptets[0], pa, pb, pc, pd); + setvertices(fliptets[1], pb, pa, pc, pe); + } else { + // c is dummypoint. The two new tets are hull tets. + setvertices(fliptets[0], pb, pa, pd, pc); + setvertices(fliptets[1], pa, pb, pe, pc); + // Adjust badc -> abcd. + esymself(fliptets[0]); + // Adjust abec -> bace. + esymself(fliptets[1]); + // The hullsize does not change. + } + } else { + setvertices(fliptets[0], pa, pb, pc, pd); + setvertices(fliptets[1], pb, pa, pc, pe); + } + + if (fc->remove_ndelaunay_edge) { // calc_tetprism_vol + REAL volneg[3], volpos[2], vol_diff; + if (pc != dummypoint) { + if (pd != dummypoint) { + volneg[0] = tetprismvol(pe, pd, pa, pb); + volneg[1] = tetprismvol(pe, pd, pb, pc); + volneg[2] = tetprismvol(pe, pd, pc, pa); + volpos[0] = tetprismvol(pa, pb, pc, pd); + volpos[1] = tetprismvol(pb, pa, pc, pe); + } else { // pd == dummypoint + volneg[0] = 0.; + volneg[1] = 0.; + volneg[2] = 0.; + volpos[0] = 0.; + volpos[1] = tetprismvol(pb, pa, pc, pe); + } + } else { // pc == dummypoint. + volneg[0] = tetprismvol(pe, pd, pa, pb); + volneg[1] = 0.; + volneg[2] = 0.; + volpos[0] = 0.; + volpos[1] = 0.; + } + vol_diff = volpos[0] + volpos[1] - volneg[0] - volneg[1] - volneg[2]; + fc->tetprism_vol_sum += vol_diff; // Update the total sum. + } + + // Bond abcd <==> bace. + bond(fliptets[0], fliptets[1]); + // Bond new faces to top outer boundary faces (at abcd). + for (i = 0; i < 3; i++) { + esym(fliptets[0], newface); + bond(newface, topcastets[i]); + enextself(fliptets[0]); + } + // Bond new faces to bottom outer boundary faces (at bace). + for (i = 0; i < 3; i++) { + esym(fliptets[1], newface); + bond(newface, botcastets[i]); + eprevself(fliptets[1]); + } + + if (checksubsegflag) { + // Bond 9 segments to new (flipped) tets. + for (i = 0; i < 3; i++) { // edges a->b, b->c, c->a. + if (issubseg(topcastets[i])) { + tsspivot1(topcastets[i], checkseg); + tssbond1(fliptets[0], checkseg); + sstbond1(checkseg, fliptets[0]); + tssbond1(fliptets[1], checkseg); + sstbond1(checkseg, fliptets[1]); + if (fc->chkencflag & 1) { + enqueuesubface(badsubsegs, &checkseg); + } + } + enextself(fliptets[0]); + eprevself(fliptets[1]); + } + // The three top edges. + for (i = 0; i < 3; i++) { // edges b->d, c->d, a->d. + esym(fliptets[0], newface); + eprevself(newface); + enext(topcastets[i], casface); + if (issubseg(casface)) { + tsspivot1(casface, checkseg); + tssbond1(newface, checkseg); + sstbond1(checkseg, newface); + if (fc->chkencflag & 1) { + enqueuesubface(badsubsegs, &checkseg); + } + } + enextself(fliptets[0]); + } + // The three bot edges. + for (i = 0; i < 3; i++) { // edges b<-e, c<-e, a<-e. + esym(fliptets[1], newface); + enextself(newface); + eprev(botcastets[i], casface); + if (issubseg(casface)) { + tsspivot1(casface, checkseg); + tssbond1(newface, checkseg); + sstbond1(checkseg, newface); + if (fc->chkencflag & 1) { + enqueuesubface(badsubsegs, &checkseg); + } + } + eprevself(fliptets[1]); + } + } // if (checksubsegflag) + + if (checksubfaceflag) { + face checksh; + // Bond the top three casing subfaces. + for (i = 0; i < 3; i++) { // At edges [b,a], [c,b], [a,c] + if (issubface(topcastets[i])) { + tspivot(topcastets[i], checksh); + esym(fliptets[0], newface); + sesymself(checksh); + tsbond(newface, checksh); + if (fc->chkencflag & 2) { + enqueuesubface(badsubfacs, &checksh); + } + } + enextself(fliptets[0]); + } + // Bond the bottom three casing subfaces. + for (i = 0; i < 3; i++) { // At edges [a,b], [b,c], [c,a] + if (issubface(botcastets[i])) { + tspivot(botcastets[i], checksh); + esym(fliptets[1], newface); + sesymself(checksh); + tsbond(newface, checksh); + if (fc->chkencflag & 2) { + enqueuesubface(badsubfacs, &checksh); + } + } + eprevself(fliptets[1]); + } + + if (scount > 0) { + face flipfaces[2]; + // Perform a 2-to-2 flip in subfaces. + flipfaces[0] = flipshs[(spivot + 1) % 3]; + flipfaces[1] = flipshs[(spivot + 2) % 3]; + sesymself(flipfaces[1]); + flip22(flipfaces, 0, fc->chkencflag); + // Connect the flipped subfaces to flipped tets. + // First go to the corresponding flipping edge. + // Re-use top- and botcastets[0]. + topcastets[0] = fliptets[0]; + botcastets[0] = fliptets[1]; + for (i = 0; i < ((spivot + 1) % 3); i++) { + enextself(topcastets[0]); + eprevself(botcastets[0]); + } + // Connect the top subface to the top tets. + esymself(topcastets[0]); + sesymself(flipfaces[0]); + // Check if there already exists a subface. + tspivot(topcastets[0], checksh); + if (checksh.sh == NULL) { + tsbond(topcastets[0], flipfaces[0]); + fsymself(topcastets[0]); + sesymself(flipfaces[0]); + tsbond(topcastets[0], flipfaces[0]); + } else { + // An invalid 2-to-2 flip. Report a bug. + terminatetetgen(this, 2); + } + // Connect the bot subface to the bottom tets. + esymself(botcastets[0]); + sesymself(flipfaces[1]); + // Check if there already exists a subface. + tspivot(botcastets[0], checksh); + if (checksh.sh == NULL) { + tsbond(botcastets[0], flipfaces[1]); + fsymself(botcastets[0]); + sesymself(flipfaces[1]); + tsbond(botcastets[0], flipfaces[1]); + } else { + // An invalid 2-to-2 flip. Report a bug. + terminatetetgen(this, 2); + } + } // if (scount > 0) + } // if (checksubfaceflag) + + if (fc->chkencflag & 4) { + // Put two new tets into check list. + for (i = 0; i < 2; i++) { + enqueuetetrahedron(&(fliptets[i])); + } + } + + setpoint2tet(pa, (tetrahedron) fliptets[0].tet); + setpoint2tet(pb, (tetrahedron) fliptets[0].tet); + setpoint2tet(pc, (tetrahedron) fliptets[0].tet); + setpoint2tet(pd, (tetrahedron) fliptets[0].tet); + setpoint2tet(pe, (tetrahedron) fliptets[1].tet); + + if (hullflag > 0) { + if (dummyflag != 0) { + // Restore the original position of the points (for flipnm()). + if (dummyflag == -1) { + // e were dummypoint. Swap the two new tets. + newface = fliptets[0]; + fliptets[0] = fliptets[1]; + fliptets[1] = newface; + } else { + // a or b was dummypoint. + if (dummyflag == 1) { + eprevself(fliptets[0]); + enextself(fliptets[1]); + } else { // dummyflag == 2 + enextself(fliptets[0]); + eprevself(fliptets[1]); + } + } + } + } + + if (fc->enqflag > 0) { + // Queue faces which may be locally non-Delaunay. + // pa = org(fliptets[0]); // 'a' may be a new vertex. + enextesym(fliptets[0], newface); + flippush(flipstack, &newface); + eprevesym(fliptets[1], newface); + flippush(flipstack, &newface); + if (fc->enqflag > 1) { + //pb = dest(fliptets[0]); + eprevesym(fliptets[0], newface); + flippush(flipstack, &newface); + enextesym(fliptets[1], newface); + flippush(flipstack, &newface); + //pc = apex(fliptets[0]); + esym(fliptets[0], newface); + flippush(flipstack, &newface); + esym(fliptets[1], newface); + flippush(flipstack, &newface); + } + } + + recenttet = fliptets[0]; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// flip41() Perform a 4-to-1 flip (Remove a vertex). // +// // +// 'fliptets' is an array of four tetrahedra in the star of the removing // +// vertex 'p'. Let the four vertices in the star of p be a, b, c, and d. The // +// four tets in 'fliptets' are: [p,d,a,b], [p,d,b,c], [p,d,c,a], and [a,b,c, // +// p]. On return, 'fliptets[0]' is the new tet [a,b,c,d]. // +// // +// If 'hullflag' is set (> 0), one of the five vertices may be 'dummypoint'. // +// The 'hullsize' may be changed. Note that p may be dummypoint. In this // +// case, four hull tets are replaced by one real tet. // +// // +// If 'checksubface' flag is set (>0), it is possible that there are three // +// interior subfaces connecting at p. If so, a 3-to-1 flip is performed to // +// to remove p from the surface triangulation. // +// // +// If it is called by the routine incrementalflip(), we assume that d is the // +// newly inserted vertex. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::flip41(triface* fliptets, int hullflag, flipconstraints *fc) +{ + triface topcastets[3], botcastet; + triface newface, neightet; + face flipshs[4]; + point pa, pb, pc, pd, pp; + int dummyflag = 0; // in {0, 1, 2, 3, 4} + int spivot = -1, scount = 0; + int t1ver; + int i; + + pa = org(fliptets[3]); + pb = dest(fliptets[3]); + pc = apex(fliptets[3]); + pd = dest(fliptets[0]); + pp = org(fliptets[0]); // The removing vertex. + + flip41count++; + + // Get the outer boundary faces. + for (i = 0; i < 3; i++) { + enext(fliptets[i], topcastets[i]); + fnextself(topcastets[i]); // [d,a,b,#], [d,b,c,#], [d,c,a,#] + enextself(topcastets[i]); // [a,b,d,#], [b,c,d,#], [c,a,d,#] + } + fsym(fliptets[3], botcastet); // [b,a,c,#] + + if (checksubfaceflag) { + // Check if there are three subfaces at 'p'. + // Re-use 'newface'. + for (i = 0; i < 3; i++) { + fnext(fliptets[3], newface); // [a,b,p,d],[b,c,p,d],[c,a,p,d]. + tspivot(newface, flipshs[i]); + if (flipshs[i].sh != NULL) { + spivot = i; // Remember this subface. + scount++; + } + enextself(fliptets[3]); + } + if (scount > 0) { + // There are three subfaces connecting at p. + if (scount < 3) { + // The new subface is one of {[a,b,d], [b,c,d], [c,a,d]}. + assert(scount == 1); // spivot >= 0 + // Go to the tet containing the three subfaces. + fsym(topcastets[spivot], neightet); + // Get the three subfaces connecting at p. + for (i = 0; i < 3; i++) { + esym(neightet, newface); + tspivot(newface, flipshs[i]); + assert(flipshs[i].sh != NULL); + eprevself(neightet); + } + } else { + spivot = 3; // The new subface is [a,b,c]. + } + } + } // if (checksubfaceflag) + + + // Re-use fliptets[0] for [a,b,c,d]. + fliptets[0].ver = 11; + setelemmarker(fliptets[0].tet, 0); // Clean all flags. + // NOTE: the element attributes and volume constraint remain unchanged. + if (checksubsegflag) { + // Dealloc the space to subsegments. + if (fliptets[0].tet[8] != NULL) { + tet2segpool->dealloc((shellface *) fliptets[0].tet[8]); + fliptets[0].tet[8] = NULL; + } + } + if (checksubfaceflag) { + // Dealloc the space to subfaces. + if (fliptets[0].tet[9] != NULL) { + tet2subpool->dealloc((shellface *) fliptets[0].tet[9]); + fliptets[0].tet[9] = NULL; + } + } + // Delete the other three tets. + for (i = 1; i < 4; i++) { + tetrahedrondealloc(fliptets[i].tet); + } + + if (pp != dummypoint) { + // Mark the point pp as unused. + setpointtype(pp, UNUSEDVERTEX); + unuverts++; + } + + // Create the new tet [a,b,c,d]. + if (hullflag > 0) { + // One of the five vertices may be 'dummypoint'. + if (pa == dummypoint) { + // pa is dummypoint. + setvertices(fliptets[0], pc, pb, pd, pa); + esymself(fliptets[0]); // [b,c,a,d] + eprevself(fliptets[0]); // [a,b,c,d] + dummyflag = 1; + } else if (pb == dummypoint) { + setvertices(fliptets[0], pa, pc, pd, pb); + esymself(fliptets[0]); // [c,a,b,d] + enextself(fliptets[0]); // [a,b,c,d] + dummyflag = 2; + } else if (pc == dummypoint) { + setvertices(fliptets[0], pb, pa, pd, pc); + esymself(fliptets[0]); // [a,b,c,d] + dummyflag = 3; + } else if (pd == dummypoint) { + setvertices(fliptets[0], pa, pb, pc, pd); + dummyflag = 4; + } else { + setvertices(fliptets[0], pa, pb, pc, pd); + if (pp == dummypoint) { + dummyflag = -1; + } else { + dummyflag = 0; + } + } + if (dummyflag > 0) { + // We deleted 3 hull tets, and create 1 hull tet. + hullsize -= 2; + } else if (dummyflag < 0) { + // We deleted 4 hull tets. + hullsize -= 4; + // meshedges does not change. + } + } else { + setvertices(fliptets[0], pa, pb, pc, pd); + } + + if (fc->remove_ndelaunay_edge) { // calc_tetprism_vol + REAL volneg[4], volpos[1], vol_diff; + if (dummyflag > 0) { + if (pa == dummypoint) { + volneg[0] = 0.; + volneg[1] = tetprismvol(pp, pd, pb, pc); + volneg[2] = 0.; + volneg[3] = 0.; + } else if (pb == dummypoint) { + volneg[0] = 0.; + volneg[1] = 0.; + volneg[2] = tetprismvol(pp, pd, pc, pa); + volneg[3] = 0.; + } else if (pc == dummypoint) { + volneg[0] = tetprismvol(pp, pd, pa, pb); + volneg[1] = 0.; + volneg[2] = 0.; + volneg[3] = 0.; + } else { // pd == dummypoint + volneg[0] = 0.; + volneg[1] = 0.; + volneg[2] = 0.; + volneg[3] = tetprismvol(pa, pb, pc, pp); + } + volpos[0] = 0.; + } else if (dummyflag < 0) { + volneg[0] = 0.; + volneg[1] = 0.; + volneg[2] = 0.; + volneg[3] = 0.; + volpos[0] = tetprismvol(pa, pb, pc, pd); + } else { + volneg[0] = tetprismvol(pp, pd, pa, pb); + volneg[1] = tetprismvol(pp, pd, pb, pc); + volneg[2] = tetprismvol(pp, pd, pc, pa); + volneg[3] = tetprismvol(pa, pb, pc, pp); + volpos[0] = tetprismvol(pa, pb, pc, pd); + } + vol_diff = volpos[0] - volneg[0] - volneg[1] - volneg[2] - volneg[3]; + fc->tetprism_vol_sum += vol_diff; // Update the total sum. + } + + // Bond the new tet to adjacent tets. + for (i = 0; i < 3; i++) { + esym(fliptets[0], newface); // At faces [b,a,d], [c,b,d], [a,c,d]. + bond(newface, topcastets[i]); + enextself(fliptets[0]); + } + bond(fliptets[0], botcastet); + + if (checksubsegflag) { + face checkseg; + // Bond 6 segments (at edges of [a,b,c,d]) if there there are. + for (i = 0; i < 3; i++) { + eprev(topcastets[i], newface); // At edges [d,a],[d,b],[d,c]. + if (issubseg(newface)) { + tsspivot1(newface, checkseg); + esym(fliptets[0], newface); + enextself(newface); // At edges [a,d], [b,d], [c,d]. + tssbond1(newface, checkseg); + sstbond1(checkseg, newface); + if (fc->chkencflag & 1) { + enqueuesubface(badsubsegs, &checkseg); + } + } + enextself(fliptets[0]); + } + for (i = 0; i < 3; i++) { + if (issubseg(topcastets[i])) { + tsspivot1(topcastets[i], checkseg); // At edges [a,b],[b,c],[c,a]. + tssbond1(fliptets[0], checkseg); + sstbond1(checkseg, fliptets[0]); + if (fc->chkencflag & 1) { + enqueuesubface(badsubsegs, &checkseg); + } + } + enextself(fliptets[0]); + } + } + + if (checksubfaceflag) { + face checksh; + // Bond 4 subfaces (at faces of [a,b,c,d]) if there are. + for (i = 0; i < 3; i++) { + if (issubface(topcastets[i])) { + tspivot(topcastets[i], checksh); // At faces [a,b,d],[b,c,d],[c,a,d] + esym(fliptets[0], newface); // At faces [b,a,d],[c,b,d],[a,c,d] + sesymself(checksh); + tsbond(newface, checksh); + if (fc->chkencflag & 2) { + enqueuesubface(badsubfacs, &checksh); + } + } + enextself(fliptets[0]); + } + if (issubface(botcastet)) { + tspivot(botcastet, checksh); // At face [b,a,c] + sesymself(checksh); + tsbond(fliptets[0], checksh); + if (fc->chkencflag & 2) { + enqueuesubface(badsubfacs, &checksh); + } + } + + if (spivot >= 0) { + // Perform a 3-to-1 flip in surface triangulation. + // Depending on the value of 'spivot', the three subfaces are: + // - 0: [a,b,p], [b,d,p], [d,a,p] + // - 1: [b,c,p], [c,d,p], [d,b,p] + // - 2: [c,a,p], [a,d,p], [d,c,p] + // - 3: [a,b,p], [b,c,p], [c,a,p] + // Adjust the three subfaces such that their origins are p, i.e., + // - 3: [p,a,b], [p,b,c], [p,c,a]. (Required by the flip31()). + for (i = 0; i < 3; i++) { + senext2self(flipshs[i]); + } + flip31(flipshs, 0); + // Delete the three old subfaces. + for (i = 0; i < 3; i++) { + shellfacedealloc(subfaces, flipshs[i].sh); + } + if (spivot < 3) { + // // Bond the new subface to the new tet [a,b,c,d]. + tsbond(topcastets[spivot], flipshs[3]); + fsym(topcastets[spivot], newface); + sesym(flipshs[3], checksh); + tsbond(newface, checksh); + } else { + // Bound the new subface [a,b,c] to the new tet [a,b,c,d]. + tsbond(fliptets[0], flipshs[3]); + fsym(fliptets[0], newface); + sesym(flipshs[3], checksh); + tsbond(newface, checksh); + } + } // if (spivot > 0) + } // if (checksubfaceflag) + + if (fc->chkencflag & 4) { + enqueuetetrahedron(&(fliptets[0])); + } + + // Update the point-to-tet map. + setpoint2tet(pa, (tetrahedron) fliptets[0].tet); + setpoint2tet(pb, (tetrahedron) fliptets[0].tet); + setpoint2tet(pc, (tetrahedron) fliptets[0].tet); + setpoint2tet(pd, (tetrahedron) fliptets[0].tet); + + if (fc->enqflag > 0) { + // Queue faces which may be locally non-Delaunay. + flippush(flipstack, &(fliptets[0])); // [a,b,c] (opposite to new point). + if (fc->enqflag > 1) { + for (i = 0; i < 3; i++) { + esym(fliptets[0], newface); + flippush(flipstack, &newface); + enextself(fliptets[0]); + } + } + } + + recenttet = fliptets[0]; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// flipnm() Flip an edge through a sequence of elementary flips. // +// // +// 'abtets' is an array of 'n' tets in the star of edge [a,b].These tets are // +// ordered in a counterclockwise cycle with respect to the vector a->b, i.e.,// +// use the right-hand rule. // +// // +// 'level' (>= 0) indicates the current link level. If 'level > 0', we are // +// flipping a link edge of an edge [a',b'], and 'abedgepivot' indicates // +// which link edge, i.e., [c',b'] or [a',c'], is [a,b] These two parameters // +// allow us to determine the new tets after a 3-to-2 flip, i.e., tets that // +// do not inside the reduced star of edge [a',b']. // +// // +// If the flag 'fc->unflip' is set, this routine un-does the flips performed // +// in flipnm([a,b]) so that the mesh is returned to its original state // +// before doing the flipnm([a,b]) operation. // +// // +// The return value is an integer nn, where nn <= n. If nn is 2, then the // +// edge is flipped. The first and the second tets in 'abtets' are new tets. // +// Otherwise, nn > 2, the edge is not flipped, and nn is the number of tets // +// in the current star of [a,b]. // +// // +// ASSUMPTIONS: // +// - Neither a nor b is 'dummypoint'. // +// - [a,b] must not be a segment. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::flipnm(triface* abtets, int n, int level, int abedgepivot, + flipconstraints* fc) +{ + triface fliptets[3], spintet, flipedge; + triface *tmpabtets, *parytet; + point pa, pb, pc, pd, pe, pf; + REAL ori; + int hullflag, hulledgeflag; + int reducflag, rejflag; + int reflexlinkedgecount; + int edgepivot; + int n1, nn; + int t1ver; + int i, j; + + pa = org(abtets[0]); + pb = dest(abtets[0]); + + if (n > 3) { + // Try to reduce the size of the Star(ab) by flipping a face in it. + reflexlinkedgecount = 0; + + for (i = 0; i < n; i++) { + // Let the face of 'abtets[i]' be [a,b,c]. + if (checksubfaceflag) { + if (issubface(abtets[i])) { + continue; // Skip a subface. + } + } + // Do not flip this face if it is involved in two Stars. + if ((elemcounter(abtets[i]) > 1) || + (elemcounter(abtets[(i - 1 + n) % n]) > 1)) { + continue; + } + + pc = apex(abtets[i]); + pd = apex(abtets[(i + 1) % n]); + pe = apex(abtets[(i - 1 + n) % n]); + if ((pd == dummypoint) || (pe == dummypoint)) { + continue; // [a,b,c] is a hull face. + } + + + // Decide whether [a,b,c] is flippable or not. + reducflag = 0; + + hullflag = (pc == dummypoint); // pc may be dummypoint. + hulledgeflag = 0; + if (hullflag == 0) { + ori = orient3d(pb, pc, pd, pe); // Is [b,c] locally convex? + if (ori > 0) { + ori = orient3d(pc, pa, pd, pe); // Is [c,a] locally convex? + if (ori > 0) { + // Test if [a,b] is locally convex OR flat. + ori = orient3d(pa, pb, pd, pe); + if (ori > 0) { + // Found a 2-to-3 flip: [a,b,c] => [e,d] + reducflag = 1; + } else if (ori == 0) { + // [a,b] is flat. + if (n == 4) { + // The "flat" tet can be removed immediately by a 3-to-2 flip. + reducflag = 1; + // Check if [e,d] is a hull edge. + pf = apex(abtets[(i + 2) % n]); + hulledgeflag = (pf == dummypoint); + } + } + } + } + if (!reducflag) { + reflexlinkedgecount++; + } + } else { + // 'c' is dummypoint. + if (n == 4) { + // Let the vertex opposite to 'c' is 'f'. + // A 4-to-4 flip is possible if the two tets [d,e,f,a] and [e,d,f,b] + // are valid tets. + // Note: When the mesh is not convex, it is possible that [a,b] is + // locally non-convex (at hull faces [a,b,e] and [b,a,d]). + // In this case, an edge flip [a,b] to [e,d] is still possible. + pf = apex(abtets[(i + 2) % n]); + assert(pf != dummypoint); + ori = orient3d(pd, pe, pf, pa); + if (ori < 0) { + ori = orient3d(pe, pd, pf, pb); + if (ori < 0) { + // Found a 4-to-4 flip: [a,b] => [e,d] + reducflag = 1; + ori = 0; // Signal as a 4-to-4 flip (like a co-planar case). + hulledgeflag = 1; // [e,d] is a hull edge. + } + } + } + } // if (hullflag) + + if (reducflag) { + if (nonconvex && hulledgeflag) { + // We will create a hull edge [e,d]. Make sure it does not exist. + if (getedge(pe, pd, &spintet)) { + // The 2-to-3 flip is not a topological valid flip. + reducflag = 0; + } + } + } + + if (reducflag) { + // [a,b,c] could be removed by a 2-to-3 flip. + rejflag = 0; + if (fc->checkflipeligibility) { + // Check if the flip can be performed. + rejflag = checkflipeligibility(1, pa, pb, pc, pd, pe, level, + abedgepivot, fc); + } + if (!rejflag) { + // Do flip: [a,b,c] => [e,d]. + fliptets[0] = abtets[i]; + fsym(fliptets[0], fliptets[1]); // abtets[i-1]. + flip23(fliptets, hullflag, fc); + + // Shrink the array 'abtets', maintain the original order. + // Two tets 'abtets[i-1] ([a,b,e,c])' and 'abtets[i] ([a,b,c,d])' + // are flipped, i.e., they do not in Star(ab) anymore. + // 'fliptets[0]' ([e,d,a,b]) is in Star(ab), it is saved in + // 'abtets[i-1]' (adjust it to be [a,b,e,d]), see below: + // + // before after + // [0] |___________| [0] |___________| + // ... |___________| ... |___________| + // [i-1] |_[a,b,e,c]_| [i-1] |_[a,b,e,d]_| + // [i] |_[a,b,c,d]_| --> [i] |_[a,b,d,#]_| + // [i+1] |_[a,b,d,#]_| [i+1] |_[a,b,#,*]_| + // ... |___________| ... |___________| + // [n-2] |___________| [n-2] |___________| + // [n-1] |___________| [n-1] |_[i]_2-t-3_| + // + edestoppoself(fliptets[0]); // [a,b,e,d] + // Increase the counter of this new tet (it is in Star(ab)). + increaseelemcounter(fliptets[0]); + abtets[(i - 1 + n) % n] = fliptets[0]; + for (j = i; j < n - 1; j++) { + abtets[j] = abtets[j + 1]; // Upshift + } + // The last entry 'abtets[n-1]' is empty. It is used in two ways: + // (i) it remembers the vertex 'c' (in 'abtets[n-1].tet'), and + // (ii) it remembers the position [i] where this flip took place. + // These informations let us to either undo this flip or recover + // the original edge link (for collecting new created tets). + //abtets[n - 1] = fliptets[1]; // [e,d,b,c] is remembered. + abtets[n - 1].tet = (tetrahedron *) pc; + abtets[n - 1].ver = 0; // Clear it. + // 'abtets[n - 1].ver' is in range [0,11] -- only uses 4 bits. + // Use the 5th bit in 'abtets[n - 1].ver' to signal a 2-to-3 flip. + abtets[n - 1].ver |= (1 << 4); + // The poisition [i] of this flip is saved above the 7th bit. + abtets[n - 1].ver |= (i << 6); + + if (fc->collectnewtets) { + // Push the two new tets [e,d,b,c] and [e,d,c,a] into a stack. + // Re-use the global array 'cavetetlist'. + for (j = 1; j < 3; j++) { + cavetetlist->newindex((void **) &parytet); + *parytet = fliptets[j]; // fliptets[1], fliptets[2]. + } + } + + // Star(ab) is reduced. Try to flip the edge [a,b]. + nn = flipnm(abtets, n - 1, level, abedgepivot, fc); + + if (nn == 2) { + // The edge has been flipped. + return nn; + } else { // if (nn > 2) + // The edge is not flipped. + if (fc->unflip || (ori == 0)) { + // Undo the previous 2-to-3 flip, i.e., do a 3-to-2 flip to + // transform [e,d] => [a,b,c]. + // 'ori == 0' means that the previous flip created a degenerated + // tet. It must be removed. + // Remember that 'abtets[i-1]' is [a,b,e,d]. We can use it to + // find another two tets [e,d,b,c] and [e,d,c,a]. + fliptets[0] = abtets[(i-1 + (n-1)) % (n-1)]; // [a,b,e,d] + edestoppoself(fliptets[0]); // [e,d,a,b] + fnext(fliptets[0], fliptets[1]); // [1] is [e,d,b,c] + fnext(fliptets[1], fliptets[2]); // [2] is [e,d,c,a] + assert(apex(fliptets[0]) == oppo(fliptets[2])); // SELF_CHECK + // Restore the two original tets in Star(ab). + flip32(fliptets, hullflag, fc); + // Marktest the two restored tets in Star(ab). + for (j = 0; j < 2; j++) { + increaseelemcounter(fliptets[j]); + } + // Expand the array 'abtets', maintain the original order. + for (j = n - 2; j>= i; j--) { + abtets[j + 1] = abtets[j]; // Downshift + } + // Insert the two new tets 'fliptets[0]' [a,b,c,d] and + // 'fliptets[1]' [b,a,c,e] into the (i-1)-th and i-th entries, + // respectively. + esym(fliptets[1], abtets[(i - 1 + n) % n]); // [a,b,e,c] + abtets[i] = fliptets[0]; // [a,b,c,d] + nn++; + if (fc->collectnewtets) { + // Pop two (flipped) tets from the stack. + cavetetlist->objects -= 2; + } + } // if (unflip || (ori == 0)) + } // if (nn > 2) + + if (!fc->unflip) { + // The flips are not reversed. The current Star(ab) can not be + // further reduced. Return its current size (# of tets). + return nn; + } + // unflip is set. + // Continue the search for flips. + } + } // if (reducflag) + } // i + + // The Star(ab) is not reduced. + if (reflexlinkedgecount > 0) { + // There are reflex edges in the Link(ab). + if (((b->fliplinklevel < 0) && (level < autofliplinklevel)) || + ((b->fliplinklevel >= 0) && (level < b->fliplinklevel))) { + // Try to reduce the Star(ab) by flipping a reflex edge in Link(ab). + for (i = 0; i < n; i++) { + // Do not flip this face [a,b,c] if there are two Stars involved. + if ((elemcounter(abtets[i]) > 1) || + (elemcounter(abtets[(i - 1 + n) % n]) > 1)) { + continue; + } + pc = apex(abtets[i]); + if (pc == dummypoint) { + continue; // [a,b] is a hull edge. + } + pd = apex(abtets[(i + 1) % n]); + pe = apex(abtets[(i - 1 + n) % n]); + if ((pd == dummypoint) || (pe == dummypoint)) { + continue; // [a,b,c] is a hull face. + } + + + edgepivot = 0; // No edge is selected yet. + + // Test if [b,c] is locally convex or flat. + ori = orient3d(pb, pc, pd, pe); + if (ori <= 0) { + // Select the edge [c,b]. + enext(abtets[i], flipedge); // [b,c,a,d] + edgepivot = 1; + } + if (!edgepivot) { + // Test if [c,a] is locally convex or flat. + ori = orient3d(pc, pa, pd, pe); + if (ori <= 0) { + // Select the edge [a,c]. + eprev(abtets[i], flipedge); // [c,a,b,d]. + edgepivot = 2; + } + } + + if (!edgepivot) continue; + + // An edge is selected. + if (checksubsegflag) { + // Do not flip it if it is a segment. + if (issubseg(flipedge)) { + if (fc->collectencsegflag) { + face checkseg, *paryseg; + tsspivot1(flipedge, checkseg); + if (!sinfected(checkseg)) { + // Queue this segment in list. + sinfect(checkseg); + caveencseglist->newindex((void **) &paryseg); + *paryseg = checkseg; + } + } + continue; + } + } + + // Try to flip the selected edge ([c,b] or [a,c]). + esymself(flipedge); + // Count the number of tets at the edge. + n1 = 0; + j = 0; // Sum of the star counters. + spintet = flipedge; + while (1) { + n1++; + j += (elemcounter(spintet)); + fnextself(spintet); + if (spintet.tet == flipedge.tet) break; + } + assert(n1 >= 3); + if (j > 2) { + // The Star(flipedge) overlaps other Stars. + continue; // Do not flip this edge. + } + // Only two tets can be marktested. + assert(j == 2); + + if ((b->flipstarsize > 0) && (n1 > b->flipstarsize)) { + // The star size exceeds the given limit. + continue; // Do not flip it. + } + + // Allocate spaces for Star(flipedge). + tmpabtets = new triface[n1]; + // Form the Star(flipedge). + j = 0; + spintet = flipedge; + while (1) { + tmpabtets[j] = spintet; + // Increase the star counter of this tet. + increaseelemcounter(tmpabtets[j]); + j++; + fnextself(spintet); + if (spintet.tet == flipedge.tet) break; + } + + // Try to flip the selected edge away. + nn = flipnm(tmpabtets, n1, level + 1, edgepivot, fc); + + if (nn == 2) { + // The edge is flipped. Star(ab) is reduced. + // Shrink the array 'abtets', maintain the original order. + if (edgepivot == 1) { + // 'tmpabtets[0]' is [d,a,e,b] => contains [a,b]. + spintet = tmpabtets[0]; // [d,a,e,b] + enextself(spintet); + esymself(spintet); + enextself(spintet); // [a,b,e,d] + } else { + // 'tmpabtets[1]' is [b,d,e,a] => contains [a,b]. + spintet = tmpabtets[1]; // [b,d,e,a] + eprevself(spintet); + esymself(spintet); + eprevself(spintet); // [a,b,e,d] + } // edgepivot == 2 + assert(elemcounter(spintet) == 0); // It's a new tet. + increaseelemcounter(spintet); // It is in Star(ab). + // Put the new tet at [i-1]-th entry. + abtets[(i - 1 + n) % n] = spintet; + for (j = i; j < n - 1; j++) { + abtets[j] = abtets[j + 1]; // Upshift + } + // Remember the flips in the last entry of the array 'abtets'. + // They can be used to recover the flipped edge. + abtets[n - 1].tet = (tetrahedron *) tmpabtets; // The star(fedge). + abtets[n - 1].ver = 0; // Clear it. + // Use the 1st and 2nd bit to save 'edgepivot' (1 or 2). + abtets[n - 1].ver |= edgepivot; + // Use the 6th bit to signal this n1-to-m1 flip. + abtets[n - 1].ver |= (1 << 5); + // The poisition [i] of this flip is saved from 7th to 19th bit. + abtets[n - 1].ver |= (i << 6); + // The size of the star 'n1' is saved from 20th bit. + abtets[n - 1].ver |= (n1 << 19); + + // Remember the flipped link vertex 'c'. It can be used to recover + // the original edge link of [a,b], and to collect new tets. + tmpabtets[0].tet = (tetrahedron *) pc; + tmpabtets[0].ver = (1 << 5); // Flag it as a vertex handle. + + // Continue to flip the edge [a,b]. + nn = flipnm(abtets, n - 1, level, abedgepivot, fc); + + if (nn == 2) { + // The edge has been flipped. + return nn; + } else { // if (nn > 2) { + // The edge is not flipped. + if (fc->unflip) { + // Recover the flipped edge ([c,b] or [a,c]). + assert(nn == (n - 1)); + // The sequence of flips are saved in 'tmpabtets'. + // abtets[(i-1) % (n-1)] is [a,b,e,d], i.e., the tet created by + // the flipping of edge [c,b] or [a,c].It must still exist in + // Star(ab). It is the start tet to recover the flipped edge. + if (edgepivot == 1) { + // The flip edge is [c,b]. + tmpabtets[0] = abtets[((i-1)+(n-1))%(n-1)]; // [a,b,e,d] + eprevself(tmpabtets[0]); + esymself(tmpabtets[0]); + eprevself(tmpabtets[0]); // [d,a,e,b] + fsym(tmpabtets[0], tmpabtets[1]); // [a,d,e,c] + } else { + // The flip edge is [a,c]. + tmpabtets[1] = abtets[((i-1)+(n-1))%(n-1)]; // [a,b,e,d] + enextself(tmpabtets[1]); + esymself(tmpabtets[1]); + enextself(tmpabtets[1]); // [b,d,e,a] + fsym(tmpabtets[1], tmpabtets[0]); // [d,b,e,c] + } // if (edgepivot == 2) + + // Recover the flipped edge ([c,b] or [a,c]). + flipnm_post(tmpabtets, n1, 2, edgepivot, fc); + + // Insert the two recovered tets into Star(ab). + for (j = n - 2; j >= i; j--) { + abtets[j + 1] = abtets[j]; // Downshift + } + if (edgepivot == 1) { + // tmpabtets[0] is [c,b,d,a] ==> contains [a,b] + // tmpabtets[1] is [c,b,a,e] ==> contains [a,b] + // tmpabtets[2] is [c,b,e,d] + fliptets[0] = tmpabtets[1]; + enextself(fliptets[0]); + esymself(fliptets[0]); // [a,b,e,c] + fliptets[1] = tmpabtets[0]; + esymself(fliptets[1]); + eprevself(fliptets[1]); // [a,b,c,d] + } else { + // tmpabtets[0] is [a,c,d,b] ==> contains [a,b] + // tmpabtets[1] is [a,c,b,e] ==> contains [a,b] + // tmpabtets[2] is [a,c,e,d] + fliptets[0] = tmpabtets[1]; + eprevself(fliptets[0]); + esymself(fliptets[0]); // [a,b,e,c] + fliptets[1] = tmpabtets[0]; + esymself(fliptets[1]); + enextself(fliptets[1]); // [a,b,c,d] + } // edgepivot == 2 + for (j = 0; j < 2; j++) { + increaseelemcounter(fliptets[j]); + } + // Insert the two recovered tets into Star(ab). + abtets[(i - 1 + n) % n] = fliptets[0]; + abtets[i] = fliptets[1]; + nn++; + // Release the allocated spaces. + delete [] tmpabtets; + } // if (unflip) + } // if (nn > 2) + + if (!fc->unflip) { + // The flips are not reversed. The current Star(ab) can not be + // further reduced. Return its size (# of tets). + return nn; + } + // unflip is set. + // Continue the search for flips. + } else { + // The selected edge is not flipped. + if (fc->unflip) { + // The memory should already be freed. + assert(nn == n1); + } else { + // Release the memory used in this attempted flip. + flipnm_post(tmpabtets, n1, nn, edgepivot, fc); + } + // Decrease the star counters of tets in Star(flipedge). + for (j = 0; j < nn; j++) { + assert(elemcounter(tmpabtets[j]) > 0); // SELF_CHECK + decreaseelemcounter(tmpabtets[j]); + } + // Release the allocated spaces. + delete [] tmpabtets; + } + } // i + } // if (level...) + } // if (reflexlinkedgecount > 0) + } else { + // Check if a 3-to-2 flip is possible. + // Let the three apexes be c, d,and e. Hull tets may be involved. If so, + // we rearrange them such that the vertex e is dummypoint. + hullflag = 0; + + if (apex(abtets[0]) == dummypoint) { + pc = apex(abtets[1]); + pd = apex(abtets[2]); + pe = apex(abtets[0]); + hullflag = 1; + } else if (apex(abtets[1]) == dummypoint) { + pc = apex(abtets[2]); + pd = apex(abtets[0]); + pe = apex(abtets[1]); + hullflag = 2; + } else { + pc = apex(abtets[0]); + pd = apex(abtets[1]); + pe = apex(abtets[2]); + hullflag = (pe == dummypoint) ? 3 : 0; + } + + reducflag = 0; + rejflag = 0; + + + if (hullflag == 0) { + // Make sure that no inverted tet will be created, i.e. the new tets + // [d,c,e,a] and [c,d,e,b] must be valid tets. + ori = orient3d(pd, pc, pe, pa); + if (ori < 0) { + ori = orient3d(pc, pd, pe, pb); + if (ori < 0) { + reducflag = 1; + } + } + } else { + // [a,b] is a hull edge. + // Note: This can happen when it is in the middle of a 4-to-4 flip. + // Note: [a,b] may even be a non-convex hull edge. + if (!nonconvex) { + // The mesh is convex, only do flip if it is a coplanar hull edge. + ori = orient3d(pa, pb, pc, pd); + if (ori == 0) { + reducflag = 1; + } + } else { // nonconvex + reducflag = 1; + } + if (reducflag == 1) { + // [a,b], [a,b,c] and [a,b,d] are on the convex hull. + // Make sure that no inverted tet will be created. + point searchpt = NULL, chkpt; + REAL bigvol = 0.0, ori1, ori2; + // Search an interior vertex which is an apex of edge [c,d]. + // In principle, it can be arbitrary interior vertex. To avoid + // numerical issue, we choose the vertex which belongs to a tet + // 't' at edge [c,d] and 't' has the biggest volume. + fliptets[0] = abtets[hullflag % 3]; // [a,b,c,d]. + eorgoppoself(fliptets[0]); // [d,c,b,a] + spintet = fliptets[0]; + while (1) { + fnextself(spintet); + chkpt = oppo(spintet); + if (chkpt == pb) break; + if ((chkpt != dummypoint) && (apex(spintet) != dummypoint)) { + ori = -orient3d(pd, pc, apex(spintet), chkpt); + assert(ori > 0); + if (ori > bigvol) { + bigvol = ori; + searchpt = chkpt; + } + } + } + if (searchpt != NULL) { + // Now valid the configuration. + ori1 = orient3d(pd, pc, searchpt, pa); + ori2 = orient3d(pd, pc, searchpt, pb); + if (ori1 * ori2 >= 0.0) { + reducflag = 0; // Not valid. + } else { + ori1 = orient3d(pa, pb, searchpt, pc); + ori2 = orient3d(pa, pb, searchpt, pd); + if (ori1 * ori2 >= 0.0) { + reducflag = 0; // Not valid. + } + } + } else { + // No valid searchpt is found. + reducflag = 0; // Do not flip it. + } + } // if (reducflag == 1) + } // if (hullflag == 1) + + if (reducflag) { + // A 3-to-2 flip is possible. + if (checksubfaceflag) { + // This edge (must not be a segment) can be flipped ONLY IF it belongs + // to either 0 or 2 subfaces. In the latter case, a 2-to-2 flip in + // the surface mesh will be automatically performed within the + // 3-to-2 flip. + nn = 0; + edgepivot = -1; // Re-use it. + for (j = 0; j < 3; j++) { + if (issubface(abtets[j])) { + nn++; // Found a subface. + } else { + edgepivot = j; + } + } + assert(nn < 3); + if (nn == 1) { + // Found only 1 subface containing this edge. This can happen in + // the boundary recovery phase. The neighbor subface is not yet + // recovered. This edge should not be flipped at this moment. + rejflag = 1; + } else if (nn == 2) { + // Found two subfaces. A 2-to-2 flip is possible. Validate it. + // Below we check if the two faces [p,q,a] and [p,q,b] are subfaces. + eorgoppo(abtets[(edgepivot + 1) % 3], spintet); // [q,p,b,a] + if (issubface(spintet)) { + rejflag = 1; // Conflict to a 2-to-2 flip. + } else { + esymself(spintet); + if (issubface(spintet)) { + rejflag = 1; // Conflict to a 2-to-2 flip. + } + } + } + } + if (!rejflag && fc->checkflipeligibility) { + // Here we must exchange 'a' and 'b'. Since in the check... function, + // we assume the following point sequence, 'a,b,c,d,e', where + // the face [a,b,c] will be flipped and the edge [e,d] will be + // created. The two new tets are [a,b,c,d] and [b,a,c,e]. + rejflag = checkflipeligibility(2, pc, pd, pe, pb, pa, level, + abedgepivot, fc); + } + if (!rejflag) { + // Do flip: [a,b] => [c,d,e] + flip32(abtets, hullflag, fc); + if (fc->remove_ndelaunay_edge) { + if (level == 0) { + // It is the desired removing edge. Check if we have improved + // the objective function. + if ((fc->tetprism_vol_sum >= 0.0) || + (fabs(fc->tetprism_vol_sum) < fc->bak_tetprism_vol)) { + // No improvement! flip back: [c,d,e] => [a,b]. + flip23(abtets, hullflag, fc); + // Increase the element counter -- They are in cavity. + for (j = 0; j < 3; j++) { + increaseelemcounter(abtets[j]); + } + return 3; + } + } // if (level == 0) + } + if (fc->collectnewtets) { + // Collect new tets. + if (level == 0) { + // Push the two new tets into stack. + for (j = 0; j < 2; j++) { + cavetetlist->newindex((void **) &parytet); + *parytet = abtets[j]; + } + } else { + // Only one of the new tets is collected. The other one is inside + // the reduced edge star. 'abedgepivot' is either '1' or '2'. + cavetetlist->newindex((void **) &parytet); + if (abedgepivot == 1) { // [c,b] + *parytet = abtets[1]; + } else { + assert(abedgepivot == 2); // [a,c] + *parytet = abtets[0]; + } + } + } // if (fc->collectnewtets) + return 2; + } + } // if (reducflag) + } // if (n == 3) + + // The current (reduced) Star size. + return n; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// flipnm_post() Post process a n-to-m flip. // +// // +// IMPORTANT: This routine only works when there is no other flip operation // +// is done after flipnm([a,b]) which attempts to remove an edge [a,b]. // +// // +// 'abtets' is an array of 'n' (>= 3) tets which are in the original star of // +// [a,b] before flipnm([a,b]). 'nn' (< n) is the value returned by flipnm. // +// If 'nn == 2', the edge [a,b] has been flipped. 'abtets[0]' and 'abtets[1]'// +// are [c,d,e,b] and [d,c,e,a], i.e., a 2-to-3 flip can recover the edge [a, // +// b] and its initial Star([a,b]). If 'nn >= 3' edge [a,b] still exists in // +// current mesh and 'nn' is the current number of tets in Star([a,b]). // +// // +// Each 'abtets[i]', where nn <= i < n, saves either a 2-to-3 flip or a // +// flipnm([p1,p2]) operation ([p1,p2] != [a,b]) which created the tet // +// 'abtets[t-1]', where '0 <= t <= i'. These information can be used to // +// undo the flips performed in flipnm([a,b]) or to collect new tets created // +// by the flipnm([a,b]) operation. // +// // +// Default, this routine only walks through the flips and frees the spaces // +// allocated during the flipnm([a,b]) operation. // +// // +// If the flag 'fc->unflip' is set, this routine un-does the flips performed // +// in flipnm([a,b]) so that the mesh is returned to its original state // +// before doing the flipnm([a,b]) operation. // +// // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::flipnm_post(triface* abtets, int n, int nn, int abedgepivot, + flipconstraints* fc) +{ + triface fliptets[3], flipface; + triface *tmpabtets; + int fliptype; + int edgepivot; + int t, n1; + int i, j; + + + if (nn == 2) { + // The edge [a,b] has been flipped. + // 'abtets[0]' is [c,d,e,b] or [#,#,#,b]. + // 'abtets[1]' is [d,c,e,a] or [#,#,#,a]. + if (fc->unflip) { + // Do a 2-to-3 flip to recover the edge [a,b]. There may be hull tets. + flip23(abtets, 1, fc); + if (fc->collectnewtets) { + // Pop up new (flipped) tets from the stack. + if (abedgepivot == 0) { + // Two new tets were collected. + cavetetlist->objects -= 2; + } else { + // Only one of the two new tets was collected. + cavetetlist->objects -= 1; + } + } + } + // The initial size of Star(ab) is 3. + nn++; + } + + // Walk through the performed flips. + for (i = nn; i < n; i++) { + // At the beginning of each step 'i', the size of the Star([a,b]) is 'i'. + // At the end of this step, the size of the Star([a,b]) is 'i+1'. + // The sizes of the Link([a,b]) are the same. + fliptype = ((abtets[i].ver >> 4) & 3); // 0, 1, or 2. + if (fliptype == 1) { + // It was a 2-to-3 flip: [a,b,c]->[e,d]. + t = (abtets[i].ver >> 6); + assert(t <= i); + if (fc->unflip) { + if (b->verbose > 2) { + printf(" Recover a 2-to-3 flip at f[%d].\n", t); + } + // 'abtets[(t-1)%i]' is the tet [a,b,e,d] in current Star(ab), i.e., + // it is created by a 2-to-3 flip [a,b,c] => [e,d]. + fliptets[0] = abtets[((t - 1) + i) % i]; // [a,b,e,d] + eprevself(fliptets[0]); + esymself(fliptets[0]); + enextself(fliptets[0]); // [e,d,a,b] + fnext(fliptets[0], fliptets[1]); // [e,d,b,c] + fnext(fliptets[1], fliptets[2]); // [e,d,c,a] + // Do a 3-to-2 flip: [e,d] => [a,b,c]. + // NOTE: hull tets may be invloved. + flip32(fliptets, 1, fc); + // Expand the array 'abtets', maintain the original order. + // The new array length is (i+1). + for (j = i - 1; j >= t; j--) { + abtets[j + 1] = abtets[j]; // Downshift + } + // The tet abtets[(t-1)%i] is deleted. Insert the two new tets + // 'fliptets[0]' [a,b,c,d] and 'fliptets[1]' [b,a,c,e] into + // the (t-1)-th and t-th entries, respectively. + esym(fliptets[1], abtets[((t-1) + (i+1)) % (i+1)]); // [a,b,e,c] + abtets[t] = fliptets[0]; // [a,b,c,d] + if (fc->collectnewtets) { + // Pop up two (flipped) tets from the stack. + cavetetlist->objects -= 2; + } + } + } else if (fliptype == 2) { + tmpabtets = (triface *) (abtets[i].tet); + n1 = ((abtets[i].ver >> 19) & 8191); // \sum_{i=0^12}{2^i} = 8191 + edgepivot = (abtets[i].ver & 3); + t = ((abtets[i].ver >> 6) & 8191); + assert(t <= i); + if (fc->unflip) { + if (b->verbose > 2) { + printf(" Recover a %d-to-m flip at e[%d] of f[%d].\n", n1, + edgepivot, t); + } + // Recover the flipped edge ([c,b] or [a,c]). + // abtets[(t - 1 + i) % i] is [a,b,e,d], i.e., the tet created by + // the flipping of edge [c,b] or [a,c]. It must still exist in + // Star(ab). Use it to recover the flipped edge. + if (edgepivot == 1) { + // The flip edge is [c,b]. + tmpabtets[0] = abtets[(t - 1 + i) % i]; // [a,b,e,d] + eprevself(tmpabtets[0]); + esymself(tmpabtets[0]); + eprevself(tmpabtets[0]); // [d,a,e,b] + fsym(tmpabtets[0], tmpabtets[1]); // [a,d,e,c] + } else { + // The flip edge is [a,c]. + tmpabtets[1] = abtets[(t - 1 + i) % i]; // [a,b,e,d] + enextself(tmpabtets[1]); + esymself(tmpabtets[1]); + enextself(tmpabtets[1]); // [b,d,e,a] + fsym(tmpabtets[1], tmpabtets[0]); // [d,b,e,c] + } // if (edgepivot == 2) + + // Do a n1-to-m1 flip to recover the flipped edge ([c,b] or [a,c]). + flipnm_post(tmpabtets, n1, 2, edgepivot, fc); + + // Insert the two recovered tets into the original Star(ab). + for (j = i - 1; j >= t; j--) { + abtets[j + 1] = abtets[j]; // Downshift + } + if (edgepivot == 1) { + // tmpabtets[0] is [c,b,d,a] ==> contains [a,b] + // tmpabtets[1] is [c,b,a,e] ==> contains [a,b] + // tmpabtets[2] is [c,b,e,d] + fliptets[0] = tmpabtets[1]; + enextself(fliptets[0]); + esymself(fliptets[0]); // [a,b,e,c] + fliptets[1] = tmpabtets[0]; + esymself(fliptets[1]); + eprevself(fliptets[1]); // [a,b,c,d] + } else { + // tmpabtets[0] is [a,c,d,b] ==> contains [a,b] + // tmpabtets[1] is [a,c,b,e] ==> contains [a,b] + // tmpabtets[2] is [a,c,e,d] + fliptets[0] = tmpabtets[1]; + eprevself(fliptets[0]); + esymself(fliptets[0]); // [a,b,e,c] + fliptets[1] = tmpabtets[0]; + esymself(fliptets[1]); + enextself(fliptets[1]); // [a,b,c,d] + } // edgepivot == 2 + // Insert the two recovered tets into Star(ab). + abtets[((t-1) + (i+1)) % (i+1)] = fliptets[0]; + abtets[t] = fliptets[1]; + } + else { + // Only free the spaces. + flipnm_post(tmpabtets, n1, 2, edgepivot, fc); + } // if (!unflip) + if (b->verbose > 2) { + printf(" Release %d spaces at f[%d].\n", n1, i); + } + delete [] tmpabtets; + } + } // i + + return 1; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// insertpoint() Insert a point into current tetrahedralization. // +// // +// The Bowyer-Watson (B-W) algorithm is used to add a new point p into the // +// tetrahedralization T. It first finds a "cavity", denoted as C, in T, C // +// consists of tetrahedra in T that "conflict" with p. If T is a Delaunay // +// tetrahedralization, then all boundary faces (triangles) of C are visible // +// by p, i.e.,C is star-shaped. We can insert p into T by first deleting all // +// tetrahedra in C, then creating new tetrahedra formed by boundary faces of // +// C and p. If T is not a DT, then C may be not star-shaped. It must be // +// modified so that it becomes star-shaped. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::insertpoint(point insertpt, triface *searchtet, face *splitsh, + face *splitseg, insertvertexflags *ivf) +{ + arraypool *swaplist; + triface *cavetet, spintet, neightet, neineitet, *parytet; + triface oldtet, newtet, newneitet; + face checksh, neighsh, *parysh; + face checkseg, *paryseg; + point *pts, pa, pb, pc, *parypt; + enum locateresult loc = OUTSIDE; + REAL sign, ori; + REAL attrib, volume; + bool enqflag; + int t1ver; + int i, j, k, s; + + if (b->verbose > 2) { + printf(" Insert point %d\n", pointmark(insertpt)); + } + + // Locate the point. + if (searchtet->tet != NULL) { + loc = (enum locateresult) ivf->iloc; + } + + if (loc == OUTSIDE) { + if (searchtet->tet == NULL) { + if (!b->weighted) { + randomsample(insertpt, searchtet); + } else { + // Weighted DT. There may exist dangling vertex. + *searchtet = recenttet; + } + } + // Locate the point. + loc = locate(insertpt, searchtet); + } + + ivf->iloc = (int) loc; // The return value. + + if (b->weighted) { + if (loc != OUTSIDE) { + // Check if this vertex is regular. + pts = (point *) searchtet->tet; + assert(pts[7] != dummypoint); + sign = orient4d_s(pts[4], pts[5], pts[6], pts[7], insertpt, + pts[4][3], pts[5][3], pts[6][3], pts[7][3], + insertpt[3]); + if (sign > 0) { + // This new vertex does not lie below the lower hull. Skip it. + setpointtype(insertpt, NREGULARVERTEX); + nonregularcount++; + ivf->iloc = (int) NONREGULAR; + return 0; + } + } + } + + // Create the initial cavity C(p) which contains all tetrahedra that + // intersect p. It may include 1, 2, or n tetrahedra. + // If p lies on a segment or subface, also create the initial sub-cavity + // sC(p) which contains all subfaces (and segment) which intersect p. + + if (loc == OUTSIDE) { + flip14count++; + // The current hull will be enlarged. + // Add four adjacent boundary tets into list. + for (i = 0; i < 4; i++) { + decode(searchtet->tet[i], neightet); + neightet.ver = epivot[neightet.ver]; + cavebdrylist->newindex((void **) &parytet); + *parytet = neightet; + } + infect(*searchtet); + caveoldtetlist->newindex((void **) &parytet); + *parytet = *searchtet; + } else if (loc == INTETRAHEDRON) { + flip14count++; + // Add four adjacent boundary tets into list. + for (i = 0; i < 4; i++) { + decode(searchtet->tet[i], neightet); + neightet.ver = epivot[neightet.ver]; + cavebdrylist->newindex((void **) &parytet); + *parytet = neightet; + } + infect(*searchtet); + caveoldtetlist->newindex((void **) &parytet); + *parytet = *searchtet; + } else if (loc == ONFACE) { + flip26count++; + // Add six adjacent boundary tets into list. + j = (searchtet->ver & 3); // The current face number. + for (i = 1; i < 4; i++) { + decode(searchtet->tet[(j + i) % 4], neightet); + neightet.ver = epivot[neightet.ver]; + cavebdrylist->newindex((void **) &parytet); + *parytet = neightet; + } + decode(searchtet->tet[j], spintet); + j = (spintet.ver & 3); // The current face number. + for (i = 1; i < 4; i++) { + decode(spintet.tet[(j + i) % 4], neightet); + neightet.ver = epivot[neightet.ver]; + cavebdrylist->newindex((void **) &parytet); + *parytet = neightet; + } + infect(spintet); + caveoldtetlist->newindex((void **) &parytet); + *parytet = spintet; + infect(*searchtet); + caveoldtetlist->newindex((void **) &parytet); + *parytet = *searchtet; + + if (ivf->splitbdflag) { + if ((splitsh != NULL) && (splitsh->sh != NULL)) { + // Create the initial sub-cavity sC(p). + smarktest(*splitsh); + caveshlist->newindex((void **) &parysh); + *parysh = *splitsh; + } + } // if (splitbdflag) + } else if (loc == ONEDGE) { + flipn2ncount++; + // Add all adjacent boundary tets into list. + spintet = *searchtet; + while (1) { + eorgoppo(spintet, neightet); + decode(neightet.tet[neightet.ver & 3], neightet); + neightet.ver = epivot[neightet.ver]; + cavebdrylist->newindex((void **) &parytet); + *parytet = neightet; + edestoppo(spintet, neightet); + decode(neightet.tet[neightet.ver & 3], neightet); + neightet.ver = epivot[neightet.ver]; + cavebdrylist->newindex((void **) &parytet); + *parytet = neightet; + infect(spintet); + caveoldtetlist->newindex((void **) &parytet); + *parytet = spintet; + fnextself(spintet); + if (spintet.tet == searchtet->tet) break; + } // while (1) + + if (ivf->splitbdflag) { + // Create the initial sub-cavity sC(p). + if ((splitseg != NULL) && (splitseg->sh != NULL)) { + smarktest(*splitseg); + splitseg->shver = 0; + spivot(*splitseg, *splitsh); + } + if (splitsh != NULL) { + if (splitsh->sh != NULL) { + // Collect all subfaces share at this edge. + pa = sorg(*splitsh); + neighsh = *splitsh; + while (1) { + // Adjust the origin of its edge to be 'pa'. + if (sorg(neighsh) != pa) { + sesymself(neighsh); + } + // Add this face into list (in B-W cavity). + smarktest(neighsh); + caveshlist->newindex((void **) &parysh); + *parysh = neighsh; + // Add this face into face-at-splitedge list. + cavesegshlist->newindex((void **) &parysh); + *parysh = neighsh; + // Go to the next face at the edge. + spivotself(neighsh); + // Stop if all faces at the edge have been visited. + if (neighsh.sh == splitsh->sh) break; + if (neighsh.sh == NULL) break; + } // while (1) + } // if (not a dangling segment) + } + } // if (splitbdflag) + } else if (loc == INSTAR) { + // We assume that all tets in the star are given in 'caveoldtetlist', + // and they are all infected. + assert(caveoldtetlist->objects > 0); + // Collect the boundary faces of the star. + for (i = 0; i < caveoldtetlist->objects; i++) { + cavetet = (triface *) fastlookup(caveoldtetlist, i); + // Check its 4 neighbor tets. + for (j = 0; j < 4; j++) { + decode(cavetet->tet[j], neightet); + if (!infected(neightet)) { + // It's a boundary face. + neightet.ver = epivot[neightet.ver]; + cavebdrylist->newindex((void **) &parytet); + *parytet = neightet; + } + } + } + } else if (loc == ONVERTEX) { + // The point already exist. Do nothing and return. + return 0; + } + + + if (ivf->assignmeshsize) { + // Assign mesh size for the new point. + if (bgm != NULL) { + // Interpolate the mesh size from the background mesh. + bgm->decode(point2bgmtet(org(*searchtet)), neightet); + int bgmloc = (int) bgm->scoutpoint(insertpt, &neightet, 0); + if (bgmloc != (int) OUTSIDE) { + insertpt[pointmtrindex] = + bgm->getpointmeshsize(insertpt, &neightet, bgmloc); + setpoint2bgmtet(insertpt, bgm->encode(neightet)); + } + } else { + insertpt[pointmtrindex] = getpointmeshsize(insertpt,searchtet,(int)loc); + } + } // if (assignmeshsize) + + if (ivf->bowywat) { + // Update the cavity C(p) using the Bowyer-Watson algorithm. + swaplist = cavetetlist; + cavetetlist = cavebdrylist; + cavebdrylist = swaplist; + for (i = 0; i < cavetetlist->objects; i++) { + // 'cavetet' is an adjacent tet at outside of the cavity. + cavetet = (triface *) fastlookup(cavetetlist, i); + // The tet may be tested and included in the (enlarged) cavity. + if (!infected(*cavetet)) { + // Check for two possible cases for this tet: + // (1) It is a cavity tet, or + // (2) it is a cavity boundary face. + enqflag = false; + if (!marktested(*cavetet)) { + // Do Delaunay (in-sphere) test. + pts = (point *) cavetet->tet; + if (pts[7] != dummypoint) { + // A volume tet. Operate on it. + if (b->weighted) { + sign = orient4d_s(pts[4], pts[5], pts[6], pts[7], insertpt, + pts[4][3], pts[5][3], pts[6][3], pts[7][3], + insertpt[3]); + } else { + sign = insphere_s(pts[4], pts[5], pts[6], pts[7], insertpt); + } + enqflag = (sign < 0.0); + } else { + if (!nonconvex) { + // Test if this hull face is visible by the new point. + ori = orient3d(pts[4], pts[5], pts[6], insertpt); + if (ori < 0) { + // A visible hull face. + //if (!nonconvex) { + // Include it in the cavity. The convex hull will be enlarged. + enqflag = true; // (ori < 0.0); + //} + } else if (ori == 0.0) { + // A coplanar hull face. We need to test if this hull face is + // Delaunay or not. We test if the adjacent tet (not faked) + // of this hull face is Delaunay or not. + decode(cavetet->tet[3], neineitet); + if (!infected(neineitet)) { + if (!marktested(neineitet)) { + // Do Delaunay test on this tet. + pts = (point *) neineitet.tet; + assert(pts[7] != dummypoint); + if (b->weighted) { + sign = orient4d_s(pts[4],pts[5],pts[6],pts[7], insertpt, + pts[4][3], pts[5][3], pts[6][3], + pts[7][3], insertpt[3]); + } else { + sign = insphere_s(pts[4],pts[5],pts[6],pts[7], insertpt); + } + enqflag = (sign < 0.0); + } + } else { + // The adjacent tet is non-Delaunay. The hull face is non- + // Delaunay as well. Include it in the cavity. + enqflag = true; + } // if (!infected(neineitet)) + } // if (ori == 0.0) + } else { + // A hull face (must be a subface). + // We FIRST include it in the initial cavity if the adjacent tet + // (not faked) of this hull face is not Delaunay wrt p. + // Whether it belongs to the final cavity will be determined + // during the validation process. 'validflag'. + decode(cavetet->tet[3], neineitet); + if (!infected(neineitet)) { + if (!marktested(neineitet)) { + // Do Delaunay test on this tet. + pts = (point *) neineitet.tet; + assert(pts[7] != dummypoint); + if (b->weighted) { + sign = orient4d_s(pts[4],pts[5],pts[6],pts[7], insertpt, + pts[4][3], pts[5][3], pts[6][3], + pts[7][3], insertpt[3]); + } else { + sign = insphere_s(pts[4],pts[5],pts[6],pts[7], insertpt); + } + enqflag = (sign < 0.0); + } + } else { + // The adjacent tet is non-Delaunay. The hull face is non- + // Delaunay as well. Include it in the cavity. + enqflag = true; + } // if (infected(neineitet)) + } // if (nonconvex) + } // if (pts[7] != dummypoint) + marktest(*cavetet); // Only test it once. + } // if (!marktested(*cavetet)) + + if (enqflag) { + // Found a tet in the cavity. Put other three faces in check list. + k = (cavetet->ver & 3); // The current face number + for (j = 1; j < 4; j++) { + decode(cavetet->tet[(j + k) % 4], neightet); + cavetetlist->newindex((void **) &parytet); + *parytet = neightet; + } + infect(*cavetet); + caveoldtetlist->newindex((void **) &parytet); + *parytet = *cavetet; + } else { + // Found a boundary face of the cavity. + cavetet->ver = epivot[cavetet->ver]; + cavebdrylist->newindex((void **) &parytet); + *parytet = *cavetet; + } + } // if (!infected(*cavetet)) + } // i + + cavetetlist->restart(); // Clear the working list. + } // if (ivf->bowywat) + + if (checksubsegflag) { + // Collect all segments of C(p). + shellface *ssptr; + for (i = 0; i < caveoldtetlist->objects; i++) { + cavetet = (triface *) fastlookup(caveoldtetlist, i); + if ((ssptr = (shellface*) cavetet->tet[8]) != NULL) { + for (j = 0; j < 6; j++) { + if (ssptr[j]) { + sdecode(ssptr[j], checkseg); + if (!sinfected(checkseg)) { + sinfect(checkseg); + cavetetseglist->newindex((void **) &paryseg); + *paryseg = checkseg; + } + } + } // j + } + } // i + // Uninfect collected segments. + for (i = 0; i < cavetetseglist->objects; i++) { + paryseg = (face *) fastlookup(cavetetseglist, i); + suninfect(*paryseg); + } + + if (ivf->rejflag & 1) { + // Reject this point if it encroaches upon any segment. + face *paryseg1; + for (i = 0; i < cavetetseglist->objects; i++) { + paryseg1 = (face *) fastlookup(cavetetseglist, i); + if (checkseg4encroach((point) paryseg1->sh[3], (point) paryseg1->sh[4], + insertpt)) { + encseglist->newindex((void **) &paryseg); + *paryseg = *paryseg1; + } + } // i + if (encseglist->objects > 0) { + insertpoint_abort(splitseg, ivf); + ivf->iloc = (int) ENCSEGMENT; + return 0; + } + } + } // if (checksubsegflag) + + if (checksubfaceflag) { + // Collect all subfaces of C(p). + shellface *sptr; + for (i = 0; i < caveoldtetlist->objects; i++) { + cavetet = (triface *) fastlookup(caveoldtetlist, i); + if ((sptr = (shellface*) cavetet->tet[9]) != NULL) { + for (j = 0; j < 4; j++) { + if (sptr[j]) { + sdecode(sptr[j], checksh); + if (!sinfected(checksh)) { + sinfect(checksh); + cavetetshlist->newindex((void **) &parysh); + *parysh = checksh; + } + } + } // j + } + } // i + // Uninfect collected subfaces. + for (i = 0; i < cavetetshlist->objects; i++) { + parysh = (face *) fastlookup(cavetetshlist, i); + suninfect(*parysh); + } + + if (ivf->rejflag & 2) { + REAL rd, cent[3]; + badface *bface; + // Reject this point if it encroaches upon any subface. + for (i = 0; i < cavetetshlist->objects; i++) { + parysh = (face *) fastlookup(cavetetshlist, i); + if (checkfac4encroach((point) parysh->sh[3], (point) parysh->sh[4], + (point) parysh->sh[5], insertpt, cent, &rd)) { + encshlist->newindex((void **) &bface); + bface->ss = *parysh; + bface->forg = (point) parysh->sh[3]; // Not a dad one. + for (j = 0; j < 3; j++) bface->cent[j] = cent[j]; + bface->key = rd; + } + } + if (encshlist->objects > 0) { + insertpoint_abort(splitseg, ivf); + ivf->iloc = (int) ENCSUBFACE; + return 0; + } + } + } // if (checksubfaceflag) + + if ((ivf->iloc == (int) OUTSIDE) && ivf->refineflag) { + // The vertex lies outside of the domain. And it does not encroach + // upon any boundary segment or subface. Do not insert it. + insertpoint_abort(splitseg, ivf); + return 0; + } + + if (ivf->splitbdflag) { + // The new point locates in surface mesh. Update the sC(p). + // We have already 'smarktested' the subfaces which directly intersect + // with p in 'caveshlist'. From them, we 'smarktest' their neighboring + // subfaces which are included in C(p). Do not across a segment. + for (i = 0; i < caveshlist->objects; i++) { + parysh = (face *) fastlookup(caveshlist, i); + assert(smarktested(*parysh)); + checksh = *parysh; + for (j = 0; j < 3; j++) { + if (!isshsubseg(checksh)) { + spivot(checksh, neighsh); + assert(neighsh.sh != NULL); + if (!smarktested(neighsh)) { + stpivot(neighsh, neightet); + if (infected(neightet)) { + fsymself(neightet); + if (infected(neightet)) { + // This subface is inside C(p). + // Check if its diametrical circumsphere encloses 'p'. + // The purpose of this check is to avoid forming invalid + // subcavity in surface mesh. + sign = incircle3d(sorg(neighsh), sdest(neighsh), + sapex(neighsh), insertpt); + if (sign < 0) { + smarktest(neighsh); + caveshlist->newindex((void **) &parysh); + *parysh = neighsh; + } + } + } + } + } + senextself(checksh); + } // j + } // i + } // if (ivf->splitbdflag) + + if (ivf->validflag) { + // Validate C(p) and update it if it is not star-shaped. + int cutcount = 0; + + if (ivf->respectbdflag) { + // The initial cavity may include subfaces which are not on the facets + // being splitting. Find them and make them as boundary of C(p). + // Comment: We have already 'smarktested' the subfaces in sC(p). They + // are completely inside C(p). + for (i = 0; i < cavetetshlist->objects; i++) { + parysh = (face *) fastlookup(cavetetshlist, i); + stpivot(*parysh, neightet); + if (infected(neightet)) { + fsymself(neightet); + if (infected(neightet)) { + // Found a subface inside C(p). + if (!smarktested(*parysh)) { + // It is possible that this face is a boundary subface. + // Check if it is a hull face. + //assert(apex(neightet) != dummypoint); + if (oppo(neightet) != dummypoint) { + fsymself(neightet); + } + if (oppo(neightet) != dummypoint) { + ori = orient3d(org(neightet), dest(neightet), apex(neightet), + insertpt); + if (ori < 0) { + // A visible face, get its neighbor face. + fsymself(neightet); + ori = -ori; // It must be invisible by p. + } + } else { + // A hull tet. It needs to be cut. + ori = 1; + } + // Cut this tet if it is either invisible by or coplanar with p. + if (ori >= 0) { + uninfect(neightet); + unmarktest(neightet); + cutcount++; + neightet.ver = epivot[neightet.ver]; + cavebdrylist->newindex((void **) &parytet); + *parytet = neightet; + // Add three new faces to find new boundaries. + for (j = 0; j < 3; j++) { + esym(neightet, neineitet); + neineitet.ver = epivot[neineitet.ver]; + cavebdrylist->newindex((void **) &parytet); + *parytet = neineitet; + enextself(neightet); + } + } // if (ori >= 0) + } + } + } + } // i + + // The initial cavity may include segments in its interior. We need to + // Update the cavity so that these segments are on the boundary of + // the cavity. + for (i = 0; i < cavetetseglist->objects; i++) { + paryseg = (face *) fastlookup(cavetetseglist, i); + // Check this segment if it is not a splitting segment. + if (!smarktested(*paryseg)) { + sstpivot1(*paryseg, neightet); + spintet = neightet; + while (1) { + if (!infected(spintet)) break; + fnextself(spintet); + if (spintet.tet == neightet.tet) break; + } + if (infected(spintet)) { + // Find an adjacent tet at this segment such that both faces + // at this segment are not visible by p. + pa = org(neightet); + pb = dest(neightet); + spintet = neightet; + j = 0; + while (1) { + // Check if this face is visible by p. + pc = apex(spintet); + if (pc != dummypoint) { + ori = orient3d(pa, pb, pc, insertpt); + if (ori >= 0) { + // Not visible. Check another face in this tet. + esym(spintet, neineitet); + pc = apex(neineitet); + if (pc != dummypoint) { + ori = orient3d(pb, pa, pc, insertpt); + if (ori >= 0) { + // Not visible. Found this face. + j = 1; // Flag that it is found. + break; + } + } + } + } + fnextself(spintet); + if (spintet.tet == neightet.tet) break; + } + if (j == 0) { + // Not found such a face. + assert(0); // debug this case. + } + neightet = spintet; + if (b->verbose > 3) { + printf(" Cut tet (%d, %d, %d, %d)\n", + pointmark(org(neightet)), pointmark(dest(neightet)), + pointmark(apex(neightet)), pointmark(oppo(neightet))); + } + uninfect(neightet); + unmarktest(neightet); + cutcount++; + neightet.ver = epivot[neightet.ver]; + cavebdrylist->newindex((void **) &parytet); + *parytet = neightet; + // Add three new faces to find new boundaries. + for (j = 0; j < 3; j++) { + esym(neightet, neineitet); + neineitet.ver = epivot[neineitet.ver]; + cavebdrylist->newindex((void **) &parytet); + *parytet = neineitet; + enextself(neightet); + } + } + } + } // i + } // if (ivf->respectbdflag) + + // Update the cavity by removing invisible faces until it is star-shaped. + for (i = 0; i < cavebdrylist->objects; i++) { + cavetet = (triface *) fastlookup(cavebdrylist, i); + // 'cavetet' is an exterior tet adjacent to the cavity. + // Check if its neighbor is inside C(p). + fsym(*cavetet, neightet); + if (infected(neightet)) { + if (apex(*cavetet) != dummypoint) { + // It is a cavity boundary face. Check its visibility. + if (oppo(neightet) != dummypoint) { + ori = orient3d(org(*cavetet), dest(*cavetet), apex(*cavetet), + insertpt); + enqflag = (ori > 0); + // Comment: if ori == 0 (coplanar case), we also cut the tet. + } else { + // It is a hull face. And its adjacent tet (at inside of the + // domain) has been cut from the cavity. Cut it as well. + //assert(nonconvex); + enqflag = false; + } + } else { + enqflag = true; // A hull edge. + } + if (enqflag) { + // This face is valid, save it. + cavetetlist->newindex((void **) &parytet); + *parytet = *cavetet; + } else { + uninfect(neightet); + unmarktest(neightet); + cutcount++; + // Add three new faces to find new boundaries. + for (j = 0; j < 3; j++) { + esym(neightet, neineitet); + neineitet.ver = epivot[neineitet.ver]; + cavebdrylist->newindex((void **) &parytet); + *parytet = neineitet; + enextself(neightet); + } + // 'cavetet' is not on the cavity boundary anymore. + unmarktest(*cavetet); + } + } else { + // 'cavetet' is not on the cavity boundary anymore. + unmarktest(*cavetet); + } + } // i + + if (cutcount > 0) { + // The cavity has been updated. + // Update the cavity boundary faces. + cavebdrylist->restart(); + for (i = 0; i < cavetetlist->objects; i++) { + cavetet = (triface *) fastlookup(cavetetlist, i); + // 'cavetet' was an exterior tet adjacent to the cavity. + fsym(*cavetet, neightet); + if (infected(neightet)) { + // It is a cavity boundary face. + cavebdrylist->newindex((void **) &parytet); + *parytet = *cavetet; + } else { + // Not a cavity boundary face. + unmarktest(*cavetet); + } + } + + // Update the list of old tets. + cavetetlist->restart(); + for (i = 0; i < caveoldtetlist->objects; i++) { + cavetet = (triface *) fastlookup(caveoldtetlist, i); + if (infected(*cavetet)) { + cavetetlist->newindex((void **) &parytet); + *parytet = *cavetet; + } + } + // Swap 'cavetetlist' and 'caveoldtetlist'. + swaplist = caveoldtetlist; + caveoldtetlist = cavetetlist; + cavetetlist = swaplist; + + // The cavity should contain at least one tet. + if (caveoldtetlist->objects == 0l) { + insertpoint_abort(splitseg, ivf); + ivf->iloc = (int) BADELEMENT; + return 0; + } + + if (ivf->splitbdflag) { + int cutshcount = 0; + // Update the sub-cavity sC(p). + for (i = 0; i < caveshlist->objects; i++) { + parysh = (face *) fastlookup(caveshlist, i); + if (smarktested(*parysh)) { + enqflag = false; + stpivot(*parysh, neightet); + if (infected(neightet)) { + fsymself(neightet); + if (infected(neightet)) { + enqflag = true; + } + } + if (!enqflag) { + sunmarktest(*parysh); + // Use the last entry of this array to fill this entry. + j = caveshlist->objects - 1; + checksh = * (face *) fastlookup(caveshlist, j); + *parysh = checksh; + cutshcount++; + caveshlist->objects--; // The list is shrinked. + i--; + } + } + } + + if (cutshcount > 0) { + i = 0; // Count the number of invalid subfaces/segments. + // Valid the updated sub-cavity sC(p). + if (loc == ONFACE) { + if ((splitsh != NULL) && (splitsh->sh != NULL)) { + // The to-be split subface should be in sC(p). + if (!smarktested(*splitsh)) i++; + } + } else if (loc == ONEDGE) { + if ((splitseg != NULL) && (splitseg->sh != NULL)) { + // The to-be split segment should be in sC(p). + if (!smarktested(*splitseg)) i++; + } + if ((splitsh != NULL) && (splitsh->sh != NULL)) { + // All subfaces at this edge should be in sC(p). + pa = sorg(*splitsh); + neighsh = *splitsh; + while (1) { + // Adjust the origin of its edge to be 'pa'. + if (sorg(neighsh) != pa) { + sesymself(neighsh); + } + // Add this face into list (in B-W cavity). + if (!smarktested(neighsh)) i++; + // Go to the next face at the edge. + spivotself(neighsh); + // Stop if all faces at the edge have been visited. + if (neighsh.sh == splitsh->sh) break; + if (neighsh.sh == NULL) break; + } // while (1) + } + } + + if (i > 0) { + // The updated sC(p) is invalid. Do not insert this vertex. + insertpoint_abort(splitseg, ivf); + ivf->iloc = (int) BADELEMENT; + return 0; + } + } // if (cutshcount > 0) + } // if (ivf->splitbdflag) + } // if (cutcount > 0) + + } // if (ivf->validflag) + + if (ivf->refineflag) { + // The new point is inserted by Delaunay refinement, i.e., it is the + // circumcenter of a tetrahedron, or a subface, or a segment. + // Do not insert this point if the tetrahedron, or subface, or segment + // is not inside the final cavity. + if (((ivf->refineflag == 1) && !infected(ivf->refinetet)) || + ((ivf->refineflag == 2) && !smarktested(ivf->refinesh))) { + insertpoint_abort(splitseg, ivf); + ivf->iloc = (int) BADELEMENT; + return 0; + } + } // if (ivf->refineflag) + + if (b->plc && (loc != INSTAR)) { + // Reject the new point if it lies too close to an existing point (b->plc), + // or it lies inside a protecting ball of near vertex (ivf->rejflag & 4). + // Collect the list of vertices of the initial cavity. + if (loc == OUTSIDE) { + pts = (point *) &(searchtet->tet[4]); + for (i = 0; i < 3; i++) { + cavetetvertlist->newindex((void **) &parypt); + *parypt = pts[i]; + } + } else if (loc == INTETRAHEDRON) { + pts = (point *) &(searchtet->tet[4]); + for (i = 0; i < 4; i++) { + cavetetvertlist->newindex((void **) &parypt); + *parypt = pts[i]; + } + } else if (loc == ONFACE) { + pts = (point *) &(searchtet->tet[4]); + for (i = 0; i < 3; i++) { + cavetetvertlist->newindex((void **) &parypt); + *parypt = pts[i]; + } + if (pts[3] != dummypoint) { + cavetetvertlist->newindex((void **) &parypt); + *parypt = pts[3]; + } + fsym(*searchtet, spintet); + if (oppo(spintet) != dummypoint) { + cavetetvertlist->newindex((void **) &parypt); + *parypt = oppo(spintet); + } + } else if (loc == ONEDGE) { + spintet = *searchtet; + cavetetvertlist->newindex((void **) &parypt); + *parypt = org(spintet); + cavetetvertlist->newindex((void **) &parypt); + *parypt = dest(spintet); + while (1) { + if (apex(spintet) != dummypoint) { + cavetetvertlist->newindex((void **) &parypt); + *parypt = apex(spintet); + } + fnextself(spintet); + if (spintet.tet == searchtet->tet) break; + } + } + + int rejptflag = (ivf->rejflag & 4); + REAL rd; + pts = NULL; + + for (i = 0; i < cavetetvertlist->objects; i++) { + parypt = (point *) fastlookup(cavetetvertlist, i); + rd = distance(*parypt, insertpt); + // Is the point very close to an existing point? + if (rd < b->minedgelength) { + pts = parypt; + loc = NEARVERTEX; + break; + } + if (rejptflag) { + // Is the point encroaches upon an existing point? + if (rd < (0.5 * (*parypt)[pointmtrindex])) { + pts = parypt; + loc = ENCVERTEX; + break; + } + } + } + cavetetvertlist->restart(); // Clear the work list. + + if (pts != NULL) { + // The point is either too close to an existing vertex (NEARVERTEX) + // or encroaches upon (inside the protecting ball) of that vertex. + if (loc == NEARVERTEX) { + if (b->nomergevertex) { // -M0/1 option. + // In this case, we still insert this vertex. Although it is very + // close to an existing vertex. Give a warning, anyway. + if (!b->quiet) { + printf("Warning: Two points, %d and %d, are very close.\n", + pointmark(insertpt), pointmark(*pts)); + printf(" Creating a very short edge (len = %g) (< %g).\n", + rd, b->minedgelength); + printf(" You may try a smaller tolerance (-T) (current is %g)\n", + b->epsilon); + printf(" to avoid this warning.\n"); + } + } else { + insertpt[3] = rd; // Only for reporting. + setpoint2ppt(insertpt, *pts); + insertpoint_abort(splitseg, ivf); + ivf->iloc = (int) loc; + return 0; + } + } else { // loc == ENCVERTEX + // The point lies inside the protection ball. + setpoint2ppt(insertpt, *pts); + insertpoint_abort(splitseg, ivf); + ivf->iloc = (int) loc; + return 0; + } + } + } // if (b->plc && (loc != INSTAR)) + + if (b->weighted || ivf->cdtflag || ivf->smlenflag + ) { + // There may be other vertices inside C(p). We need to find them. + // Collect all vertices of C(p). + for (i = 0; i < caveoldtetlist->objects; i++) { + cavetet = (triface *) fastlookup(caveoldtetlist, i); + //assert(infected(*cavetet)); + pts = (point *) &(cavetet->tet[4]); + for (j = 0; j < 4; j++) { + if (pts[j] != dummypoint) { + if (!pinfected(pts[j])) { + pinfect(pts[j]); + cavetetvertlist->newindex((void **) &parypt); + *parypt = pts[j]; + } + } + } // j + } // i + // Uninfect all collected (cavity) vertices. + for (i = 0; i < cavetetvertlist->objects; i++) { + parypt = (point *) fastlookup(cavetetvertlist, i); + puninfect(*parypt); + } + if (ivf->smlenflag) { + REAL len; + // Get the length of the shortest edge connecting to 'newpt'. + parypt = (point *) fastlookup(cavetetvertlist, 0); + ivf->smlen = distance(*parypt, insertpt); + ivf->parentpt = *parypt; + for (i = 1; i < cavetetvertlist->objects; i++) { + parypt = (point *) fastlookup(cavetetvertlist, i); + len = distance(*parypt, insertpt); + if (len < ivf->smlen) { + ivf->smlen = len; + ivf->parentpt = *parypt; + } + } + } + } + + + if (ivf->cdtflag) { + // Unmark tets. + for (i = 0; i < caveoldtetlist->objects; i++) { + cavetet = (triface *) fastlookup(caveoldtetlist, i); + unmarktest(*cavetet); + } + for (i = 0; i < cavebdrylist->objects; i++) { + cavetet = (triface *) fastlookup(cavebdrylist, i); + unmarktest(*cavetet); + } + // Clean up arrays which are not needed. + cavetetlist->restart(); + if (checksubsegflag) { + cavetetseglist->restart(); + } + if (checksubfaceflag) { + cavetetshlist->restart(); + } + return 1; + } + + // Before re-mesh C(p). Process the segments and subfaces which are on the + // boundary of C(p). Make sure that each such segment or subface is + // connecting to a tet outside C(p). So we can re-connect them to the + // new tets inside the C(p) later. + + if (checksubsegflag) { + for (i = 0; i < cavetetseglist->objects; i++) { + paryseg = (face *) fastlookup(cavetetseglist, i); + // Operate on it if it is not the splitting segment, i.e., in sC(p). + if (!smarktested(*paryseg)) { + // Check if the segment is inside the cavity. + // 'j' counts the num of adjacent tets of this seg. + // 'k' counts the num of adjacent tets which are 'sinfected'. + j = k = 0; + sstpivot1(*paryseg, neightet); + spintet = neightet; + while (1) { + j++; + if (!infected(spintet)) { + neineitet = spintet; // An outer tet. Remember it. + } else { + k++; // An in tet. + } + fnextself(spintet); + if (spintet.tet == neightet.tet) break; + } + // assert(j > 0); + if (k == 0) { + // The segment is not connect to C(p) anymore. Remove it by + // Replacing it by the last entry of this list. + s = cavetetseglist->objects - 1; + checkseg = * (face *) fastlookup(cavetetseglist, s); + *paryseg = checkseg; + cavetetseglist->objects--; + i--; + } else if (k < j) { + // The segment is on the boundary of C(p). + sstbond1(*paryseg, neineitet); + } else { // k == j + // The segment is inside C(p). + if (!ivf->splitbdflag) { + checkseg = *paryseg; + sinfect(checkseg); // Flag it as an interior segment. + caveencseglist->newindex((void **) &paryseg); + *paryseg = checkseg; + } else { + assert(0); // Not possible. + } + } + } else { + // assert(smarktested(*paryseg)); + // Flag it as an interior segment. Do not queue it, since it will + // be deleted after the segment splitting. + sinfect(*paryseg); + } + } // i + } // if (checksubsegflag) + + if (checksubfaceflag) { + for (i = 0; i < cavetetshlist->objects; i++) { + parysh = (face *) fastlookup(cavetetshlist, i); + // Operate on it if it is not inside the sub-cavity sC(p). + if (!smarktested(*parysh)) { + // Check if this subface is inside the cavity. + k = 0; + for (j = 0; j < 2; j++) { + stpivot(*parysh, neightet); + if (!infected(neightet)) { + checksh = *parysh; // Remember this side. + } else { + k++; + } + sesymself(*parysh); + } + if (k == 0) { + // The subface is not connected to C(p). Remove it. + s = cavetetshlist->objects - 1; + checksh = * (face *) fastlookup(cavetetshlist, s); + *parysh = checksh; + cavetetshlist->objects--; + i--; + } else if (k == 1) { + // This side is the outer boundary of C(p). + *parysh = checksh; + } else { // k == 2 + if (!ivf->splitbdflag) { + checksh = *parysh; + sinfect(checksh); // Flag it. + caveencshlist->newindex((void **) &parysh); + *parysh = checksh; + } else { + assert(0); // Not possible. + } + } + } else { + // assert(smarktested(*parysh)); + // Flag it as an interior subface. Do not queue it. It will be + // deleted after the facet point insertion. + sinfect(*parysh); + } + } // i + } // if (checksubfaceflag) + + // Create new tetrahedra to fill the cavity. + + for (i = 0; i < cavebdrylist->objects; i++) { + cavetet = (triface *) fastlookup(cavebdrylist, i); + neightet = *cavetet; + unmarktest(neightet); // Unmark it. + // Get the oldtet (inside the cavity). + fsym(neightet, oldtet); + if (apex(neightet) != dummypoint) { + // Create a new tet in the cavity. + maketetrahedron(&newtet); + setorg(newtet, dest(neightet)); + setdest(newtet, org(neightet)); + setapex(newtet, apex(neightet)); + setoppo(newtet, insertpt); + } else { + // Create a new hull tet. + hullsize++; + maketetrahedron(&newtet); + setorg(newtet, org(neightet)); + setdest(newtet, dest(neightet)); + setapex(newtet, insertpt); + setoppo(newtet, dummypoint); // It must opposite to face 3. + // Adjust back to the cavity bounday face. + esymself(newtet); + } + // The new tet inherits attribtes from the old tet. + for (j = 0; j < numelemattrib; j++) { + attrib = elemattribute(oldtet.tet, j); + setelemattribute(newtet.tet, j, attrib); + } + if (b->varvolume) { + volume = volumebound(oldtet.tet); + setvolumebound(newtet.tet, volume); + } + // Connect newtet <==> neightet, this also disconnect the old bond. + bond(newtet, neightet); + // oldtet still connects to neightet. + *cavetet = oldtet; // *cavetet = newtet; + } // i + + // Set a handle for speeding point location. + recenttet = newtet; + //setpoint2tet(insertpt, encode(newtet)); + setpoint2tet(insertpt, (tetrahedron) (newtet.tet)); + + // Re-use this list to save new interior cavity faces. + cavetetlist->restart(); + + // Connect adjacent new tetrahedra together. + for (i = 0; i < cavebdrylist->objects; i++) { + cavetet = (triface *) fastlookup(cavebdrylist, i); + // cavtet is an oldtet, get the newtet at this face. + oldtet = *cavetet; + fsym(oldtet, neightet); + fsym(neightet, newtet); + // Comment: oldtet and newtet must be at the same directed edge. + // Connect the three other faces of this newtet. + for (j = 0; j < 3; j++) { + esym(newtet, neightet); // Go to the face. + if (neightet.tet[neightet.ver & 3] == NULL) { + // Find the adjacent face of this newtet. + spintet = oldtet; + while (1) { + fnextself(spintet); + if (!infected(spintet)) break; + } + fsym(spintet, newneitet); + esymself(newneitet); + assert(newneitet.tet[newneitet.ver & 3] == NULL); + bond(neightet, newneitet); + if (ivf->lawson > 1) { + cavetetlist->newindex((void **) &parytet); + *parytet = neightet; + } + } + //setpoint2tet(org(newtet), encode(newtet)); + setpoint2tet(org(newtet), (tetrahedron) (newtet.tet)); + enextself(newtet); + enextself(oldtet); + } + *cavetet = newtet; // Save the new tet. + } // i + + if (checksubfaceflag) { + // Connect subfaces on the boundary of the cavity to the new tets. + for (i = 0; i < cavetetshlist->objects; i++) { + parysh = (face *) fastlookup(cavetetshlist, i); + // Connect it if it is not a missing subface. + if (!sinfected(*parysh)) { + stpivot(*parysh, neightet); + fsym(neightet, spintet); + sesymself(*parysh); + tsbond(spintet, *parysh); + } + } + } + + if (checksubsegflag) { + // Connect segments on the boundary of the cavity to the new tets. + for (i = 0; i < cavetetseglist->objects; i++) { + paryseg = (face *) fastlookup(cavetetseglist, i); + // Connect it if it is not a missing segment. + if (!sinfected(*paryseg)) { + sstpivot1(*paryseg, neightet); + spintet = neightet; + while (1) { + tssbond1(spintet, *paryseg); + fnextself(spintet); + if (spintet.tet == neightet.tet) break; + } + } + } + } + + if (((splitsh != NULL) && (splitsh->sh != NULL)) || + ((splitseg != NULL) && (splitseg->sh != NULL))) { + // Split a subface or a segment. + sinsertvertex(insertpt, splitsh, splitseg, ivf->sloc, ivf->sbowywat, 0); + } + + if (checksubfaceflag) { + if (ivf->splitbdflag) { + // Recover new subfaces in C(p). + for (i = 0; i < caveshbdlist->objects; i++) { + // Get an old subface at edge [a, b]. + parysh = (face *) fastlookup(caveshbdlist, i); + spivot(*parysh, checksh); // The new subface [a, b, p]. + // Do not recover a deleted new face (degenerated). + if (checksh.sh[3] != NULL) { + // Note that the old subface still connects to adjacent old tets + // of C(p), which still connect to the tets outside C(p). + stpivot(*parysh, neightet); + assert(infected(neightet)); + // Find the adjacent tet containing the edge [a,b] outside C(p). + spintet = neightet; + while (1) { + fnextself(spintet); + if (!infected(spintet)) break; + assert(spintet.tet != neightet.tet); + } + // The adjacent tet connects to a new tet in C(p). + fsym(spintet, neightet); + assert(!infected(neightet)); + // Find the tet containing the face [a, b, p]. + spintet = neightet; + while (1) { + fnextself(spintet); + if (apex(spintet) == insertpt) break; + assert(spintet.tet != neightet.tet); + } + // Adjust the edge direction in spintet and checksh. + if (sorg(checksh) != org(spintet)) { + sesymself(checksh); + assert(sorg(checksh) == org(spintet)); + } + assert(sdest(checksh) == dest(spintet)); + // Connect the subface to two adjacent tets. + tsbond(spintet, checksh); + fsymself(spintet); + sesymself(checksh); + tsbond(spintet, checksh); + } // if (checksh.sh[3] != NULL) + } + // There should be no missing interior subfaces in C(p). + assert(caveencshlist->objects == 0l); + } else { + // The Boundary recovery phase. + // Put all new subfaces into stack for recovery. + for (i = 0; i < caveshbdlist->objects; i++) { + // Get an old subface at edge [a, b]. + parysh = (face *) fastlookup(caveshbdlist, i); + spivot(*parysh, checksh); // The new subface [a, b, p]. + // Do not recover a deleted new face (degenerated). + if (checksh.sh[3] != NULL) { + subfacstack->newindex((void **) &parysh); + *parysh = checksh; + } + } + // Put all interior subfaces into stack for recovery. + for (i = 0; i < caveencshlist->objects; i++) { + parysh = (face *) fastlookup(caveencshlist, i); + assert(sinfected(*parysh)); + // Some subfaces inside C(p) might be split in sinsertvertex(). + // Only queue those faces which are not split. + if (!smarktested(*parysh)) { + checksh = *parysh; + suninfect(checksh); + stdissolve(checksh); // Detach connections to old tets. + subfacstack->newindex((void **) &parysh); + *parysh = checksh; + } + } + } + } // if (checksubfaceflag) + + if (checksubsegflag) { + if (ivf->splitbdflag) { + if (splitseg != NULL) { + // Recover the two new subsegments in C(p). + for (i = 0; i < cavesegshlist->objects; i++) { + paryseg = (face *) fastlookup(cavesegshlist, i); + // Insert this subsegment into C(p). + checkseg = *paryseg; + // Get the adjacent new subface. + checkseg.shver = 0; + spivot(checkseg, checksh); + if (checksh.sh != NULL) { + // Get the adjacent new tetrahedron. + stpivot(checksh, neightet); + } else { + // It's a dangling segment. + point2tetorg(sorg(checkseg), neightet); + finddirection(&neightet, sdest(checkseg)); + assert(dest(neightet) == sdest(checkseg)); + } + assert(!infected(neightet)); + sstbond1(checkseg, neightet); + spintet = neightet; + while (1) { + tssbond1(spintet, checkseg); + fnextself(spintet); + if (spintet.tet == neightet.tet) break; + } + } + } // if (splitseg != NULL) + // There should be no interior segment in C(p). + assert(caveencseglist->objects == 0l); + } else { + // The Boundary Recovery Phase. + // Queue missing segments in C(p) for recovery. + if (splitseg != NULL) { + // Queue two new subsegments in C(p) for recovery. + for (i = 0; i < cavesegshlist->objects; i++) { + paryseg = (face *) fastlookup(cavesegshlist, i); + checkseg = *paryseg; + //sstdissolve1(checkseg); // It has not been connected yet. + s = randomnation(subsegstack->objects + 1); + subsegstack->newindex((void **) &paryseg); + *paryseg = * (face *) fastlookup(subsegstack, s); + paryseg = (face *) fastlookup(subsegstack, s); + *paryseg = checkseg; + } + } // if (splitseg != NULL) + for (i = 0; i < caveencseglist->objects; i++) { + paryseg = (face *) fastlookup(caveencseglist, i); + assert(sinfected(*paryseg)); + if (!smarktested(*paryseg)) { // It may be split. + checkseg = *paryseg; + suninfect(checkseg); + sstdissolve1(checkseg); // Detach connections to old tets. + s = randomnation(subsegstack->objects + 1); + subsegstack->newindex((void **) &paryseg); + *paryseg = * (face *) fastlookup(subsegstack, s); + paryseg = (face *) fastlookup(subsegstack, s); + *paryseg = checkseg; + } + } + } + } // if (checksubsegflag) + + if (b->weighted + ) { + // Some vertices may be completed inside the cavity. They must be + // detected and added to recovering list. + // Since every "live" vertex must contain a pointer to a non-dead + // tetrahedron, we can check for each vertex this pointer. + for (i = 0; i < cavetetvertlist->objects; i++) { + pts = (point *) fastlookup(cavetetvertlist, i); + decode(point2tet(*pts), *searchtet); + assert(searchtet->tet != NULL); // No tet has been deleted yet. + if (infected(*searchtet)) { + if (b->weighted) { + if (b->verbose > 1) { + printf(" Point #%d is non-regular after the insertion of #%d.\n", + pointmark(*pts), pointmark(insertpt)); + } + setpointtype(*pts, NREGULARVERTEX); + nonregularcount++; + } + } + } + } + + if (ivf->chkencflag & 1) { + // Queue all segment outside C(p). + for (i = 0; i < cavetetseglist->objects; i++) { + paryseg = (face *) fastlookup(cavetetseglist, i); + // Skip if it is the split segment. + if (!sinfected(*paryseg)) { + enqueuesubface(badsubsegs, paryseg); + } + } + if (splitseg != NULL) { + // Queue the two new subsegments inside C(p). + for (i = 0; i < cavesegshlist->objects; i++) { + paryseg = (face *) fastlookup(cavesegshlist, i); + enqueuesubface(badsubsegs, paryseg); + } + } + } // if (chkencflag & 1) + + if (ivf->chkencflag & 2) { + // Queue all subfaces outside C(p). + for (i = 0; i < cavetetshlist->objects; i++) { + parysh = (face *) fastlookup(cavetetshlist, i); + // Skip if it is a split subface. + if (!sinfected(*parysh)) { + enqueuesubface(badsubfacs, parysh); + } + } + // Queue all new subfaces inside C(p). + for (i = 0; i < caveshbdlist->objects; i++) { + // Get an old subface at edge [a, b]. + parysh = (face *) fastlookup(caveshbdlist, i); + spivot(*parysh, checksh); // checksh is a new subface [a, b, p]. + // Do not recover a deleted new face (degenerated). + if (checksh.sh[3] != NULL) { + enqueuesubface(badsubfacs, &checksh); + } + } + } // if (chkencflag & 2) + + if (ivf->chkencflag & 4) { + // Queue all new tetrahedra in C(p). + for (i = 0; i < cavebdrylist->objects; i++) { + cavetet = (triface *) fastlookup(cavebdrylist, i); + enqueuetetrahedron(cavetet); + } + } + + // C(p) is re-meshed successfully. + + // Delete the old tets in C(p). + for (i = 0; i < caveoldtetlist->objects; i++) { + searchtet = (triface *) fastlookup(caveoldtetlist, i); + if (ishulltet(*searchtet)) { + hullsize--; + } + tetrahedrondealloc(searchtet->tet); + } + + if (((splitsh != NULL) && (splitsh->sh != NULL)) || + ((splitseg != NULL) && (splitseg->sh != NULL))) { + // Delete the old subfaces in sC(p). + for (i = 0; i < caveshlist->objects; i++) { + parysh = (face *) fastlookup(caveshlist, i); + if (checksubfaceflag) {//if (bowywat == 2) { + // It is possible that this subface still connects to adjacent + // tets which are not in C(p). If so, clear connections in the + // adjacent tets at this subface. + stpivot(*parysh, neightet); + if (neightet.tet != NULL) { + if (neightet.tet[4] != NULL) { + // Found an adjacent tet. It must be not in C(p). + assert(!infected(neightet)); + tsdissolve(neightet); + fsymself(neightet); + assert(!infected(neightet)); + tsdissolve(neightet); + } + } + } + shellfacedealloc(subfaces, parysh->sh); + } + if ((splitseg != NULL) && (splitseg->sh != NULL)) { + // Delete the old segment in sC(p). + shellfacedealloc(subsegs, splitseg->sh); + } + } + + if (ivf->lawson) { + for (i = 0; i < cavebdrylist->objects; i++) { + searchtet = (triface *) fastlookup(cavebdrylist, i); + flippush(flipstack, searchtet); + } + if (ivf->lawson > 1) { + for (i = 0; i < cavetetlist->objects; i++) { + searchtet = (triface *) fastlookup(cavetetlist, i); + flippush(flipstack, searchtet); + } + } + } + + + // Clean the working lists. + + caveoldtetlist->restart(); + cavebdrylist->restart(); + cavetetlist->restart(); + + if (checksubsegflag) { + cavetetseglist->restart(); + caveencseglist->restart(); + } + + if (checksubfaceflag) { + cavetetshlist->restart(); + caveencshlist->restart(); + } + + if (b->weighted || ivf->validflag) { + cavetetvertlist->restart(); + } + + if (((splitsh != NULL) && (splitsh->sh != NULL)) || + ((splitseg != NULL) && (splitseg->sh != NULL))) { + caveshlist->restart(); + caveshbdlist->restart(); + cavesegshlist->restart(); + } + + return 1; // Point is inserted. +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// insertpoint_abort() Abort the insertion of a new vertex. // +// // +// The cavity will be restored. All working lists are cleared. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::insertpoint_abort(face *splitseg, insertvertexflags *ivf) +{ + triface *cavetet; + face *parysh; + int i; + + for (i = 0; i < caveoldtetlist->objects; i++) { + cavetet = (triface *) fastlookup(caveoldtetlist, i); + uninfect(*cavetet); + unmarktest(*cavetet); + } + for (i = 0; i < cavebdrylist->objects; i++) { + cavetet = (triface *) fastlookup(cavebdrylist, i); + unmarktest(*cavetet); + } + cavetetlist->restart(); + cavebdrylist->restart(); + caveoldtetlist->restart(); + cavetetseglist->restart(); + cavetetshlist->restart(); + if (ivf->splitbdflag) { + if ((splitseg != NULL) && (splitseg->sh != NULL)) { + sunmarktest(*splitseg); + } + for (i = 0; i < caveshlist->objects; i++) { + parysh = (face *) fastlookup(caveshlist, i); + assert(smarktested(*parysh)); + sunmarktest(*parysh); + } + caveshlist->restart(); + cavesegshlist->restart(); + } +} + +//// //// +//// //// +//// flip_cxx ///////////////////////////////////////////////////////////////// + +//// delaunay_cxx ///////////////////////////////////////////////////////////// +//// //// +//// //// + +/////////////////////////////////////////////////////////////////////////////// +// // +// transfernodes() Read the vertices from the input (tetgenio). // +// // +// Transferring all points from input ('in->pointlist') to TetGen's 'points'.// +// All points are indexed (the first point index is 'in->firstnumber'). Each // +// point's type is initialized as UNUSEDVERTEX. The bounding box (xmax, xmin,// +// ...) and the diameter (longest) of the point set are calculated. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::transfernodes() +{ + point pointloop; + REAL x, y, z, w; + int coordindex; + int attribindex; + int mtrindex; + int i, j; + + if (b->psc) { + assert(in->pointparamlist != NULL); + } + + // Read the points. + coordindex = 0; + attribindex = 0; + mtrindex = 0; + for (i = 0; i < in->numberofpoints; i++) { + makepoint(&pointloop, UNUSEDVERTEX); + // Read the point coordinates. + x = pointloop[0] = in->pointlist[coordindex++]; + y = pointloop[1] = in->pointlist[coordindex++]; + z = pointloop[2] = in->pointlist[coordindex++]; + // Read the point attributes. (Including point weights.) + for (j = 0; j < in->numberofpointattributes; j++) { + pointloop[3 + j] = in->pointattributelist[attribindex++]; + } + // Read the point metric tensor. + for (j = 0; j < in->numberofpointmtrs; j++) { + pointloop[pointmtrindex + j] = in->pointmtrlist[mtrindex++]; + } + if (b->weighted) { // -w option + if (in->numberofpointattributes > 0) { + // The first point attribute is its weight. + //w = in->pointattributelist[in->numberofpointattributes * i]; + w = pointloop[3]; + } else { + // No given weight available. Default choose the maximum + // absolute value among its coordinates. + w = fabs(x); + if (w < fabs(y)) w = fabs(y); + if (w < fabs(z)) w = fabs(z); + } + if (b->weighted_param == 0) { + pointloop[3] = x * x + y * y + z * z - w; // Weighted DT. + } else { // -w1 option + pointloop[3] = w; // Regular tetrahedralization. + } + } + // Determine the smallest and largest x, y and z coordinates. + if (i == 0) { + xmin = xmax = x; + ymin = ymax = y; + zmin = zmax = z; + } else { + xmin = (x < xmin) ? x : xmin; + xmax = (x > xmax) ? x : xmax; + ymin = (y < ymin) ? y : ymin; + ymax = (y > ymax) ? y : ymax; + zmin = (z < zmin) ? z : zmin; + zmax = (z > zmax) ? z : zmax; + } + if (b->psc) { + // Read the geometry parameters. + setpointgeomuv(pointloop, 0, in->pointparamlist[i].uv[0]); + setpointgeomuv(pointloop, 1, in->pointparamlist[i].uv[1]); + setpointgeomtag(pointloop, in->pointparamlist[i].tag); + if (in->pointparamlist[i].type == 0) { + setpointtype(pointloop, RIDGEVERTEX); + } else if (in->pointparamlist[i].type == 1) { + setpointtype(pointloop, FREESEGVERTEX); + } else if (in->pointparamlist[i].type == 2) { + setpointtype(pointloop, FREEFACETVERTEX); + } else if (in->pointparamlist[i].type == 3) { + setpointtype(pointloop, FREEVOLVERTEX); + } + } + } + + // 'longest' is the largest possible edge length formed by input vertices. + x = xmax - xmin; + y = ymax - ymin; + z = zmax - zmin; + longest = sqrt(x * x + y * y + z * z); + if (longest == 0.0) { + printf("Error: The point set is trivial.\n"); + terminatetetgen(this, 3); + } + + // Two identical points are distinguished by 'lengthlimit'. + if (b->minedgelength == 0.0) { + b->minedgelength = longest * b->epsilon; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// hilbert_init() Initialize the Gray code permutation table. // +// // +// The table 'transgc' has 8 x 3 x 8 entries. It contains all possible Gray // +// code sequences traveled by the 1st order Hilbert curve in 3 dimensions. // +// The first column is the Gray code of the entry point of the curve, and // +// the second column is the direction (0, 1, or 2, 0 means the x-axis) where // +// the exit point of curve lies. // +// // +// The table 'tsb1mod3' contains the numbers of trailing set '1' bits of the // +// indices from 0 to 7, modulo by '3'. The code for generating this table is // +// from: http://graphics.stanford.edu/~seander/bithacks.html. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::hilbert_init(int n) +{ + int gc[8], N, mask, travel_bit; + int e, d, f, k, g; + int v, c; + int i; + + N = (n == 2) ? 4 : 8; + mask = (n == 2) ? 3 : 7; + + // Generate the Gray code sequence. + for (i = 0; i < N; i++) { + gc[i] = i ^ (i >> 1); + } + + for (e = 0; e < N; e++) { + for (d = 0; d < n; d++) { + // Calculate the end point (f). + f = e ^ (1 << d); // Toggle the d-th bit of 'e'. + // travel_bit = 2**p, the bit we want to travel. + travel_bit = e ^ f; + for (i = 0; i < N; i++) { + // // Rotate gc[i] left by (p + 1) % n bits. + k = gc[i] * (travel_bit * 2); + g = ((k | (k / N)) & mask); + // Calculate the permuted Gray code by xor with the start point (e). + transgc[e][d][i] = (g ^ e); + } + assert(transgc[e][d][0] == e); + assert(transgc[e][d][N - 1] == f); + } // d + } // e + + // Count the consecutive '1' bits (trailing) on the right. + tsb1mod3[0] = 0; + for (i = 1; i < N; i++) { + v = ~i; // Count the 0s. + v = (v ^ (v - 1)) >> 1; // Set v's trailing 0s to 1s and zero rest + for (c = 0; v; c++) { + v >>= 1; + } + tsb1mod3[i] = c % n; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// hilbert_sort3() Sort points using the 3d Hilbert curve. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::hilbert_split(point* vertexarray,int arraysize,int gc0,int gc1, + REAL bxmin, REAL bxmax, REAL bymin, REAL bymax, + REAL bzmin, REAL bzmax) +{ + point swapvert; + int axis, d; + REAL split; + int i, j; + + + // Find the current splitting axis. 'axis' is a value 0, or 1, or 2, which + // correspoding to x-, or y- or z-axis. + axis = (gc0 ^ gc1) >> 1; + + // Calulate the split position along the axis. + if (axis == 0) { + split = 0.5 * (bxmin + bxmax); + } else if (axis == 1) { + split = 0.5 * (bymin + bymax); + } else { // == 2 + split = 0.5 * (bzmin + bzmax); + } + + // Find the direction (+1 or -1) of the axis. If 'd' is +1, the direction + // of the axis is to the positive of the axis, otherwise, it is -1. + d = ((gc0 & (1< 0) { + do { + for (; i < arraysize; i++) { + if (vertexarray[i][axis] >= split) break; + } + for (; j >= 0; j--) { + if (vertexarray[j][axis] < split) break; + } + // Is the partition finished? + if (i == (j + 1)) break; + // Swap i-th and j-th vertices. + swapvert = vertexarray[i]; + vertexarray[i] = vertexarray[j]; + vertexarray[j] = swapvert; + // Continue patitioning the array; + } while (true); + } else { + do { + for (; i < arraysize; i++) { + if (vertexarray[i][axis] <= split) break; + } + for (; j >= 0; j--) { + if (vertexarray[j][axis] > split) break; + } + // Is the partition finished? + if (i == (j + 1)) break; + // Swap i-th and j-th vertices. + swapvert = vertexarray[i]; + vertexarray[i] = vertexarray[j]; + vertexarray[j] = swapvert; + // Continue patitioning the array; + } while (true); + } + + return i; +} + +void tetgenmesh::hilbert_sort3(point* vertexarray, int arraysize, int e, int d, + REAL bxmin, REAL bxmax, REAL bymin, REAL bymax, + REAL bzmin, REAL bzmax, int depth) +{ + REAL x1, x2, y1, y2, z1, z2; + int p[9], w, e_w, d_w, k, ei, di; + int n = 3, mask = 7; + + p[0] = 0; + p[8] = arraysize; + + // Sort the points according to the 1st order Hilbert curve in 3d. + p[4] = hilbert_split(vertexarray, p[8], transgc[e][d][3], transgc[e][d][4], + bxmin, bxmax, bymin, bymax, bzmin, bzmax); + p[2] = hilbert_split(vertexarray, p[4], transgc[e][d][1], transgc[e][d][2], + bxmin, bxmax, bymin, bymax, bzmin, bzmax); + p[1] = hilbert_split(vertexarray, p[2], transgc[e][d][0], transgc[e][d][1], + bxmin, bxmax, bymin, bymax, bzmin, bzmax); + p[3] = hilbert_split(&(vertexarray[p[2]]), p[4] - p[2], + transgc[e][d][2], transgc[e][d][3], + bxmin, bxmax, bymin, bymax, bzmin, bzmax) + p[2]; + p[6] = hilbert_split(&(vertexarray[p[4]]), p[8] - p[4], + transgc[e][d][5], transgc[e][d][6], + bxmin, bxmax, bymin, bymax, bzmin, bzmax) + p[4]; + p[5] = hilbert_split(&(vertexarray[p[4]]), p[6] - p[4], + transgc[e][d][4], transgc[e][d][5], + bxmin, bxmax, bymin, bymax, bzmin, bzmax) + p[4]; + p[7] = hilbert_split(&(vertexarray[p[6]]), p[8] - p[6], + transgc[e][d][6], transgc[e][d][7], + bxmin, bxmax, bymin, bymax, bzmin, bzmax) + p[6]; + + if (b->hilbert_order > 0) { + // A maximum order is prescribed. + if ((depth + 1) == b->hilbert_order) { + // The maximum prescribed order is reached. + return; + } + } + + // Recursively sort the points in sub-boxes. + for (w = 0; w < 8; w++) { + // w is the local Hilbert index (NOT Gray code). + // Sort into the sub-box either there are more than 2 points in it, or + // the prescribed order of the curve is not reached yet. + //if ((p[w+1] - p[w] > b->hilbert_limit) || (b->hilbert_order > 0)) { + if ((p[w+1] - p[w]) > b->hilbert_limit) { + // Calculcate the start point (ei) of the curve in this sub-box. + // update e = e ^ (e(w) left_rotate (d+1)). + if (w == 0) { + e_w = 0; + } else { + // calculate e(w) = gc(2 * floor((w - 1) / 2)). + k = 2 * ((w - 1) / 2); + e_w = k ^ (k >> 1); // = gc(k). + } + k = e_w; + e_w = ((k << (d+1)) & mask) | ((k >> (n-d-1)) & mask); + ei = e ^ e_w; + // Calulcate the direction (di) of the curve in this sub-box. + // update d = (d + d(w) + 1) % n + if (w == 0) { + d_w = 0; + } else { + d_w = ((w % 2) == 0) ? tsb1mod3[w - 1] : tsb1mod3[w]; + } + di = (d + d_w + 1) % n; + // Calculate the bounding box of the sub-box. + if (transgc[e][d][w] & 1) { // x-axis + x1 = 0.5 * (bxmin + bxmax); + x2 = bxmax; + } else { + x1 = bxmin; + x2 = 0.5 * (bxmin + bxmax); + } + if (transgc[e][d][w] & 2) { // y-axis + y1 = 0.5 * (bymin + bymax); + y2 = bymax; + } else { + y1 = bymin; + y2 = 0.5 * (bymin + bymax); + } + if (transgc[e][d][w] & 4) { // z-axis + z1 = 0.5 * (bzmin + bzmax); + z2 = bzmax; + } else { + z1 = bzmin; + z2 = 0.5 * (bzmin + bzmax); + } + hilbert_sort3(&(vertexarray[p[w]]), p[w+1] - p[w], ei, di, + x1, x2, y1, y2, z1, z2, depth+1); + } // if (p[w+1] - p[w] > 1) + } // w +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// brio_multiscale_sort() Sort the points using BRIO and Hilbert curve. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::brio_multiscale_sort(point* vertexarray, int arraysize, + int threshold, REAL ratio, int *depth) +{ + int middle; + + middle = 0; + if (arraysize >= threshold) { + (*depth)++; + middle = arraysize * ratio; + brio_multiscale_sort(vertexarray, middle, threshold, ratio, depth); + } + // Sort the right-array (rnd-th round) using the Hilbert curve. + hilbert_sort3(&(vertexarray[middle]), arraysize - middle, 0, 0, // e, d + xmin, xmax, ymin, ymax, zmin, zmax, 0); // depth. +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// randomnation() Generate a random number between 0 and 'choices' - 1. // +// // +/////////////////////////////////////////////////////////////////////////////// + +unsigned long tetgenmesh::randomnation(unsigned int choices) +{ + unsigned long newrandom; + + if (choices >= 714025l) { + newrandom = (randomseed * 1366l + 150889l) % 714025l; + randomseed = (newrandom * 1366l + 150889l) % 714025l; + newrandom = newrandom * (choices / 714025l) + randomseed; + if (newrandom >= choices) { + return newrandom - choices; + } else { + return newrandom; + } + } else { + randomseed = (randomseed * 1366l + 150889l) % 714025l; + return randomseed % choices; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// randomsample() Randomly sample the tetrahedra for point loation. // +// // +// Searching begins from one of handles: the input 'searchtet', a recently // +// encountered tetrahedron 'recenttet', or from one chosen from a random // +// sample. The choice is made by determining which one's origin is closest // +// to the point we are searching for. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::randomsample(point searchpt,triface *searchtet) +{ + tetrahedron *firsttet, *tetptr; + point torg; + void **sampleblock; + uintptr_t alignptr; + long sampleblocks, samplesperblock, samplenum; + long tetblocks, i, j; + REAL searchdist, dist; + + if (b->verbose > 2) { + printf(" Random sampling tetrahedra for searching point %d.\n", + pointmark(searchpt)); + } + + if (!nonconvex) { + if (searchtet->tet == NULL) { + // A null tet. Choose the recenttet as the starting tet. + *searchtet = recenttet; + // Recenttet should not be dead. + assert(recenttet.tet[4] != NULL); + } + + // 'searchtet' should be a valid tetrahedron. Choose the base face + // whose vertices must not be 'dummypoint'. + searchtet->ver = 3; + // Record the distance from its origin to the searching point. + torg = org(*searchtet); + searchdist = (searchpt[0] - torg[0]) * (searchpt[0] - torg[0]) + + (searchpt[1] - torg[1]) * (searchpt[1] - torg[1]) + + (searchpt[2] - torg[2]) * (searchpt[2] - torg[2]); + + // If a recently encountered tetrahedron has been recorded and has not + // been deallocated, test it as a good starting point. + if (recenttet.tet != searchtet->tet) { + recenttet.ver = 3; + torg = org(recenttet); + dist = (searchpt[0] - torg[0]) * (searchpt[0] - torg[0]) + + (searchpt[1] - torg[1]) * (searchpt[1] - torg[1]) + + (searchpt[2] - torg[2]) * (searchpt[2] - torg[2]); + if (dist < searchdist) { + *searchtet = recenttet; + searchdist = dist; + } + } + } else { + // The mesh is non-convex. Do not use 'recenttet'. + assert(samples >= 1l); // Make sure at least 1 sample. + searchdist = longest; + } + + // Select "good" candidate using k random samples, taking the closest one. + // The number of random samples taken is proportional to the fourth root + // of the number of tetrahedra in the mesh. + while (samples * samples * samples * samples < tetrahedrons->items) { + samples++; + } + // Find how much blocks in current tet pool. + tetblocks = (tetrahedrons->maxitems + b->tetrahedraperblock - 1) + / b->tetrahedraperblock; + // Find the average samples per block. Each block at least have 1 sample. + samplesperblock = 1 + (samples / tetblocks); + sampleblocks = samples / samplesperblock; + sampleblock = tetrahedrons->firstblock; + for (i = 0; i < sampleblocks; i++) { + alignptr = (uintptr_t) (sampleblock + 1); + firsttet = (tetrahedron *) + (alignptr + (uintptr_t) tetrahedrons->alignbytes + - (alignptr % (uintptr_t) tetrahedrons->alignbytes)); + for (j = 0; j < samplesperblock; j++) { + if (i == tetblocks - 1) { + // This is the last block. + samplenum = randomnation((int) + (tetrahedrons->maxitems - (i * b->tetrahedraperblock))); + } else { + samplenum = randomnation(b->tetrahedraperblock); + } + tetptr = (tetrahedron *) + (firsttet + (samplenum * tetrahedrons->itemwords)); + torg = (point) tetptr[4]; + if (torg != (point) NULL) { + dist = (searchpt[0] - torg[0]) * (searchpt[0] - torg[0]) + + (searchpt[1] - torg[1]) * (searchpt[1] - torg[1]) + + (searchpt[2] - torg[2]) * (searchpt[2] - torg[2]); + if (dist < searchdist) { + searchtet->tet = tetptr; + searchtet->ver = 11; // torg = org(t); + searchdist = dist; + } + } else { + // A dead tet. Re-sample it. + if (i != tetblocks - 1) j--; + } + } + sampleblock = (void **) *sampleblock; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// locate() Find a tetrahedron containing a given point. // +// // +// Begins its search from 'searchtet', assume there is a line segment L from // +// a vertex of 'searchtet' to the query point 'searchpt', and simply walk // +// towards 'searchpt' by traversing all faces intersected by L. // +// // +// On completion, 'searchtet' is a tetrahedron that contains 'searchpt'. The // +// returned value indicates one of the following cases: // +// - ONVERTEX, the search point lies on the origin of 'searchtet'. // +// - ONEDGE, the search point lies on an edge of 'searchtet'. // +// - ONFACE, the search point lies on a face of 'searchtet'. // +// - INTET, the search point lies in the interior of 'searchtet'. // +// - OUTSIDE, the search point lies outside the mesh. 'searchtet' is a // +// hull face which is visible by the search point. // +// // +// WARNING: This routine is designed for convex triangulations, and will not // +// generally work after the holes and concavities have been carved. // +// // +/////////////////////////////////////////////////////////////////////////////// + +enum tetgenmesh::locateresult tetgenmesh::locate(point searchpt, + triface* searchtet) +{ + point torg, tdest, tapex, toppo; + enum {ORGMOVE, DESTMOVE, APEXMOVE} nextmove; + REAL ori, oriorg, oridest, oriapex; + enum locateresult loc = OUTSIDE; + int t1ver; + int s; + + if (searchtet->tet == NULL) { + // A null tet. Choose the recenttet as the starting tet. + searchtet->tet = recenttet.tet; + } + + // Check if we are in the outside of the convex hull. + if (ishulltet(*searchtet)) { + // Get its adjacent tet (inside the hull). + searchtet->ver = 3; + fsymself(*searchtet); + } + + // Let searchtet be the face such that 'searchpt' lies above to it. + for (searchtet->ver = 0; searchtet->ver < 4; searchtet->ver++) { + torg = org(*searchtet); + tdest = dest(*searchtet); + tapex = apex(*searchtet); + ori = orient3d(torg, tdest, tapex, searchpt); + if (ori < 0.0) break; + } + assert(searchtet->ver != 4); + + // Walk through tetrahedra to locate the point. + while (true) { + + toppo = oppo(*searchtet); + + // Check if the vertex is we seek. + if (toppo == searchpt) { + // Adjust the origin of searchtet to be searchpt. + esymself(*searchtet); + eprevself(*searchtet); + loc = ONVERTEX; // return ONVERTEX; + break; + } + + // We enter from one of serarchtet's faces, which face do we exit? + oriorg = orient3d(tdest, tapex, toppo, searchpt); + oridest = orient3d(tapex, torg, toppo, searchpt); + oriapex = orient3d(torg, tdest, toppo, searchpt); + + // Now decide which face to move. It is possible there are more than one + // faces are viable moves. If so, randomly choose one. + if (oriorg < 0) { + if (oridest < 0) { + if (oriapex < 0) { + // All three faces are possible. + s = randomnation(3); // 's' is in {0,1,2}. + if (s == 0) { + nextmove = ORGMOVE; + } else if (s == 1) { + nextmove = DESTMOVE; + } else { + nextmove = APEXMOVE; + } + } else { + // Two faces, opposite to origin and destination, are viable. + //s = randomnation(2); // 's' is in {0,1}. + if (randomnation(2)) { + nextmove = ORGMOVE; + } else { + nextmove = DESTMOVE; + } + } + } else { + if (oriapex < 0) { + // Two faces, opposite to origin and apex, are viable. + //s = randomnation(2); // 's' is in {0,1}. + if (randomnation(2)) { + nextmove = ORGMOVE; + } else { + nextmove = APEXMOVE; + } + } else { + // Only the face opposite to origin is viable. + nextmove = ORGMOVE; + } + } + } else { + if (oridest < 0) { + if (oriapex < 0) { + // Two faces, opposite to destination and apex, are viable. + //s = randomnation(2); // 's' is in {0,1}. + if (randomnation(2)) { + nextmove = DESTMOVE; + } else { + nextmove = APEXMOVE; + } + } else { + // Only the face opposite to destination is viable. + nextmove = DESTMOVE; + } + } else { + if (oriapex < 0) { + // Only the face opposite to apex is viable. + nextmove = APEXMOVE; + } else { + // The point we seek must be on the boundary of or inside this + // tetrahedron. Check for boundary cases. + if (oriorg == 0) { + // Go to the face opposite to origin. + enextesymself(*searchtet); + if (oridest == 0) { + eprevself(*searchtet); // edge oppo->apex + if (oriapex == 0) { + // oppo is duplicated with p. + loc = ONVERTEX; // return ONVERTEX; + break; + } + loc = ONEDGE; // return ONEDGE; + break; + } + if (oriapex == 0) { + enextself(*searchtet); // edge dest->oppo + loc = ONEDGE; // return ONEDGE; + break; + } + loc = ONFACE; // return ONFACE; + break; + } + if (oridest == 0) { + // Go to the face opposite to destination. + eprevesymself(*searchtet); + if (oriapex == 0) { + eprevself(*searchtet); // edge oppo->org + loc = ONEDGE; // return ONEDGE; + break; + } + loc = ONFACE; // return ONFACE; + break; + } + if (oriapex == 0) { + // Go to the face opposite to apex + esymself(*searchtet); + loc = ONFACE; // return ONFACE; + break; + } + loc = INTETRAHEDRON; // return INTETRAHEDRON; + break; + } + } + } + + // Move to the selected face. + if (nextmove == ORGMOVE) { + enextesymself(*searchtet); + } else if (nextmove == DESTMOVE) { + eprevesymself(*searchtet); + } else { + esymself(*searchtet); + } + // Move to the adjacent tetrahedron (maybe a hull tetrahedron). + fsymself(*searchtet); + if (oppo(*searchtet) == dummypoint) { + loc = OUTSIDE; // return OUTSIDE; + break; + } + + // Retreat the three vertices of the base face. + torg = org(*searchtet); + tdest = dest(*searchtet); + tapex = apex(*searchtet); + + } // while (true) + + return loc; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// flippush() Push a face (possibly will be flipped) into flipstack. // +// // +// The face is marked. The flag is used to check the validity of the face on // +// its popup. Some other flips may change it already. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::flippush(badface*& fstack, triface* flipface) +{ + if (!facemarked(*flipface)) { + badface *newflipface = (badface *) flippool->alloc(); + newflipface->tt = *flipface; + markface(newflipface->tt); + // Push this face into stack. + newflipface->nextitem = fstack; + fstack = newflipface; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// incrementalflip() Incrementally flipping to construct DT. // +// // +// Faces need to be checked for flipping are already queued in 'flipstack'. // +// Return the total number of performed flips. // +// // +// Comment: This routine should be only used in the incremental Delaunay // +// construction. In other cases, lawsonflip3d() should be used. // +// // +// If the new point lies outside of the convex hull ('hullflag' is set). The // +// incremental flip algorithm still works as usual. However, we must ensure // +// that every flip (2-to-3 or 3-to-2) does not create a duplicated (existing)// +// edge or face. Otherwise, the underlying space of the triangulation becomes// +// non-manifold and it is not possible to flip further. // +// Thanks to Joerg Rambau and Frank Lutz for helping in this issue. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::incrementalflip(point newpt, int hullflag, flipconstraints *fc) +{ + badface *popface; + triface fliptets[5], *parytet; + point *pts, *parypt, pe; + REAL sign, ori; + int flipcount = 0; + int t1ver; + int i; + + if (b->verbose > 2) { + printf(" Lawson flip (%ld faces).\n", flippool->items); + } + + if (hullflag) { + // 'newpt' lies in the outside of the convex hull. + // Mark all hull vertices which are connecting to it. + popface = flipstack; + while (popface != NULL) { + pts = (point *) popface->tt.tet; + for (i = 4; i < 8; i++) { + if ((pts[i] != newpt) && (pts[i] != dummypoint)) { + if (!pinfected(pts[i])) { + pinfect(pts[i]); + cavetetvertlist->newindex((void **) &parypt); + *parypt = pts[i]; + } + } + } + popface = popface->nextitem; + } + } + + // Loop until the queue is empty. + while (flipstack != NULL) { + + // Pop a face from the stack. + popface = flipstack; + fliptets[0] = popface->tt; + flipstack = flipstack->nextitem; // The next top item in stack. + flippool->dealloc((void *) popface); + + // Skip it if it is a dead tet (destroyed by previous flips). + if (isdeadtet(fliptets[0])) continue; + // Skip it if it is not the same tet as we saved. + if (!facemarked(fliptets[0])) continue; + + unmarkface(fliptets[0]); + + if ((point) fliptets[0].tet[7] == dummypoint) { + // It must be a hull edge. + fliptets[0].ver = epivot[fliptets[0].ver]; + // A hull edge. The current convex hull may be enlarged. + fsym(fliptets[0], fliptets[1]); + pts = (point *) fliptets[1].tet; + ori = orient3d(pts[4], pts[5], pts[6], newpt); + if (ori < 0) { + // Visible. The convex hull will be enlarged. + // Decide which flip (2-to-3, 3-to-2, or 4-to-1) to use. + // Check if the tet [a,c,e,d] or [c,b,e,d] exists. + enext(fliptets[1], fliptets[2]); + eprev(fliptets[1], fliptets[3]); + fnextself(fliptets[2]); // [a,c,e,*] + fnextself(fliptets[3]); // [c,b,e,*] + if (oppo(fliptets[2]) == newpt) { + if (oppo(fliptets[3]) == newpt) { + // Both tets exist! A 4-to-1 flip is found. + terminatetetgen(this, 2); // Report a bug. + } else { + esym(fliptets[2], fliptets[0]); + fnext(fliptets[0], fliptets[1]); + fnext(fliptets[1], fliptets[2]); + // Perform a 3-to-2 flip. Replace edge [c,a] by face [d,e,b]. + // This corresponds to my standard labels, where edge [e,d] is + // repalced by face [a,b,c], and a is the new vertex. + // [0] [c,a,d,e] (d = newpt) + // [1] [c,a,e,b] (c = dummypoint) + // [2] [c,a,b,d] + flip32(fliptets, 1, fc); + } + } else { + if (oppo(fliptets[3]) == newpt) { + fnext(fliptets[3], fliptets[0]); + fnext(fliptets[0], fliptets[1]); + fnext(fliptets[1], fliptets[2]); + // Perform a 3-to-2 flip. Replace edge [c,b] by face [d,a,e]. + // [0] [c,b,d,a] (d = newpt) + // [1] [c,b,a,e] (c = dummypoint) + // [2] [c,b,e,d] + flip32(fliptets, 1, fc); + } else { + if (hullflag) { + // Reject this flip if pe is already marked. + pe = oppo(fliptets[1]); + if (!pinfected(pe)) { + pinfect(pe); + cavetetvertlist->newindex((void **) &parypt); + *parypt = pe; + // Perform a 2-to-3 flip. + flip23(fliptets, 1, fc); + } else { + // Reject this flip. + flipcount--; + } + } else { + // Perform a 2-to-3 flip. Replace face [a,b,c] by edge [e,d]. + // [0] [a,b,c,d], d = newpt. + // [1] [b,a,c,e], c = dummypoint. + flip23(fliptets, 1, fc); + } + } + } + flipcount++; + } + continue; + } // if (dummypoint) + + fsym(fliptets[0], fliptets[1]); + if ((point) fliptets[1].tet[7] == dummypoint) { + // A hull face is locally Delaunay. + continue; + } + // Check if the adjacent tet has already been tested. + if (marktested(fliptets[1])) { + // It has been tested and it is Delaunay. + continue; + } + + // Test whether the face is locally Delaunay or not. + pts = (point *) fliptets[1].tet; + if (b->weighted) { + sign = orient4d_s(pts[4], pts[5], pts[6], pts[7], newpt, + pts[4][3], pts[5][3], pts[6][3], pts[7][3], + newpt[3]); + } else { + sign = insphere_s(pts[4], pts[5], pts[6], pts[7], newpt); + } + + + if (sign < 0) { + point pd = newpt; + point pe = oppo(fliptets[1]); + // Check the convexity of its three edges. Stop checking either a + // locally non-convex edge (ori < 0) or a flat edge (ori = 0) is + // encountered, and 'fliptet' represents that edge. + for (i = 0; i < 3; i++) { + ori = orient3d(org(fliptets[0]), dest(fliptets[0]), pd, pe); + if (ori <= 0) break; + enextself(fliptets[0]); + } + if (ori > 0) { + // A 2-to-3 flip is found. + // [0] [a,b,c,d], + // [1] [b,a,c,e]. no dummypoint. + flip23(fliptets, 0, fc); + flipcount++; + } else { // ori <= 0 + // The edge ('fliptets[0]' = [a',b',c',d]) is non-convex or flat, + // where the edge [a',b'] is one of [a,b], [b,c], and [c,a]. + // Check if there are three or four tets sharing at this edge. + esymself(fliptets[0]); // [b,a,d,c] + for (i = 0; i < 3; i++) { + fnext(fliptets[i], fliptets[i+1]); + } + if (fliptets[3].tet == fliptets[0].tet) { + // A 3-to-2 flip is found. (No hull tet.) + flip32(fliptets, 0, fc); + flipcount++; + } else { + // There are more than 3 tets at this edge. + fnext(fliptets[3], fliptets[4]); + if (fliptets[4].tet == fliptets[0].tet) { + if (ori == 0) { + // A 4-to-4 flip is found. (Two hull tets may be involved.) + // Current tets in 'fliptets': + // [0] [b,a,d,c] (d may be newpt) + // [1] [b,a,c,e] + // [2] [b,a,e,f] (f may be dummypoint) + // [3] [b,a,f,d] + esymself(fliptets[0]); // [a,b,c,d] + // A 2-to-3 flip replaces face [a,b,c] by edge [e,d]. + // This creates a degenerate tet [e,d,a,b] (tmpfliptets[0]). + // It will be removed by the followed 3-to-2 flip. + flip23(fliptets, 0, fc); // No hull tet. + fnext(fliptets[3], fliptets[1]); + fnext(fliptets[1], fliptets[2]); + // Current tets in 'fliptets': + // [0] [...] + // [1] [b,a,d,e] (degenerated, d may be new point). + // [2] [b,a,e,f] (f may be dummypoint) + // [3] [b,a,f,d] + // A 3-to-2 flip replaces edge [b,a] by face [d,e,f]. + // Hull tets may be involved (f may be dummypoint). + flip32(&(fliptets[1]), (apex(fliptets[3]) == dummypoint), fc); + flipcount++; + } + } + } + } // ori + } else { + // The adjacent tet is Delaunay. Mark it to avoid testing it again. + marktest(fliptets[1]); + // Save it for unmarking it later. + cavebdrylist->newindex((void **) &parytet); + *parytet = fliptets[1]; + } + + } // while (flipstack) + + // Unmark saved tetrahedra. + for (i = 0; i < cavebdrylist->objects; i++) { + parytet = (triface *) fastlookup(cavebdrylist, i); + unmarktest(*parytet); + } + cavebdrylist->restart(); + + if (hullflag) { + // Unmark infected vertices. + for (i = 0; i < cavetetvertlist->objects; i++) { + parypt = (point *) fastlookup(cavetetvertlist, i); + puninfect(*parypt); + } + cavetetvertlist->restart(); + } + + + return flipcount; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// initialdelaunay() Create an initial Delaunay tetrahedralization. // +// // +// The tetrahedralization contains only one tetrahedron abcd, and four hull // +// tetrahedra. The points pa, pb, pc, and pd must be linearly independent. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::initialdelaunay(point pa, point pb, point pc, point pd) +{ + triface firsttet, tetopa, tetopb, tetopc, tetopd; + triface worktet, worktet1; + + if (b->verbose > 2) { + printf(" Create init tet (%d, %d, %d, %d)\n", pointmark(pa), + pointmark(pb), pointmark(pc), pointmark(pd)); + } + + // Create the first tetrahedron. + maketetrahedron(&firsttet); + setvertices(firsttet, pa, pb, pc, pd); + // Create four hull tetrahedra. + maketetrahedron(&tetopa); + setvertices(tetopa, pb, pc, pd, dummypoint); + maketetrahedron(&tetopb); + setvertices(tetopb, pc, pa, pd, dummypoint); + maketetrahedron(&tetopc); + setvertices(tetopc, pa, pb, pd, dummypoint); + maketetrahedron(&tetopd); + setvertices(tetopd, pb, pa, pc, dummypoint); + hullsize += 4; + + // Connect hull tetrahedra to firsttet (at four faces of firsttet). + bond(firsttet, tetopd); + esym(firsttet, worktet); + bond(worktet, tetopc); // ab + enextesym(firsttet, worktet); + bond(worktet, tetopa); // bc + eprevesym(firsttet, worktet); + bond(worktet, tetopb); // ca + + // Connect hull tetrahedra together (at six edges of firsttet). + esym(tetopc, worktet); + esym(tetopd, worktet1); + bond(worktet, worktet1); // ab + esym(tetopa, worktet); + eprevesym(tetopd, worktet1); + bond(worktet, worktet1); // bc + esym(tetopb, worktet); + enextesym(tetopd, worktet1); + bond(worktet, worktet1); // ca + eprevesym(tetopc, worktet); + enextesym(tetopb, worktet1); + bond(worktet, worktet1); // da + eprevesym(tetopa, worktet); + enextesym(tetopc, worktet1); + bond(worktet, worktet1); // db + eprevesym(tetopb, worktet); + enextesym(tetopa, worktet1); + bond(worktet, worktet1); // dc + + // Set the vertex type. + if (pointtype(pa) == UNUSEDVERTEX) { + setpointtype(pa, VOLVERTEX); + } + if (pointtype(pb) == UNUSEDVERTEX) { + setpointtype(pb, VOLVERTEX); + } + if (pointtype(pc) == UNUSEDVERTEX) { + setpointtype(pc, VOLVERTEX); + } + if (pointtype(pd) == UNUSEDVERTEX) { + setpointtype(pd, VOLVERTEX); + } + + setpoint2tet(pa, encode(firsttet)); + setpoint2tet(pb, encode(firsttet)); + setpoint2tet(pc, encode(firsttet)); + setpoint2tet(pd, encode(firsttet)); + + // Remember the first tetrahedron. + recenttet = firsttet; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// incrementaldelaunay() Create a Delaunay tetrahedralization by // +// the incremental approach. // +// // +/////////////////////////////////////////////////////////////////////////////// + + +void tetgenmesh::incrementaldelaunay(clock_t& tv) +{ + triface searchtet; + point *permutarray, swapvertex; + REAL v1[3], v2[3], n[3]; + REAL bboxsize, bboxsize2, bboxsize3, ori; + int randindex; + int ngroup = 0; + int i, j; + + if (!b->quiet) { + printf("Delaunizing vertices...\n"); + } + + // Form a random permuation (uniformly at random) of the set of vertices. + permutarray = new point[in->numberofpoints]; + points->traversalinit(); + + if (b->no_sort) { + if (b->verbose) { + printf(" Using the input order.\n"); + } + for (i = 0; i < in->numberofpoints; i++) { + permutarray[i] = (point) points->traverse(); + } + } else { + if (b->verbose) { + printf(" Permuting vertices.\n"); + } + srand(in->numberofpoints); + for (i = 0; i < in->numberofpoints; i++) { + randindex = rand() % (i + 1); // randomnation(i + 1); + permutarray[i] = permutarray[randindex]; + permutarray[randindex] = (point) points->traverse(); + } + if (b->brio_hilbert) { // -b option + if (b->verbose) { + printf(" Sorting vertices.\n"); + } + hilbert_init(in->mesh_dim); + brio_multiscale_sort(permutarray, in->numberofpoints, b->brio_threshold, + b->brio_ratio, &ngroup); + } + } + + tv = clock(); // Remember the time for sorting points. + + // Calculate the diagonal size of its bounding box. + bboxsize = sqrt(norm2(xmax - xmin, ymax - ymin, zmax - zmin)); + bboxsize2 = bboxsize * bboxsize; + bboxsize3 = bboxsize2 * bboxsize; + + // Make sure the second vertex is not identical with the first one. + i = 1; + while ((distance(permutarray[0],permutarray[i])/bboxsize)epsilon) { + i++; + if (i == in->numberofpoints - 1) { + printf("Exception: All vertices are (nearly) identical (Tol = %g).\n", + b->epsilon); + terminatetetgen(this, 10); + } + } + if (i > 1) { + // Swap to move the non-identical vertex from index i to index 1. + swapvertex = permutarray[i]; + permutarray[i] = permutarray[1]; + permutarray[1] = swapvertex; + } + + // Make sure the third vertex is not collinear with the first two. + // Acknowledgement: Thanks Jan Pomplun for his correction by using + // epsilon^2 and epsilon^3 (instead of epsilon). 2013-08-15. + i = 2; + for (j = 0; j < 3; j++) { + v1[j] = permutarray[1][j] - permutarray[0][j]; + v2[j] = permutarray[i][j] - permutarray[0][j]; + } + cross(v1, v2, n); + while ((sqrt(norm2(n[0], n[1], n[2])) / bboxsize2) < + (b->epsilon * b->epsilon)) { + i++; + if (i == in->numberofpoints - 1) { + printf("Exception: All vertices are (nearly) collinear (Tol = %g).\n", + b->epsilon); + terminatetetgen(this, 10); + } + for (j = 0; j < 3; j++) { + v2[j] = permutarray[i][j] - permutarray[0][j]; + } + cross(v1, v2, n); + } + if (i > 2) { + // Swap to move the non-identical vertex from index i to index 1. + swapvertex = permutarray[i]; + permutarray[i] = permutarray[2]; + permutarray[2] = swapvertex; + } + + // Make sure the fourth vertex is not coplanar with the first three. + i = 3; + ori = orient3dfast(permutarray[0], permutarray[1], permutarray[2], + permutarray[i]); + while ((fabs(ori) / bboxsize3) < (b->epsilon * b->epsilon * b->epsilon)) { + i++; + if (i == in->numberofpoints) { + printf("Exception: All vertices are coplanar (Tol = %g).\n", + b->epsilon); + terminatetetgen(this, 10); + } + ori = orient3dfast(permutarray[0], permutarray[1], permutarray[2], + permutarray[i]); + } + if (i > 3) { + // Swap to move the non-identical vertex from index i to index 1. + swapvertex = permutarray[i]; + permutarray[i] = permutarray[3]; + permutarray[3] = swapvertex; + } + + // Orient the first four vertices in permutarray so that they follow the + // right-hand rule. + if (ori > 0.0) { + // Swap the first two vertices. + swapvertex = permutarray[0]; + permutarray[0] = permutarray[1]; + permutarray[1] = swapvertex; + } + + // Create the initial Delaunay tetrahedralization. + initialdelaunay(permutarray[0], permutarray[1], permutarray[2], + permutarray[3]); + + if (b->verbose) { + printf(" Incrementally inserting vertices.\n"); + } + insertvertexflags ivf; + flipconstraints fc; + + // Choose algorithm: Bowyer-Watson (default) or Incremental Flip + if (b->incrflip) { + ivf.bowywat = 0; + ivf.lawson = 1; + fc.enqflag = 1; + } else { + ivf.bowywat = 1; + ivf.lawson = 0; + } + + + for (i = 4; i < in->numberofpoints; i++) { + if (pointtype(permutarray[i]) == UNUSEDVERTEX) { + setpointtype(permutarray[i], VOLVERTEX); + } + if (b->brio_hilbert || b->no_sort) { // -b or -b/1 + // Start the last updated tet. + searchtet.tet = recenttet.tet; + } else { // -b0 + // Randomly choose the starting tet for point location. + searchtet.tet = NULL; + } + ivf.iloc = (int) OUTSIDE; + // Insert the vertex. + if (insertpoint(permutarray[i], &searchtet, NULL, NULL, &ivf)) { + if (flipstack != NULL) { + // Perform flip to recover Delaunayness. + incrementalflip(permutarray[i], (ivf.iloc == (int) OUTSIDE), &fc); + } + } else { + if (ivf.iloc == (int) ONVERTEX) { + // The point already exists. Mark it and do nothing on it. + swapvertex = org(searchtet); + assert(swapvertex != permutarray[i]); // SELF_CHECK + if (b->object != tetgenbehavior::STL) { + if (!b->quiet) { + printf("Warning: Point #%d is coincident with #%d. Ignored!\n", + pointmark(permutarray[i]), pointmark(swapvertex)); + } + } + setpoint2ppt(permutarray[i], swapvertex); + setpointtype(permutarray[i], DUPLICATEDVERTEX); + dupverts++; + } else if (ivf.iloc == (int) NEARVERTEX) { + swapvertex = point2ppt(permutarray[i]); + if (!b->quiet) { + printf("Warning: Point %d is replaced by point %d.\n", + pointmark(permutarray[i]), pointmark(swapvertex)); + printf(" Avoid creating a very short edge (len = %g) (< %g).\n", + permutarray[i][3], b->minedgelength); + printf(" You may try a smaller tolerance (-T) (current is %g)\n", + b->epsilon); + printf(" or use the option -M0/1 to avoid such replacement.\n"); + } + // Remember it is a duplicated point. + setpointtype(permutarray[i], DUPLICATEDVERTEX); + // Count the number of duplicated points. + dupverts++; + } + } + } + + + + delete [] permutarray; +} + +//// //// +//// //// +//// delaunay_cxx ///////////////////////////////////////////////////////////// + +//// surface_cxx ////////////////////////////////////////////////////////////// +//// //// +//// //// + +/////////////////////////////////////////////////////////////////////////////// +// // +// flipshpush() Push a facet edge into flip stack. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::flipshpush(face* flipedge) +{ + badface *newflipface; + + newflipface = (badface *) flippool->alloc(); + newflipface->ss = *flipedge; + newflipface->forg = sorg(*flipedge); + newflipface->fdest = sdest(*flipedge); + newflipface->nextitem = flipstack; + flipstack = newflipface; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// flip22() Perform a 2-to-2 flip in surface mesh. // +// // +// 'flipfaces' is an array of two subfaces. On input, they are [a,b,c] and // +// [b,a,d]. On output, they are [c,d,b] and [d,c,a]. As a result, edge [a,b] // +// is replaced by edge [c,d]. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::flip22(face* flipfaces, int flipflag, int chkencflag) +{ + face bdedges[4], outfaces[4], infaces[4]; + face bdsegs[4]; + face checkface; + point pa, pb, pc, pd; + int i; + + pa = sorg(flipfaces[0]); + pb = sdest(flipfaces[0]); + pc = sapex(flipfaces[0]); + pd = sapex(flipfaces[1]); + + if (sorg(flipfaces[1]) != pb) { + sesymself(flipfaces[1]); + } + + flip22count++; + + // Collect the four boundary edges. + senext(flipfaces[0], bdedges[0]); + senext2(flipfaces[0], bdedges[1]); + senext(flipfaces[1], bdedges[2]); + senext2(flipfaces[1], bdedges[3]); + + // Collect outer boundary faces. + for (i = 0; i < 4; i++) { + spivot(bdedges[i], outfaces[i]); + infaces[i] = outfaces[i]; + sspivot(bdedges[i], bdsegs[i]); + if (outfaces[i].sh != NULL) { + if (isshsubseg(bdedges[i])) { + spivot(infaces[i], checkface); + while (checkface.sh != bdedges[i].sh) { + infaces[i] = checkface; + spivot(infaces[i], checkface); + } + } + } + } + + // The flags set in these two subfaces do not change. + // Shellmark does not change. + // area constraint does not change. + + // Transform [a,b,c] -> [c,d,b]. + setshvertices(flipfaces[0], pc, pd, pb); + // Transform [b,a,d] -> [d,c,a]. + setshvertices(flipfaces[1], pd, pc, pa); + + // Update the point-to-subface map. + if (pointtype(pa) == FREEFACETVERTEX) { + setpoint2sh(pa, sencode(flipfaces[1])); + } + if (pointtype(pb) == FREEFACETVERTEX) { + setpoint2sh(pb, sencode(flipfaces[0])); + } + if (pointtype(pc) == FREEFACETVERTEX) { + setpoint2sh(pc, sencode(flipfaces[0])); + } + if (pointtype(pd) == FREEFACETVERTEX) { + setpoint2sh(pd, sencode(flipfaces[0])); + } + + // Reconnect boundary edges to outer boundary faces. + for (i = 0; i < 4; i++) { + if (outfaces[(3 + i) % 4].sh != NULL) { + // Make sure that the subface has the ori as the segment. + if (bdsegs[(3 + i) % 4].sh != NULL) { + bdsegs[(3 + i) % 4].shver = 0; + if (sorg(bdedges[i]) != sorg(bdsegs[(3 + i) % 4])) { + sesymself(bdedges[i]); + } + } + sbond1(bdedges[i], outfaces[(3 + i) % 4]); + sbond1(infaces[(3 + i) % 4], bdedges[i]); + } else { + sdissolve(bdedges[i]); + } + if (bdsegs[(3 + i) % 4].sh != NULL) { + ssbond(bdedges[i], bdsegs[(3 + i) % 4]); + if (chkencflag & 1) { + // Queue this segment for encroaching check. + enqueuesubface(badsubsegs, &(bdsegs[(3 + i) % 4])); + } + } else { + ssdissolve(bdedges[i]); + } + } + + if (chkencflag & 2) { + // Queue the flipped subfaces for quality/encroaching checks. + for (i = 0; i < 2; i++) { + enqueuesubface(badsubfacs, &(flipfaces[i])); + } + } + + recentsh = flipfaces[0]; + + if (flipflag) { + // Put the boundary edges into flip stack. + for (i = 0; i < 4; i++) { + flipshpush(&(bdedges[i])); + } + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// flip31() Remove a vertex by transforming 3-to-1 subfaces. // +// // +// 'flipfaces' is an array of subfaces. Its length is at least 4. On input, // +// the first three faces are: [p,a,b], [p,b,c], and [p,c,a]. This routine // +// replaces them by one face [a,b,c], it is returned in flipfaces[3]. // +// // +// NOTE: The three old subfaces are not deleted within this routine. They // +// still hold pointers to their adjacent subfaces. These informations are // +// needed by the routine 'sremovevertex()' for recovering a segment. // +// The caller of this routine must delete the old subfaces after their uses. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::flip31(face* flipfaces, int flipflag) +{ + face bdedges[3], outfaces[3], infaces[3]; + face bdsegs[3]; + face checkface; + point pa, pb, pc; + int i; + + pa = sdest(flipfaces[0]); + pb = sdest(flipfaces[1]); + pc = sdest(flipfaces[2]); + + flip31count++; + + // Collect all infos at the three boundary edges. + for (i = 0; i < 3; i++) { + senext(flipfaces[i], bdedges[i]); + spivot(bdedges[i], outfaces[i]); + infaces[i] = outfaces[i]; + sspivot(bdedges[i], bdsegs[i]); + if (outfaces[i].sh != NULL) { + if (isshsubseg(bdedges[i])) { + spivot(infaces[i], checkface); + while (checkface.sh != bdedges[i].sh) { + infaces[i] = checkface; + spivot(infaces[i], checkface); + } + } + } + } // i + + // Create a new subface. + makeshellface(subfaces, &(flipfaces[3])); + setshvertices(flipfaces[3], pa, pb,pc); + setshellmark(flipfaces[3], shellmark(flipfaces[0])); + if (checkconstraints) { + //area = areabound(flipfaces[0]); + setareabound(flipfaces[3], areabound(flipfaces[0])); + } + if (useinsertradius) { + setfacetindex(flipfaces[3], getfacetindex(flipfaces[0])); + } + + // Update the point-to-subface map. + if (pointtype(pa) == FREEFACETVERTEX) { + setpoint2sh(pa, sencode(flipfaces[3])); + } + if (pointtype(pb) == FREEFACETVERTEX) { + setpoint2sh(pb, sencode(flipfaces[3])); + } + if (pointtype(pc) == FREEFACETVERTEX) { + setpoint2sh(pc, sencode(flipfaces[3])); + } + + // Update the three new boundary edges. + bdedges[0] = flipfaces[3]; // [a,b] + senext(flipfaces[3], bdedges[1]); // [b,c] + senext2(flipfaces[3], bdedges[2]); // [c,a] + + // Reconnect boundary edges to outer boundary faces. + for (i = 0; i < 3; i++) { + if (outfaces[i].sh != NULL) { + // Make sure that the subface has the ori as the segment. + if (bdsegs[i].sh != NULL) { + bdsegs[i].shver = 0; + if (sorg(bdedges[i]) != sorg(bdsegs[i])) { + sesymself(bdedges[i]); + } + } + sbond1(bdedges[i], outfaces[i]); + sbond1(infaces[i], bdedges[i]); + } + if (bdsegs[i].sh != NULL) { + ssbond(bdedges[i], bdsegs[i]); + } + } + + recentsh = flipfaces[3]; + + if (flipflag) { + // Put the boundary edges into flip stack. + for (i = 0; i < 3; i++) { + flipshpush(&(bdedges[i])); + } + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// lawsonflip() Flip non-locally Delaunay edges. // +// // +/////////////////////////////////////////////////////////////////////////////// + +long tetgenmesh::lawsonflip() +{ + badface *popface; + face flipfaces[2]; + point pa, pb, pc, pd; + REAL sign; + long flipcount = 0; + + if (b->verbose > 2) { + printf(" Lawson flip %ld edges.\n", flippool->items); + } + + while (flipstack != (badface *) NULL) { + + // Pop an edge from the stack. + popface = flipstack; + flipfaces[0] = popface->ss; + pa = popface->forg; + pb = popface->fdest; + flipstack = popface->nextitem; // The next top item in stack. + flippool->dealloc((void *) popface); + + // Skip it if it is dead. + if (flipfaces[0].sh[3] == NULL) continue; + // Skip it if it is not the same edge as we saved. + if ((sorg(flipfaces[0]) != pa) || (sdest(flipfaces[0]) != pb)) continue; + // Skip it if it is a subsegment. + if (isshsubseg(flipfaces[0])) continue; + + // Get the adjacent face. + spivot(flipfaces[0], flipfaces[1]); + if (flipfaces[1].sh == NULL) continue; // Skip a hull edge. + pc = sapex(flipfaces[0]); + pd = sapex(flipfaces[1]); + + sign = incircle3d(pa, pb, pc, pd); + + if (sign < 0) { + // It is non-locally Delaunay. Flip it. + flip22(flipfaces, 1, 0); + flipcount++; + } + } + + if (b->verbose > 2) { + printf(" Performed %ld flips.\n", flipcount); + } + + return flipcount; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// sinsertvertex() Insert a vertex into a triangulation of a facet. // +// // +// This function uses three global arrays: 'caveshlist', 'caveshbdlist', and // +// 'caveshseglist'. On return, 'caveshlist' contains old subfaces in C(p), // +// 'caveshbdlist' contains new subfaces in C(p). If the new point lies on a // +// segment, 'cavesegshlist' returns the two new subsegments. // +// // +// 'iloc' suggests the location of the point. If it is OUTSIDE, this routine // +// will first locate the point. It starts searching from 'searchsh' or 'rec- // +// entsh' if 'searchsh' is NULL. // +// // +// If 'bowywat' is set (1), the Bowyer-Watson algorithm is used to insert // +// the vertex. Otherwise, only insert the vertex in the initial cavity. // +// // +// If 'iloc' is 'INSTAR', this means the cavity of this vertex was already // +// provided in the list 'caveshlist'. // +// // +// If 'splitseg' is not NULL, the new vertex lies on the segment and it will // +// be split. 'iloc' must be either 'ONEDGE' or 'INSTAR'. // +// // +// 'rflag' (rounding) is a parameter passed to slocate() function. If it is // +// set, after the location of the point is found, either ONEDGE or ONFACE, // +// round the result using an epsilon. // +// // +// NOTE: the old subfaces in C(p) are not deleted. They're needed in case we // +// want to remove the new point immediately. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::sinsertvertex(point insertpt, face *searchsh, face *splitseg, + int iloc, int bowywat, int rflag) +{ + face cavesh, neighsh, *parysh; + face newsh, casout, casin; + face checkseg; + point pa, pb; + enum locateresult loc = OUTSIDE; + REAL sign, ori; + int i, j; + + if (b->verbose > 2) { + printf(" Insert facet point %d.\n", pointmark(insertpt)); + } + + if (bowywat == 3) { + loc = INSTAR; + } + + if ((splitseg != NULL) && (splitseg->sh != NULL)) { + // A segment is going to be split, no point location. + spivot(*splitseg, *searchsh); + if (loc != INSTAR) loc = ONEDGE; + } else { + if (loc != INSTAR) loc = (enum locateresult) iloc; + if (loc == OUTSIDE) { + // Do point location in surface mesh. + if (searchsh->sh == NULL) { + *searchsh = recentsh; + } + // Search the vertex. An above point must be provided ('aflag' = 1). + loc = slocate(insertpt, searchsh, 1, 1, rflag); + } + } + + + // Form the initial sC(p). + if (loc == ONFACE) { + // Add the face into list (in B-W cavity). + smarktest(*searchsh); + caveshlist->newindex((void **) &parysh); + *parysh = *searchsh; + } else if (loc == ONEDGE) { + if ((splitseg != NULL) && (splitseg->sh != NULL)) { + splitseg->shver = 0; + pa = sorg(*splitseg); + } else { + pa = sorg(*searchsh); + } + if (searchsh->sh != NULL) { + // Collect all subfaces share at this edge. + neighsh = *searchsh; + while (1) { + // Adjust the origin of its edge to be 'pa'. + if (sorg(neighsh) != pa) sesymself(neighsh); + // Add this face into list (in B-W cavity). + smarktest(neighsh); + caveshlist->newindex((void **) &parysh); + *parysh = neighsh; + // Add this face into face-at-splitedge list. + cavesegshlist->newindex((void **) &parysh); + *parysh = neighsh; + // Go to the next face at the edge. + spivotself(neighsh); + // Stop if all faces at the edge have been visited. + if (neighsh.sh == searchsh->sh) break; + if (neighsh.sh == NULL) break; + } + } // If (not a non-dangling segment). + } else if (loc == ONVERTEX) { + return (int) loc; + } else if (loc == OUTSIDE) { + // Comment: This should only happen during the surface meshing step. + // Enlarge the convex hull of the triangulation by including p. + // An above point of the facet is set in 'dummypoint' to replace + // orient2d tests by orient3d tests. + // Imagine that the current edge a->b (in 'searchsh') is horizontal in a + // plane, and a->b is directed from left to right, p lies above a->b. + // Find the right-most edge of the triangulation which is visible by p. + neighsh = *searchsh; + while (1) { + senext2self(neighsh); + spivot(neighsh, casout); + if (casout.sh == NULL) { + // A convex hull edge. Is it visible by p. + ori = orient3d(sorg(neighsh), sdest(neighsh), dummypoint, insertpt); + if (ori < 0) { + *searchsh = neighsh; // Visible, update 'searchsh'. + } else { + break; // 'searchsh' is the right-most visible edge. + } + } else { + if (sorg(casout) != sdest(neighsh)) sesymself(casout); + neighsh = casout; + } + } + // Create new triangles for all visible edges of p (from right to left). + casin.sh = NULL; // No adjacent face at right. + pa = sorg(*searchsh); + pb = sdest(*searchsh); + while (1) { + // Create a new subface on top of the (visible) edge. + makeshellface(subfaces, &newsh); + setshvertices(newsh, pb, pa, insertpt); + setshellmark(newsh, shellmark(*searchsh)); + if (checkconstraints) { + //area = areabound(*searchsh); + setareabound(newsh, areabound(*searchsh)); + } + if (useinsertradius) { + setfacetindex(newsh, getfacetindex(*searchsh)); + } + // Connect the new subface to the bottom subfaces. + sbond1(newsh, *searchsh); + sbond1(*searchsh, newsh); + // Connect the new subface to its right-adjacent subface. + if (casin.sh != NULL) { + senext(newsh, casout); + sbond1(casout, casin); + sbond1(casin, casout); + } + // The left-adjacent subface has not been created yet. + senext2(newsh, casin); + // Add the new face into list (inside the B-W cavity). + smarktest(newsh); + caveshlist->newindex((void **) &parysh); + *parysh = newsh; + // Move to the convex hull edge at the left of 'searchsh'. + neighsh = *searchsh; + while (1) { + senextself(neighsh); + spivot(neighsh, casout); + if (casout.sh == NULL) { + *searchsh = neighsh; + break; + } + if (sorg(casout) != sdest(neighsh)) sesymself(casout); + neighsh = casout; + } + // A convex hull edge. Is it visible by p. + pa = sorg(*searchsh); + pb = sdest(*searchsh); + ori = orient3d(pa, pb, dummypoint, insertpt); + // Finish the process if p is not visible by the hull edge. + if (ori >= 0) break; + } + } else if (loc == INSTAR) { + // Under this case, the sub-cavity sC(p) has already been formed in + // insertvertex(). + } + + // Form the Bowyer-Watson cavity sC(p). + for (i = 0; i < caveshlist->objects; i++) { + cavesh = * (face *) fastlookup(caveshlist, i); + for (j = 0; j < 3; j++) { + if (!isshsubseg(cavesh)) { + spivot(cavesh, neighsh); + if (neighsh.sh != NULL) { + // The adjacent face exists. + if (!smarktested(neighsh)) { + if (bowywat) { + if (loc == INSTAR) { // if (bowywat > 2) { + // It must be a boundary edge. + sign = 1; + } else { + // Check if this subface is connected to adjacent tet(s). + if (!isshtet(neighsh)) { + // Check if the subface is non-Delaunay wrt. the new pt. + sign = incircle3d(sorg(neighsh), sdest(neighsh), + sapex(neighsh), insertpt); + } else { + // It is connected to an adjacent tet. A boundary edge. + sign = 1; + } + } + if (sign < 0) { + // Add the adjacent face in list (in B-W cavity). + smarktest(neighsh); + caveshlist->newindex((void **) &parysh); + *parysh = neighsh; + } + } else { + sign = 1; // A boundary edge. + } + } else { + sign = -1; // Not a boundary edge. + } + } else { + // No adjacent face. It is a hull edge. + if (loc == OUTSIDE) { + // It is a boundary edge if it does not contain p. + if ((sorg(cavesh) == insertpt) || (sdest(cavesh) == insertpt)) { + sign = -1; // Not a boundary edge. + } else { + sign = 1; // A boundary edge. + } + } else { + sign = 1; // A boundary edge. + } + } + } else { + // Do not across a segment. It is a boundary edge. + sign = 1; + } + if (sign >= 0) { + // Add a boundary edge. + caveshbdlist->newindex((void **) &parysh); + *parysh = cavesh; + } + senextself(cavesh); + } // j + } // i + + + // Creating new subfaces. + for (i = 0; i < caveshbdlist->objects; i++) { + parysh = (face *) fastlookup(caveshbdlist, i); + sspivot(*parysh, checkseg); + if ((parysh->shver & 01) != 0) sesymself(*parysh); + pa = sorg(*parysh); + pb = sdest(*parysh); + // Create a new subface. + makeshellface(subfaces, &newsh); + setshvertices(newsh, pa, pb, insertpt); + setshellmark(newsh, shellmark(*parysh)); + if (checkconstraints) { + //area = areabound(*parysh); + setareabound(newsh, areabound(*parysh)); + } + if (useinsertradius) { + setfacetindex(newsh, getfacetindex(*parysh)); + } + // Update the point-to-subface map. + if (pointtype(pa) == FREEFACETVERTEX) { + setpoint2sh(pa, sencode(newsh)); + } + if (pointtype(pb) == FREEFACETVERTEX) { + setpoint2sh(pb, sencode(newsh)); + } + // Connect newsh to outer subfaces. + spivot(*parysh, casout); + if (casout.sh != NULL) { + casin = casout; + if (checkseg.sh != NULL) { + // Make sure that newsh has the right ori at this segment. + checkseg.shver = 0; + if (sorg(newsh) != sorg(checkseg)) { + sesymself(newsh); + sesymself(*parysh); // This side should also be inverse. + } + spivot(casin, neighsh); + while (neighsh.sh != parysh->sh) { + casin = neighsh; + spivot(casin, neighsh); + } + } + sbond1(newsh, casout); + sbond1(casin, newsh); + } + if (checkseg.sh != NULL) { + ssbond(newsh, checkseg); + } + // Connect oldsh <== newsh (for connecting adjacent new subfaces). + // *parysh and newsh point to the same edge and the same ori. + sbond1(*parysh, newsh); + } + + if (newsh.sh != NULL) { + // Set a handle for searching. + recentsh = newsh; + } + + // Update the point-to-subface map. + if (pointtype(insertpt) == FREEFACETVERTEX) { + setpoint2sh(insertpt, sencode(newsh)); + } + + // Connect adjacent new subfaces together. + for (i = 0; i < caveshbdlist->objects; i++) { + // Get an old subface at edge [a, b]. + parysh = (face *) fastlookup(caveshbdlist, i); + spivot(*parysh, newsh); // The new subface [a, b, p]. + senextself(newsh); // At edge [b, p]. + spivot(newsh, neighsh); + if (neighsh.sh == NULL) { + // Find the adjacent new subface at edge [b, p]. + pb = sdest(*parysh); + neighsh = *parysh; + while (1) { + senextself(neighsh); + spivotself(neighsh); + if (neighsh.sh == NULL) break; + if (!smarktested(neighsh)) break; + if (sdest(neighsh) != pb) sesymself(neighsh); + } + if (neighsh.sh != NULL) { + // Now 'neighsh' is a new subface at edge [b, #]. + if (sorg(neighsh) != pb) sesymself(neighsh); + senext2self(neighsh); // Go to the open edge [p, b]. + sbond(newsh, neighsh); + } else { + // There is no adjacent new face at this side. + assert(loc == OUTSIDE); // SELF_CHECK + } + } + spivot(*parysh, newsh); // The new subface [a, b, p]. + senext2self(newsh); // At edge [p, a]. + spivot(newsh, neighsh); + if (neighsh.sh == NULL) { + // Find the adjacent new subface at edge [p, a]. + pa = sorg(*parysh); + neighsh = *parysh; + while (1) { + senext2self(neighsh); + spivotself(neighsh); + if (neighsh.sh == NULL) break; + if (!smarktested(neighsh)) break; + if (sorg(neighsh) != pa) sesymself(neighsh); + } + if (neighsh.sh != NULL) { + // Now 'neighsh' is a new subface at edge [#, a]. + if (sdest(neighsh) != pa) sesymself(neighsh); + senextself(neighsh); // Go to the open edge [a, p]. + sbond(newsh, neighsh); + } else { + // There is no adjacent new face at this side. + assert(loc == OUTSIDE); // SELF_CHECK + } + } + } + + if ((loc == ONEDGE) || ((splitseg != NULL) && (splitseg->sh != NULL)) + || (cavesegshlist->objects > 0l)) { + // An edge is being split. We distinguish two cases: + // (1) the edge is not on the boundary of the cavity; + // (2) the edge is on the boundary of the cavity. + // In case (2), the edge is either a segment or a hull edge. There are + // degenerated new faces in the cavity. They must be removed. + face aseg, bseg, aoutseg, boutseg; + + for (i = 0; i < cavesegshlist->objects; i++) { + // Get the saved old subface. + parysh = (face *) fastlookup(cavesegshlist, i); + // Get a possible new degenerated subface. + spivot(*parysh, cavesh); + if (sapex(cavesh) == insertpt) { + // Found a degenerated new subface, i.e., case (2). + if (cavesegshlist->objects > 1) { + // There are more than one subface share at this edge. + j = (i + 1) % (int) cavesegshlist->objects; + parysh = (face *) fastlookup(cavesegshlist, j); + spivot(*parysh, neighsh); + // Adjust cavesh and neighsh both at edge a->b, and has p as apex. + if (sorg(neighsh) != sorg(cavesh)) { + sesymself(neighsh); + assert(sorg(neighsh) == sorg(cavesh)); // SELF_CHECK + } + assert(sapex(neighsh) == insertpt); // SELF_CHECK + // Connect adjacent faces at two other edges of cavesh and neighsh. + // As a result, the two degenerated new faces are squeezed from the + // new triangulation of the cavity. Note that the squeezed faces + // still hold the adjacent informations which will be used in + // re-connecting subsegments (if they exist). + for (j = 0; j < 2; j++) { + senextself(cavesh); + senextself(neighsh); + spivot(cavesh, newsh); + spivot(neighsh, casout); + sbond1(newsh, casout); // newsh <- casout. + } + } else { + // There is only one subface containing this edge [a,b]. Squeeze the + // degenerated new face [a,b,c] by disconnecting it from its two + // adjacent subfaces at edges [b,c] and [c,a]. Note that the face + // [a,b,c] still hold the connection to them. + for (j = 0; j < 2; j++) { + senextself(cavesh); + spivot(cavesh, newsh); + sdissolve(newsh); + } + } + //recentsh = newsh; + // Update the point-to-subface map. + if (pointtype(insertpt) == FREEFACETVERTEX) { + setpoint2sh(insertpt, sencode(newsh)); + } + } + } + + if ((splitseg != NULL) && (splitseg->sh != NULL)) { + if (loc != INSTAR) { // if (bowywat < 3) { + smarktest(*splitseg); // Mark it as being processed. + } + + aseg = *splitseg; + pa = sorg(*splitseg); + pb = sdest(*splitseg); + + // Insert the new point p. + makeshellface(subsegs, &aseg); + makeshellface(subsegs, &bseg); + + setshvertices(aseg, pa, insertpt, NULL); + setshvertices(bseg, insertpt, pb, NULL); + setshellmark(aseg, shellmark(*splitseg)); + setshellmark(bseg, shellmark(*splitseg)); + if (checkconstraints) { + setareabound(aseg, areabound(*splitseg)); + setareabound(bseg, areabound(*splitseg)); + } + if (useinsertradius) { + setfacetindex(aseg, getfacetindex(*splitseg)); + setfacetindex(bseg, getfacetindex(*splitseg)); + } + + // Connect [#, a]<->[a, p]. + senext2(*splitseg, boutseg); // Temporarily use boutseg. + spivotself(boutseg); + if (boutseg.sh != NULL) { + senext2(aseg, aoutseg); + sbond(boutseg, aoutseg); + } + // Connect [p, b]<->[b, #]. + senext(*splitseg, aoutseg); + spivotself(aoutseg); + if (aoutseg.sh != NULL) { + senext(bseg, boutseg); + sbond(boutseg, aoutseg); + } + // Connect [a, p] <-> [p, b]. + senext(aseg, aoutseg); + senext2(bseg, boutseg); + sbond(aoutseg, boutseg); + + // Connect subsegs [a, p] and [p, b] to adjacent new subfaces. + // Although the degenerated new faces have been squeezed. They still + // hold the connections to the actual new faces. + for (i = 0; i < cavesegshlist->objects; i++) { + parysh = (face *) fastlookup(cavesegshlist, i); + spivot(*parysh, neighsh); + // neighsh is a degenerated new face. + if (sorg(neighsh) != pa) { + sesymself(neighsh); + } + senext2(neighsh, newsh); + spivotself(newsh); // The edge [p, a] in newsh + ssbond(newsh, aseg); + senext(neighsh, newsh); + spivotself(newsh); // The edge [b, p] in newsh + ssbond(newsh, bseg); + } + + + // Let the point remember the segment it lies on. + if (pointtype(insertpt) == FREESEGVERTEX) { + setpoint2sh(insertpt, sencode(aseg)); + } + // Update the point-to-seg map. + if (pointtype(pa) == FREESEGVERTEX) { + setpoint2sh(pa, sencode(aseg)); + } + if (pointtype(pb) == FREESEGVERTEX) { + setpoint2sh(pb, sencode(bseg)); + } + } // if ((splitseg != NULL) && (splitseg->sh != NULL)) + + // Delete all degenerated new faces. + for (i = 0; i < cavesegshlist->objects; i++) { + parysh = (face *) fastlookup(cavesegshlist, i); + spivotself(*parysh); + if (sapex(*parysh) == insertpt) { + shellfacedealloc(subfaces, parysh->sh); + } + } + cavesegshlist->restart(); + + if ((splitseg != NULL) && (splitseg->sh != NULL)) { + // Return the two new subsegments (for further process). + // Re-use 'cavesegshlist'. + cavesegshlist->newindex((void **) &parysh); + *parysh = aseg; + cavesegshlist->newindex((void **) &parysh); + *parysh = bseg; + } + } // if (loc == ONEDGE) + + + return (int) loc; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// sremovevertex() Remove a vertex from the surface mesh. // +// // +// 'delpt' (p) is the vertex to be removed. If 'parentseg' is not NULL, p is // +// a segment vertex, and the origin of 'parentseg' is p. Otherwise, p is a // +// facet vertex, and the origin of 'parentsh' is p. // +// // +// Within each facet, we first use a sequence of 2-to-2 flips to flip any // +// edge at p, finally use a 3-to-1 flip to remove p. // +// // +// All new created subfaces are returned in the global array 'caveshbdlist'. // +// The new segment (when p is on segment) is returned in 'parentseg'. // +// // +// If 'lawson' > 0, the Lawson flip algorithm is used to recover Delaunay- // +// ness after p is removed. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::sremovevertex(point delpt, face* parentsh, face* parentseg, + int lawson) +{ + face flipfaces[4], spinsh, *parysh; + point pa, pb, pc, pd; + REAL ori1, ori2; + int it, i, j; + + if (parentseg != NULL) { + // 'delpt' (p) should be a Steiner point inserted in a segment [a,b], + // where 'parentseg' should be [p,b]. Find the segment [a,p]. + face startsh, neighsh, nextsh; + face abseg, prevseg, checkseg; + face adjseg1, adjseg2; + face fakesh; + senext2(*parentseg, prevseg); + spivotself(prevseg); + prevseg.shver = 0; + assert(sdest(prevseg) == delpt); + // Restore the original segment [a,b]. + pa = sorg(prevseg); + pb = sdest(*parentseg); + if (b->verbose > 2) { + printf(" Remove vertex %d from segment [%d, %d].\n", + pointmark(delpt), pointmark(pa), pointmark(pb)); + } + makeshellface(subsegs, &abseg); + setshvertices(abseg, pa, pb, NULL); + setshellmark(abseg, shellmark(*parentseg)); + if (checkconstraints) { + setareabound(abseg, areabound(*parentseg)); + } + if (useinsertradius) { + setfacetindex(abseg, getfacetindex(*parentseg)); + } + // Connect [#, a]<->[a, b]. + senext2(prevseg, adjseg1); + spivotself(adjseg1); + if (adjseg1.sh != NULL) { + adjseg1.shver = 0; + assert(sdest(adjseg1) == pa); + senextself(adjseg1); + senext2(abseg, adjseg2); + sbond(adjseg1, adjseg2); + } + // Connect [a, b]<->[b, #]. + senext(*parentseg, adjseg1); + spivotself(adjseg1); + if (adjseg1.sh != NULL) { + adjseg1.shver = 0; + assert(sorg(adjseg1) == pb); + senext2self(adjseg1); + senext(abseg, adjseg2); + sbond(adjseg1, adjseg2); + } + // Update the point-to-segment map. + setpoint2sh(pa, sencode(abseg)); + setpoint2sh(pb, sencode(abseg)); + + // Get the faces in face ring at segment [p, b]. + // Re-use array 'caveshlist'. + spivot(*parentseg, *parentsh); + if (parentsh->sh != NULL) { + spinsh = *parentsh; + while (1) { + // Save this face in list. + caveshlist->newindex((void **) &parysh); + *parysh = spinsh; + // Go to the next face in the ring. + spivotself(spinsh); + if (spinsh.sh == parentsh->sh) break; + } + } + + // Create the face ring of the new segment [a,b]. Each face in the ring + // is [a,b,p] (degenerated!). It will be removed (automatically). + for (i = 0; i < caveshlist->objects; i++) { + parysh = (face *) fastlookup(caveshlist, i); + startsh = *parysh; + if (sorg(startsh) != delpt) { + sesymself(startsh); + assert(sorg(startsh) == delpt); + } + // startsh is [p, b, #1], find the subface [a, p, #2]. + neighsh = startsh; + while (1) { + senext2self(neighsh); + sspivot(neighsh, checkseg); + if (checkseg.sh != NULL) { + // It must be the segment [a, p]. + assert(checkseg.sh == prevseg.sh); + break; + } + spivotself(neighsh); + assert(neighsh.sh != NULL); + if (sorg(neighsh) != delpt) sesymself(neighsh); + } + // Now neighsh is [a, p, #2]. + if (neighsh.sh != startsh.sh) { + // Detach the two subsegments [a,p] and [p,b] from subfaces. + ssdissolve(startsh); + ssdissolve(neighsh); + // Create a degenerated subface [a,b,p]. It is used to: (1) hold the + // new segment [a,b]; (2) connect to the two adjacent subfaces + // [p,b,#] and [a,p,#]. + makeshellface(subfaces, &fakesh); + setshvertices(fakesh, pa, pb, delpt); + setshellmark(fakesh, shellmark(startsh)); + // Connect fakesh to the segment [a,b]. + ssbond(fakesh, abseg); + // Connect fakesh to adjacent subfaces: [p,b,#1] and [a,p,#2]. + senext(fakesh, nextsh); + sbond(nextsh, startsh); + senext2(fakesh, nextsh); + sbond(nextsh, neighsh); + smarktest(fakesh); // Mark it as faked. + } else { + // Special case. There exists already a degenerated face [a,b,p]! + // There is no need to create a faked subface here. + senext2self(neighsh); // [a,b,p] + assert(sapex(neighsh) == delpt); + // Since we will re-connect the face ring using the faked subfaces. + // We put the adjacent face of [a,b,p] to the list. + spivot(neighsh, startsh); // The original adjacent subface. + if (sorg(startsh) != pa) sesymself(startsh); + sdissolve(startsh); + // Connect fakesh to the segment [a,b]. + ssbond(startsh, abseg); + fakesh = startsh; // Do not mark it! + // Delete the degenerated subface. + shellfacedealloc(subfaces, neighsh.sh); + } + // Save the fakesh in list (for re-creating the face ring). + cavesegshlist->newindex((void **) &parysh); + *parysh = fakesh; + } // i + caveshlist->restart(); + + // Re-create the face ring. + if (cavesegshlist->objects > 1) { + for (i = 0; i < cavesegshlist->objects; i++) { + parysh = (face *) fastlookup(cavesegshlist, i); + fakesh = *parysh; + // Get the next face in the ring. + j = (i + 1) % cavesegshlist->objects; + parysh = (face *) fastlookup(cavesegshlist, j); + nextsh = *parysh; + sbond1(fakesh, nextsh); + } + } + + // Delete the two subsegments containing p. + shellfacedealloc(subsegs, parentseg->sh); + shellfacedealloc(subsegs, prevseg.sh); + // Return the new segment. + *parentseg = abseg; + } else { + // p is inside the surface. + if (b->verbose > 2) { + printf(" Remove vertex %d from surface.\n", pointmark(delpt)); + } + assert(sorg(*parentsh) == delpt); + // Let 'delpt' be its apex. + senextself(*parentsh); + // For unifying the code, we add parentsh to list. + cavesegshlist->newindex((void **) &parysh); + *parysh = *parentsh; + } + + // Remove the point (p). + + for (it = 0; it < cavesegshlist->objects; it++) { + parentsh = (face *) fastlookup(cavesegshlist, it); // [a,b,p] + senextself(*parentsh); // [b,p,a]. + spivotself(*parentsh); + if (sorg(*parentsh) != delpt) sesymself(*parentsh); + // now parentsh is [p,b,#]. + if (sorg(*parentsh) != delpt) { + // The vertex has already been removed in above special case. + assert(!smarktested(*parentsh)); + continue; + } + + while (1) { + // Initialize the flip edge list. Re-use 'caveshlist'. + spinsh = *parentsh; // [p, b, #] + while (1) { + caveshlist->newindex((void **) &parysh); + *parysh = spinsh; + senext2self(spinsh); + spivotself(spinsh); + assert(spinsh.sh != NULL); + if (spinsh.sh == parentsh->sh) break; + if (sorg(spinsh) != delpt) sesymself(spinsh); + assert(sorg(spinsh) == delpt); + } // while (1) + + if (caveshlist->objects == 3) { + // Delete the point by a 3-to-1 flip. + for (i = 0; i < 3; i++) { + parysh = (face *) fastlookup(caveshlist, i); + flipfaces[i] = *parysh; + } + flip31(flipfaces, lawson); + for (i = 0; i < 3; i++) { + shellfacedealloc(subfaces, flipfaces[i].sh); + } + caveshlist->restart(); + // Save the new subface. + caveshbdlist->newindex((void **) &parysh); + *parysh = flipfaces[3]; + // The vertex is removed. + break; + } + + // Search an edge to flip. + for (i = 0; i < caveshlist->objects; i++) { + parysh = (face *) fastlookup(caveshlist, i); + flipfaces[0] = *parysh; + spivot(flipfaces[0], flipfaces[1]); + if (sorg(flipfaces[0]) != sdest(flipfaces[1])) + sesymself(flipfaces[1]); + // Skip this edge if it belongs to a faked subface. + if (!smarktested(flipfaces[0]) && !smarktested(flipfaces[1])) { + pa = sorg(flipfaces[0]); + pb = sdest(flipfaces[0]); + pc = sapex(flipfaces[0]); + pd = sapex(flipfaces[1]); + calculateabovepoint4(pa, pb, pc, pd); + // Check if a 2-to-2 flip is possible. + ori1 = orient3d(pc, pd, dummypoint, pa); + ori2 = orient3d(pc, pd, dummypoint, pb); + if (ori1 * ori2 < 0) { + // A 2-to-2 flip is found. + flip22(flipfaces, lawson, 0); + // The i-th edge is flipped. The i-th and (i-1)-th subfaces are + // changed. The 'flipfaces[1]' contains p as its apex. + senext2(flipfaces[1], *parentsh); + // Save the new subface. + caveshbdlist->newindex((void **) &parysh); + *parysh = flipfaces[0]; + break; + } + } // + } // i + + if (i == caveshlist->objects) { + // This can happen only if there are 4 edges at p, and they are + // orthogonal to each other, see Fig. 2010-11-01. + assert(caveshlist->objects == 4); + // Do a flip22 and a flip31 to remove p. + parysh = (face *) fastlookup(caveshlist, 0); + flipfaces[0] = *parysh; + spivot(flipfaces[0], flipfaces[1]); + if (sorg(flipfaces[0]) != sdest(flipfaces[1])) { + sesymself(flipfaces[1]); + } + flip22(flipfaces, lawson, 0); + senext2(flipfaces[1], *parentsh); + // Save the new subface. + caveshbdlist->newindex((void **) &parysh); + *parysh = flipfaces[0]; + } + + // The edge list at p are changed. + caveshlist->restart(); + } // while (1) + + } // it + + cavesegshlist->restart(); + + if (b->verbose > 2) { + printf(" Created %ld new subfaces.\n", caveshbdlist->objects); + } + + + if (lawson) { + lawsonflip(); + } + + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// slocate() Locate a point in a surface triangulation. // +// // +// Staring the search from 'searchsh'(it should not be NULL). Perform a line // +// walk search for a subface containing the point (p). // +// // +// If 'aflag' is set, the 'dummypoint' is pre-calculated so that it lies // +// above the 'searchsh' in its current orientation. The test if c is CCW to // +// the line a->b can be done by the test if c is below the oriented plane // +// a->b->dummypoint. // +// // +// If 'cflag' is not TRUE, the triangulation may not be convex. Stop search // +// when a segment is met and return OUTSIDE. // +// // +// If 'rflag' (rounding) is set, after the location of the point is found, // +// either ONEDGE or ONFACE, round the result using an epsilon. // +// // +// The returned value indicates the following cases: // +// - ONVERTEX, p is the origin of 'searchsh'. // +// - ONEDGE, p lies on the edge of 'searchsh'. // +// - ONFACE, p lies in the interior of 'searchsh'. // +// - OUTSIDE, p lies outside of the triangulation, p is on the left-hand // +// side of the edge 'searchsh'(s), i.e., org(s), dest(s), p are CW. // +// // +/////////////////////////////////////////////////////////////////////////////// + +enum tetgenmesh::locateresult tetgenmesh::slocate(point searchpt, + face* searchsh, int aflag, int cflag, int rflag) +{ + face neighsh; + point pa, pb, pc; + enum locateresult loc; + enum {MOVE_BC, MOVE_CA} nextmove; + REAL ori, ori_bc, ori_ca; + int i; + + pa = sorg(*searchsh); + pb = sdest(*searchsh); + pc = sapex(*searchsh); + + if (!aflag) { + // No above point is given. Calculate an above point for this facet. + calculateabovepoint4(pa, pb, pc, searchpt); + } + + // 'dummypoint' is given. Make sure it is above [a,b,c] + ori = orient3d(pa, pb, pc, dummypoint); + assert(ori != 0); // SELF_CHECK + if (ori > 0) { + sesymself(*searchsh); // Reverse the face orientation. + } + + // Find an edge of the face s.t. p lies on its right-hand side (CCW). + for (i = 0; i < 3; i++) { + pa = sorg(*searchsh); + pb = sdest(*searchsh); + ori = orient3d(pa, pb, dummypoint, searchpt); + if (ori > 0) break; + senextself(*searchsh); + } + assert(i < 3); // SELF_CHECK + + pc = sapex(*searchsh); + + if (pc == searchpt) { + senext2self(*searchsh); + return ONVERTEX; + } + + while (1) { + + ori_bc = orient3d(pb, pc, dummypoint, searchpt); + ori_ca = orient3d(pc, pa, dummypoint, searchpt); + + if (ori_bc < 0) { + if (ori_ca < 0) { // (--) + // Any of the edges is a viable move. + if (randomnation(2)) { + nextmove = MOVE_CA; + } else { + nextmove = MOVE_BC; + } + } else { // (-#) + // Edge [b, c] is viable. + nextmove = MOVE_BC; + } + } else { + if (ori_ca < 0) { // (#-) + // Edge [c, a] is viable. + nextmove = MOVE_CA; + } else { + if (ori_bc > 0) { + if (ori_ca > 0) { // (++) + loc = ONFACE; // Inside [a, b, c]. + break; + } else { // (+0) + senext2self(*searchsh); // On edge [c, a]. + loc = ONEDGE; + break; + } + } else { // ori_bc == 0 + if (ori_ca > 0) { // (0+) + senextself(*searchsh); // On edge [b, c]. + loc = ONEDGE; + break; + } else { // (00) + // p is coincident with vertex c. + senext2self(*searchsh); + return ONVERTEX; + } + } + } + } + + // Move to the next face. + if (nextmove == MOVE_BC) { + senextself(*searchsh); + } else { + senext2self(*searchsh); + } + if (!cflag) { + // NON-convex case. Check if we will cross a boundary. + if (isshsubseg(*searchsh)) { + return ENCSEGMENT; + } + } + spivot(*searchsh, neighsh); + if (neighsh.sh == NULL) { + return OUTSIDE; // A hull edge. + } + // Adjust the edge orientation. + if (sorg(neighsh) != sdest(*searchsh)) { + sesymself(neighsh); + } + assert(sorg(neighsh) == sdest(*searchsh)); // SELF_CHECK + + // Update the newly discovered face and its endpoints. + *searchsh = neighsh; + pa = sorg(*searchsh); + pb = sdest(*searchsh); + pc = sapex(*searchsh); + + if (pc == searchpt) { + senext2self(*searchsh); + return ONVERTEX; + } + + } // while (1) + + // assert(loc == ONFACE || loc == ONEDGE); + + + if (rflag) { + // Round the locate result before return. + REAL n[3], area_abc, area_abp, area_bcp, area_cap; + + pa = sorg(*searchsh); + pb = sdest(*searchsh); + pc = sapex(*searchsh); + + facenormal(pa, pb, pc, n, 1, NULL); + area_abc = sqrt(dot(n, n)); + + facenormal(pb, pc, searchpt, n, 1, NULL); + area_bcp = sqrt(dot(n, n)); + if ((area_bcp / area_abc) < b->epsilon) { + area_bcp = 0; // Rounding. + } + + facenormal(pc, pa, searchpt, n, 1, NULL); + area_cap = sqrt(dot(n, n)); + if ((area_cap / area_abc) < b->epsilon) { + area_cap = 0; // Rounding + } + + if ((loc == ONFACE) || (loc == OUTSIDE)) { + facenormal(pa, pb, searchpt, n, 1, NULL); + area_abp = sqrt(dot(n, n)); + if ((area_abp / area_abc) < b->epsilon) { + area_abp = 0; // Rounding + } + } else { // loc == ONEDGE + area_abp = 0; + } + + if (area_abp == 0) { + if (area_bcp == 0) { + assert(area_cap != 0); + senextself(*searchsh); + loc = ONVERTEX; // p is close to b. + } else { + if (area_cap == 0) { + loc = ONVERTEX; // p is close to a. + } else { + loc = ONEDGE; // p is on edge [a,b]. + } + } + } else if (area_bcp == 0) { + if (area_cap == 0) { + senext2self(*searchsh); + loc = ONVERTEX; // p is close to c. + } else { + senextself(*searchsh); + loc = ONEDGE; // p is on edge [b,c]. + } + } else if (area_cap == 0) { + senext2self(*searchsh); + loc = ONEDGE; // p is on edge [c,a]. + } else { + loc = ONFACE; // p is on face [a,b,c]. + } + } // if (rflag) + + return loc; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// sscoutsegment() Look for a segment in surface triangulation. // +// // +// The segment is given by the origin of 'searchsh' and 'endpt'. Assume the // +// orientation of 'searchsh' is CCW w.r.t. the above point. // +// // +// If an edge in T is found matching this segment, the segment is "locked" // +// in T at the edge. Otherwise, flip the first edge in T that the segment // +// crosses. Continue the search from the flipped face. // +// // +/////////////////////////////////////////////////////////////////////////////// + +enum tetgenmesh::interresult tetgenmesh::sscoutsegment(face *searchsh, + point endpt) +{ + face flipshs[2], neighsh; + face newseg; + point startpt, pa, pb, pc, pd; + enum interresult dir; + enum {MOVE_AB, MOVE_CA} nextmove; + REAL ori_ab, ori_ca, len; + + // The origin of 'searchsh' is fixed. + startpt = sorg(*searchsh); // pa = startpt; + nextmove = MOVE_AB; // Avoid compiler warning. + + if (b->verbose > 2) { + printf(" Scout segment (%d, %d).\n", pointmark(startpt), + pointmark(endpt)); + } + len = distance(startpt, endpt); + + // Search an edge in 'searchsh' on the path of this segment. + while (1) { + + pb = sdest(*searchsh); + if (pb == endpt) { + dir = SHAREEDGE; // Found! + break; + } + + pc = sapex(*searchsh); + if (pc == endpt) { + senext2self(*searchsh); + sesymself(*searchsh); + dir = SHAREEDGE; // Found! + break; + } + + // Round the results. + if ((sqrt(triarea(startpt, pb, endpt)) / len) < b->epsilon) { + ori_ab = 0.0; + } else { + ori_ab = orient3d(startpt, pb, dummypoint, endpt); + } + if ((sqrt(triarea(pc, startpt, endpt)) / len) < b->epsilon) { + ori_ca = 0.0; + } else { + ori_ca = orient3d(pc, startpt, dummypoint, endpt); + } + + if (ori_ab < 0) { + if (ori_ca < 0) { // (--) + // Both sides are viable moves. + if (randomnation(2)) { + nextmove = MOVE_CA; + } else { + nextmove = MOVE_AB; + } + } else { // (-#) + nextmove = MOVE_AB; + } + } else { + if (ori_ca < 0) { // (#-) + nextmove = MOVE_CA; + } else { + if (ori_ab > 0) { + if (ori_ca > 0) { // (++) + // The segment intersects with edge [b, c]. + dir = ACROSSEDGE; + break; + } else { // (+0) + // The segment collinear with edge [c, a]. + senext2self(*searchsh); + sesymself(*searchsh); + dir = ACROSSVERT; + break; + } + } else { + if (ori_ca > 0) { // (0+) + // The segment collinear with edge [a, b]. + dir = ACROSSVERT; + break; + } else { // (00) + // startpt == endpt. Not possible. + assert(0); // SELF_CHECK + } + } + } + } + + // Move 'searchsh' to the next face, keep the origin unchanged. + if (nextmove == MOVE_AB) { + spivot(*searchsh, neighsh); + if (neighsh.sh != NULL) { + if (sorg(neighsh) != pb) sesymself(neighsh); + senext(neighsh, *searchsh); + } else { + // This side (startpt->pb) is outside. It is caused by rounding error. + // Try the next side, i.e., (pc->startpt). + senext2(*searchsh, neighsh); + spivotself(neighsh); + assert(neighsh.sh != NULL); + if (sdest(neighsh) != pc) sesymself(neighsh); + *searchsh = neighsh; + } + } else { + senext2(*searchsh, neighsh); + spivotself(neighsh); + if (neighsh.sh != NULL) { + if (sdest(neighsh) != pc) sesymself(neighsh); + *searchsh = neighsh; + } else { + // The same reason as above. + // Try the next side, i.e., (startpt->pb). + spivot(*searchsh, neighsh); + assert(neighsh.sh != NULL); + if (sorg(neighsh) != pb) sesymself(neighsh); + senext(neighsh, *searchsh); + } + } + assert(sorg(*searchsh) == startpt); // SELF_CHECK + + } // while + + if (dir == SHAREEDGE) { + // Insert the segment into the triangulation. + makeshellface(subsegs, &newseg); + setshvertices(newseg, startpt, endpt, NULL); + // Set the default segment marker. + setshellmark(newseg, 1); + ssbond(*searchsh, newseg); + spivot(*searchsh, neighsh); + if (neighsh.sh != NULL) { + ssbond(neighsh, newseg); + } + return dir; + } + + if (dir == ACROSSVERT) { + // A point is found collinear with this segment. + return dir; + } + + if (dir == ACROSSEDGE) { + // Edge [b, c] intersects with the segment. + senext(*searchsh, flipshs[0]); + if (isshsubseg(flipshs[0])) { + printf("Error: Invalid PLC.\n"); + pb = sorg(flipshs[0]); + pc = sdest(flipshs[0]); + printf(" Two segments (%d, %d) and (%d, %d) intersect.\n", + pointmark(startpt), pointmark(endpt), pointmark(pb), pointmark(pc)); + terminatetetgen(this, 3); + } + // Flip edge [b, c], queue unflipped edges (for Delaunay checks). + spivot(flipshs[0], flipshs[1]); + assert(flipshs[1].sh != NULL); // SELF_CHECK + if (sorg(flipshs[1]) != sdest(flipshs[0])) sesymself(flipshs[1]); + flip22(flipshs, 1, 0); + // The flip may create an inverted triangle, check it. + pa = sapex(flipshs[1]); + pb = sapex(flipshs[0]); + pc = sorg(flipshs[0]); + pd = sdest(flipshs[0]); + // Check if pa and pb are on the different sides of [pc, pd]. + // Re-use ori_ab, ori_ca for the tests. + ori_ab = orient3d(pc, pd, dummypoint, pb); + ori_ca = orient3d(pd, pc, dummypoint, pa); + //assert(ori_ab * ori_ca != 0); // SELF_CHECK + if (ori_ab < 0) { + flipshpush(&(flipshs[0])); // push it to 'flipstack' + } else if (ori_ca < 0) { + flipshpush(&(flipshs[1])); // // push it to 'flipstack' + } + // Set 'searchsh' s.t. its origin is 'startpt'. + *searchsh = flipshs[0]; + assert(sorg(*searchsh) == startpt); + } + + return sscoutsegment(searchsh, endpt); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// scarveholes() Remove triangles not in the facet. // +// // +// This routine re-uses the two global arrays: caveshlist and caveshbdlist. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::scarveholes(int holes, REAL* holelist) +{ + face *parysh, searchsh, neighsh; + enum locateresult loc; + int i, j; + + // Get all triangles. Infect unprotected convex hull triangles. + smarktest(recentsh); + caveshlist->newindex((void **) &parysh); + *parysh = recentsh; + for (i = 0; i < caveshlist->objects; i++) { + parysh = (face *) fastlookup(caveshlist, i); + searchsh = *parysh; + searchsh.shver = 0; + for (j = 0; j < 3; j++) { + spivot(searchsh, neighsh); + // Is this side on the convex hull? + if (neighsh.sh != NULL) { + if (!smarktested(neighsh)) { + smarktest(neighsh); + caveshlist->newindex((void **) &parysh); + *parysh = neighsh; + } + } else { + // A hull side. Check if it is protected by a segment. + if (!isshsubseg(searchsh)) { + // Not protected. Save this face. + if (!sinfected(searchsh)) { + sinfect(searchsh); + caveshbdlist->newindex((void **) &parysh); + *parysh = searchsh; + } + } + } + senextself(searchsh); + } + } + + // Infect the triangles in the holes. + for (i = 0; i < 3 * holes; i += 3) { + searchsh = recentsh; + loc = slocate(&(holelist[i]), &searchsh, 1, 1, 0); + if (loc != OUTSIDE) { + sinfect(searchsh); + caveshbdlist->newindex((void **) &parysh); + *parysh = searchsh; + } + } + + // Find and infect all exterior triangles. + for (i = 0; i < caveshbdlist->objects; i++) { + parysh = (face *) fastlookup(caveshbdlist, i); + searchsh = *parysh; + searchsh.shver = 0; + for (j = 0; j < 3; j++) { + spivot(searchsh, neighsh); + if (neighsh.sh != NULL) { + if (!isshsubseg(searchsh)) { + if (!sinfected(neighsh)) { + sinfect(neighsh); + caveshbdlist->newindex((void **) &parysh); + *parysh = neighsh; + } + } else { + sdissolve(neighsh); // Disconnect a protected face. + } + } + senextself(searchsh); + } + } + + // Delete exterior triangles, unmark interior triangles. + for (i = 0; i < caveshlist->objects; i++) { + parysh = (face *) fastlookup(caveshlist, i); + if (sinfected(*parysh)) { + shellfacedealloc(subfaces, parysh->sh); + } else { + sunmarktest(*parysh); + } + } + + caveshlist->restart(); + caveshbdlist->restart(); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// triangulate() Create a CDT for the facet. // +// // +// All vertices of the triangulation have type FACETVERTEX. The actual type // +// of boundary vertices are set by the routine unifysements(). // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::triangulate(int shmark, arraypool* ptlist, arraypool* conlist, + int holes, REAL* holelist) +{ + face searchsh, newsh, *parysh; + face newseg; + point pa, pb, pc, *ppt, *cons; + int iloc; + int i, j; + + if (b->verbose > 2) { + printf(" f%d: %ld vertices, %ld segments", shmark, ptlist->objects, + conlist->objects); + if (holes > 0) { + printf(", %d holes", holes); + } + printf(".\n"); + } + + if (ptlist->objects < 2l) { + // Not a segment or a facet. + return; + } + + if (ptlist->objects == 2l) { + pa = * (point *) fastlookup(ptlist, 0); + pb = * (point *) fastlookup(ptlist, 1); + if (distance(pa, pb) > 0) { + // It is a single segment. + makeshellface(subsegs, &newseg); + setshvertices(newseg, pa, pb, NULL); + // Set the default segment marker '1'. + setshellmark(newseg, 1); + } + if (pointtype(pa) == VOLVERTEX) { + setpointtype(pa, FACETVERTEX); + } + if (pointtype(pb) == VOLVERTEX) { + setpointtype(pb, FACETVERTEX); + } + return; + } + + + if (ptlist->objects == 3) { + pa = * (point *) fastlookup(ptlist, 0); + pb = * (point *) fastlookup(ptlist, 1); + pc = * (point *) fastlookup(ptlist, 2); + } else { + // Calculate an above point of this facet. + if (!calculateabovepoint(ptlist, &pa, &pb, &pc)) { + return; // The point set is degenerate. + } + } + + // Create an initial triangulation. + makeshellface(subfaces, &newsh); + setshvertices(newsh, pa, pb, pc); + setshellmark(newsh, shmark); + recentsh = newsh; + + if (pointtype(pa) == VOLVERTEX) { + setpointtype(pa, FACETVERTEX); + } + if (pointtype(pb) == VOLVERTEX) { + setpointtype(pb, FACETVERTEX); + } + if (pointtype(pc) == VOLVERTEX) { + setpointtype(pc, FACETVERTEX); + } + + // Are there area constraints? + if (b->quality && (in->facetconstraintlist != (REAL *) NULL)) { + int idx, fmarker; + REAL area; + idx = in->facetmarkerlist[shmark - 1]; // The actual facet marker. + for (i = 0; i < in->numberoffacetconstraints; i++) { + fmarker = (int) in->facetconstraintlist[i * 2]; + if (fmarker == idx) { + area = in->facetconstraintlist[i * 2 + 1]; + setareabound(newsh, area); + break; + } + } + } + + if (ptlist->objects == 3) { + // The triangulation only has one element. + for (i = 0; i < 3; i++) { + makeshellface(subsegs, &newseg); + setshvertices(newseg, sorg(newsh), sdest(newsh), NULL); + // Set the default segment marker '1'. + setshellmark(newseg, 1); + ssbond(newsh, newseg); + senextself(newsh); + } + return; + } + + // Incrementally build the triangulation. + pinfect(pa); + pinfect(pb); + pinfect(pc); + for (i = 0; i < ptlist->objects; i++) { + ppt = (point *) fastlookup(ptlist, i); + if (!pinfected(*ppt)) { + searchsh = recentsh; // Start from 'recentsh'. + iloc = (int) OUTSIDE; + // Insert the vertex. Use Bowyer-Watson algo. Round the location. + iloc = sinsertvertex(*ppt, &searchsh, NULL, iloc, 1, 1); + if (pointtype(*ppt) == VOLVERTEX) { + setpointtype(*ppt, FACETVERTEX); + } + // Delete all removed subfaces. + for (j = 0; j < caveshlist->objects; j++) { + parysh = (face *) fastlookup(caveshlist, j); + shellfacedealloc(subfaces, parysh->sh); + } + // Clear the global lists. + caveshbdlist->restart(); + caveshlist->restart(); + cavesegshlist->restart(); + } else { + puninfect(*ppt); // This point has inserted. + } + } + + // Insert the segments. + for (i = 0; i < conlist->objects; i++) { + cons = (point *) fastlookup(conlist, i); + searchsh = recentsh; + iloc = (int) slocate(cons[0], &searchsh, 1, 1, 0); + if (iloc != (enum locateresult) ONVERTEX) { + // Not found due to roundoff errors. Do a brute-force search. + subfaces->traversalinit(); + searchsh.sh = shellfacetraverse(subfaces); + while (searchsh.sh != NULL) { + // Only search the subface in the same facet. + if (shellmark(searchsh) == shmark) { + if ((point) searchsh.sh[3] == cons[0]) { + searchsh.shver = 0; break; + } else if ((point) searchsh.sh[4] == cons[0]) { + searchsh.shver = 2; break; + } else if ((point) searchsh.sh[5] == cons[0]) { + searchsh.shver = 4; break; + } + } + searchsh.sh = shellfacetraverse(subfaces); + } + assert(searchsh.sh != NULL); + } + // Recover the segment. Some edges may be flipped. + sscoutsegment(&searchsh, cons[1]); + if (flipstack != NULL) { + // Recover locally Delaunay edges. + lawsonflip(); + } + } + + // Remove exterior and hole triangles. + scarveholes(holes, holelist); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// unifysubfaces() Unify two identical subfaces. // +// // +// Two subfaces, f1 [a, b, c] and f2 [a, b, d], share the same edge [a, b]. // +// If c = d, then f1 and f2 are identical. Otherwise, these two subfaces // +// intersect, and the mesher is stopped. // +// // +// If the two subfaces are identical, we try to replace f2 by f1, i.e, all // +// neighbors of f2 are re-connected to f1. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::unifysubfaces(face *f1, face *f2) +{ + if (b->psc) { + // In this case, it is possible that two subfaces are identical. + // While they must belong to two different surfaces. + return; + } + + point pa, pb, pc, pd; + + pa = sorg(*f1); + pb = sdest(*f1); + pc = sapex(*f1); + pd = sapex(*f2); + + if (pc != pd) { + printf("Found two facets intersect each other.\n"); + printf(" 1st: [%d, %d, %d] #%d\n", + pointmark(pa), pointmark(pb), pointmark(pc), shellmark(*f1)); + printf(" 2nd: [%d, %d, %d] #%d\n", + pointmark(pa), pointmark(pb), pointmark(pd), shellmark(*f2)); + terminatetetgen(this, 3); + } else { + printf("Found two duplicated facets.\n"); + printf(" 1st: [%d, %d, %d] #%d\n", + pointmark(pa), pointmark(pb), pointmark(pc), shellmark(*f1)); + printf(" 2nd: [%d, %d, %d] #%d\n", + pointmark(pa), pointmark(pb), pointmark(pd), shellmark(*f2)); + terminatetetgen(this, 3); + } + +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// unifysegments() Remove redundant segments and create face links. // +// // +// After this routine, although segments are unique, but some of them may be // +// removed later by mergefacet(). All vertices still have type FACETVERTEX. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::unifysegments() +{ + badface *facelink = NULL, *newlinkitem, *f1, *f2; + face *facperverlist, sface; + face subsegloop, testseg; + point torg, tdest; + REAL ori1, ori2, ori3; + REAL n1[3], n2[3]; + int *idx2faclist; + int idx, k, m; + + if (b->verbose > 1) { + printf(" Unifying segments.\n"); + } + + // Create a mapping from vertices to subfaces. + makepoint2submap(subfaces, idx2faclist, facperverlist); + + if (b->psc) { + face sface1; + face seg, seg1; + int fmarker, fmarker1; + // First only connect subfaces which belong to the same surfaces. + subsegloop.shver = 0; + subsegs->traversalinit(); + subsegloop.sh = shellfacetraverse(subsegs); + while (subsegloop.sh != (shellface *) NULL) { + torg = sorg(subsegloop); + tdest = sdest(subsegloop); + + idx = pointmark(torg) - in->firstnumber; + for (k = idx2faclist[idx]; k < idx2faclist[idx + 1]; k++) { + sface = facperverlist[k]; + // The face may be deleted if it is a duplicated face. + if (sface.sh[3] == NULL) continue; + // Search the edge torg->tdest. + assert(sorg(sface) == torg); // SELF_CHECK + if (sdest(sface) != tdest) { + senext2self(sface); + sesymself(sface); + } + if (sdest(sface) != tdest) continue; + + sspivot(sface, seg); + if (seg.sh == NULL) continue; + // assert(seg.sh != NULL); It may or may not be subsegloop. + + // Find the adjacent subface on the same facet. + fmarker = in->facetmarkerlist[shellmark(sface) - 1]; + sface1.sh = NULL; + k++; + for (; k < idx2faclist[idx + 1]; k++) { + sface1 = facperverlist[k]; + // The face may be deleted if it is a duplicated face. + if (sface1.sh[3] == NULL) continue; + // Search the edge torg->tdest. + assert(sorg(sface1) == torg); // SELF_CHECK + if (sdest(sface1) != tdest) { + senext2self(sface1); + sesymself(sface1); + } + if (sdest(sface1) != tdest) continue; + // Found a subface sharing at the same edge. + fmarker1 = in->facetmarkerlist[shellmark(sface1) - 1]; + if (fmarker1 == fmarker) { + // Found a pair of adjacent subfaces. Connect them. + // Delete a redundent segment. + sspivot(sface1, seg1); + assert(seg1.sh != NULL); // SELF_CHECK + shellfacedealloc(subsegs, seg.sh); + shellfacedealloc(subsegs, seg1.sh); + ssdissolve(sface); + ssdissolve(sface1); + // Connect them. + sbond(sface, sface1); + // Set Steiner point -to- subface map. + if (pointtype(torg) == FREEFACETVERTEX) { + setpoint2sh(torg, sencode(sface)); + } + if (pointtype(tdest) == FREEFACETVERTEX) { + setpoint2sh(tdest, sencode(sface)); + } + break; + } + } + break; + } + subsegloop.sh = shellfacetraverse(subsegs); + } + } // if (b->psc) + + subsegloop.shver = 0; + subsegs->traversalinit(); + subsegloop.sh = shellfacetraverse(subsegs); + while (subsegloop.sh != (shellface *) NULL) { + torg = sorg(subsegloop); + tdest = sdest(subsegloop); + + idx = pointmark(torg) - in->firstnumber; + // Loop through the set of subfaces containing 'torg'. Get all the + // subfaces containing the edge (torg, tdest). Save and order them + // in 'sfacelist', the ordering is defined by the right-hand rule + // with thumb points from torg to tdest. + for (k = idx2faclist[idx]; k < idx2faclist[idx + 1]; k++) { + sface = facperverlist[k]; + // The face may be deleted if it is a duplicated face. + if (sface.sh[3] == NULL) continue; + // Search the edge torg->tdest. + assert(sorg(sface) == torg); // SELF_CHECK + if (sdest(sface) != tdest) { + senext2self(sface); + sesymself(sface); + } + if (sdest(sface) != tdest) continue; + + // Save the face f in facelink. + if (flippool->items >= 2) { + f1 = facelink; + for (m = 0; m < flippool->items - 1; m++) { + f2 = f1->nextitem; + ori1 = orient3d(torg, tdest, sapex(f1->ss), sapex(f2->ss)); + ori2 = orient3d(torg, tdest, sapex(f1->ss), sapex(sface)); + if (ori1 > 0) { + // apex(f2) is below f1. + if (ori2 > 0) { + // apex(f) is below f1 (see Fig.1). + ori3 = orient3d(torg, tdest, sapex(f2->ss), sapex(sface)); + if (ori3 > 0) { + // apex(f) is below f2, insert it. + break; + } else if (ori3 < 0) { + // apex(f) is above f2, continue. + } else { // ori3 == 0; + // f is coplanar and codirection with f2. + unifysubfaces(&(f2->ss), &sface); + break; + } + } else if (ori2 < 0) { + // apex(f) is above f1 below f2, inset it (see Fig. 2). + break; + } else { // ori2 == 0; + // apex(f) is coplanar with f1 (see Fig. 5). + ori3 = orient3d(torg, tdest, sapex(f2->ss), sapex(sface)); + if (ori3 > 0) { + // apex(f) is below f2, insert it. + break; + } else { + // f is coplanar and codirection with f1. + unifysubfaces(&(f1->ss), &sface); + break; + } + } + } else if (ori1 < 0) { + // apex(f2) is above f1. + if (ori2 > 0) { + // apex(f) is below f1, continue (see Fig. 3). + } else if (ori2 < 0) { + // apex(f) is above f1 (see Fig.4). + ori3 = orient3d(torg, tdest, sapex(f2->ss), sapex(sface)); + if (ori3 > 0) { + // apex(f) is below f2, insert it. + break; + } else if (ori3 < 0) { + // apex(f) is above f2, continue. + } else { // ori3 == 0; + // f is coplanar and codirection with f2. + unifysubfaces(&(f2->ss), &sface); + break; + } + } else { // ori2 == 0; + // f is coplanar and with f1 (see Fig. 6). + ori3 = orient3d(torg, tdest, sapex(f2->ss), sapex(sface)); + if (ori3 > 0) { + // f is also codirection with f1. + unifysubfaces(&(f1->ss), &sface); + break; + } else { + // f is above f2, continue. + } + } + } else { // ori1 == 0; + // apex(f2) is coplanar with f1. By assumption, f1 is not + // coplanar and codirection with f2. + if (ori2 > 0) { + // apex(f) is below f1, continue (see Fig. 7). + } else if (ori2 < 0) { + // apex(f) is above f1, insert it (see Fig. 7). + break; + } else { // ori2 == 0. + // apex(f) is coplanar with f1 (see Fig. 8). + // f is either codirection with f1 or is codirection with f2. + facenormal(torg, tdest, sapex(f1->ss), n1, 1, NULL); + facenormal(torg, tdest, sapex(sface), n2, 1, NULL); + if (dot(n1, n2) > 0) { + unifysubfaces(&(f1->ss), &sface); + } else { + unifysubfaces(&(f2->ss), &sface); + } + break; + } + } + // Go to the next item; + f1 = f2; + } // for (m = 0; ...) + if (sface.sh[3] != NULL) { + // Insert sface between f1 and f2. + newlinkitem = (badface *) flippool->alloc(); + newlinkitem->ss = sface; + newlinkitem->nextitem = f1->nextitem; + f1->nextitem = newlinkitem; + } + } else if (flippool->items == 1) { + f1 = facelink; + // Make sure that f is not coplanar and codirection with f1. + ori1 = orient3d(torg, tdest, sapex(f1->ss), sapex(sface)); + if (ori1 == 0) { + // f is coplanar with f1 (see Fig. 8). + facenormal(torg, tdest, sapex(f1->ss), n1, 1, NULL); + facenormal(torg, tdest, sapex(sface), n2, 1, NULL); + if (dot(n1, n2) > 0) { + // The two faces are codirectional as well. + unifysubfaces(&(f1->ss), &sface); + } + } + // Add this face to link if it is not deleted. + if (sface.sh[3] != NULL) { + // Add this face into link. + newlinkitem = (badface *) flippool->alloc(); + newlinkitem->ss = sface; + newlinkitem->nextitem = NULL; + f1->nextitem = newlinkitem; + } + } else { + // The first face. + newlinkitem = (badface *) flippool->alloc(); + newlinkitem->ss = sface; + newlinkitem->nextitem = NULL; + facelink = newlinkitem; + } + } // for (k = idx2faclist[idx]; ...) + + if (b->psc) { + // Set Steiner point -to- segment map. + if (pointtype(torg) == FREESEGVERTEX) { + setpoint2sh(torg, sencode(subsegloop)); + } + if (pointtype(tdest) == FREESEGVERTEX) { + setpoint2sh(tdest, sencode(subsegloop)); + } + } + + // Set the connection between this segment and faces containing it, + // at the same time, remove redundant segments. + f1 = facelink; + for (k = 0; k < flippool->items; k++) { + sspivot(f1->ss, testseg); + // If 'testseg' is not 'subsegloop' and is not dead, it is redundant. + if ((testseg.sh != subsegloop.sh) && (testseg.sh[3] != NULL)) { + shellfacedealloc(subsegs, testseg.sh); + } + // Bonds the subface and the segment together. + ssbond(f1->ss, subsegloop); + f1 = f1->nextitem; + } + + // Create the face ring at the segment. + if (flippool->items > 1) { + f1 = facelink; + for (k = 1; k <= flippool->items; k++) { + k < flippool->items ? f2 = f1->nextitem : f2 = facelink; + sbond1(f1->ss, f2->ss); + f1 = f2; + } + } + + // All identified segments has an init marker "0". + flippool->restart(); + + // Are there length constraints? + if (b->quality && (in->segmentconstraintlist != (REAL *) NULL)) { + int e1, e2; + REAL len; + for (k = 0; k < in->numberofsegmentconstraints; k++) { + e1 = (int) in->segmentconstraintlist[k * 3]; + e2 = (int) in->segmentconstraintlist[k * 3 + 1]; + if (((pointmark(torg) == e1) && (pointmark(tdest) == e2)) || + ((pointmark(torg) == e2) && (pointmark(tdest) == e1))) { + len = in->segmentconstraintlist[k * 3 + 2]; + setareabound(subsegloop, len); + break; + } + } + } + + subsegloop.sh = shellfacetraverse(subsegs); + } + + delete [] idx2faclist; + delete [] facperverlist; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// mergefacets() Merge adjacent facets. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::mergefacets() +{ + face parentsh, neighsh, neineish; + face segloop; + point pa, pb, pc, pd; + REAL ang_tol, ang; + int remsegcount; + int fidx1, fidx2; + int fmrk1, fmrk2; + + if (b->verbose > 1) { + printf(" Merging adjacent facets.\n"); + } + + // The dihedral angle bound for two different facets. + // Set by -p option. Default is 179 degree. + ang_tol = b->facet_ang_tol / 180.0 * PI; + remsegcount = 0; + + // Loop all segments, merge adjacent coplanar facets. + subsegs->traversalinit(); + segloop.sh = shellfacetraverse(subsegs); + while (segloop.sh != (shellface *) NULL) { + spivot(segloop, parentsh); + if (parentsh.sh != NULL) { + spivot(parentsh, neighsh); + if (neighsh.sh != NULL) { + spivot(neighsh, neineish); + if (neineish.sh == parentsh.sh) { + // Exactly two subfaces at this segment. + fidx1 = shellmark(parentsh) - 1; + fidx2 = shellmark(neighsh) - 1; + // Only merge them if they are in different facet. + if (fidx1 != fidx2) { + // The two subfaces are not in the same facet. + if (in->facetmarkerlist != NULL) { + fmrk1 = in->facetmarkerlist[fidx1]; + fmrk2 = in->facetmarkerlist[fidx2]; + } else { + fmrk1 = fmrk2 = 0; + } + // Only merge them if they have the same boundary marker. + if (fmrk1 == fmrk2) { + pa = sorg(segloop); + pb = sdest(segloop); + pc = sapex(parentsh); + pd = sapex(neighsh); + // Calculate the dihedral angle at the segment [a,b]. + ang = facedihedral(pa, pb, pc, pd); + if (ang > PI) ang = (2 * PI - ang); + if (ang > ang_tol) { + remsegcount++; + ssdissolve(parentsh); + ssdissolve(neighsh); + shellfacedealloc(subsegs, segloop.sh); + // Add the edge to flip stack. + flipshpush(&parentsh); + } // if (ang > ang_tol) + } // if (fmrk1 == fmrk2) + } // if (fidx1 != fidx2) + } // if (neineish.sh == parentsh.sh) + } + } + segloop.sh = shellfacetraverse(subsegs); + } + + if (flipstack != NULL) { + lawsonflip(); // Recover Delaunayness. + } + + if (b->verbose > 1) { + printf(" %d segments are removed.\n", remsegcount); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// identifypscedges() Identify PSC edges. // +// // +// The set of PSC edges are provided in the 'in->edgelist'. Each edge should // +// also be an edge in the surface mesh. We find the corresponding edges in // +// the surface mesh and make them segments of the mesh. // +// // +// It is possible to give an edge which is not in any facet, i.e., it is a // +// dangling edge inside the volume. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::identifypscedges(point *idx2verlist) +{ + face* shperverlist; + int* idx2shlist; + face searchsh, neighsh; + face segloop, checkseg, newseg; + point checkpt, pa = NULL, pb = NULL; + int *endpts; + int edgemarker; + int idx, i, j; + + int e1, e2; + REAL len; + + if (!b->quiet) { + printf("Inserting edges ...\n"); + } + + // All identified segments have the initial marker '1'. + // All segments inserted here should have a marker 'k >= 0'. + + if (b->psc) { + // First mark all segments of the mesh with a marker '-1'. + subsegs->traversalinit(); + segloop.sh = shellfacetraverse(subsegs); + while (segloop.sh != NULL) { + setshellmark(segloop, -1); + segloop.sh = shellfacetraverse(subsegs); + } + } + + // Construct a map from points to subfaces. + makepoint2submap(subfaces, idx2shlist, shperverlist); + + // Process the set of PSC edges. + for (i = 0; i < in->numberofedges; i++) { + endpts = &(in->edgelist[(i << 1)]); + edgemarker = in->edgemarkerlist ? in->edgemarkerlist[i] : 0; + + // Find a face contains the edge. + newseg.sh = NULL; + searchsh.sh = NULL; + idx = endpts[0] - in->firstnumber; + for (j = idx2shlist[idx]; j < idx2shlist[idx + 1]; j++) { + checkpt = sdest(shperverlist[j]); + if (pointmark(checkpt) == endpts[1]) { + searchsh = shperverlist[j]; + break; // Found. + } else { + checkpt = sapex(shperverlist[j]); + if (pointmark(checkpt) == endpts[1]) { + senext2(shperverlist[j], searchsh); + sesymself(searchsh); + break; + } + } + } // j + + if (searchsh.sh != NULL) { + // Check if this edge is already a segment of the mesh. + sspivot(searchsh, checkseg); + if (checkseg.sh != NULL) { + // This segment already exist. + newseg = checkseg; + } else { + // Create a new segment at this edge. + pa = sorg(searchsh); + pb = sdest(searchsh); + makeshellface(subsegs, &newseg); + setshvertices(newseg, pa, pb, NULL); + ssbond(searchsh, newseg); + spivot(searchsh, neighsh); + if (neighsh.sh != NULL) { + ssbond(neighsh, newseg); + } + if (b->psc) { + if (pointtype(pa) == FREESEGVERTEX) { + setpoint2sh(pa, sencode(newseg)); + } + if (pointtype(pb) == FREESEGVERTEX) { + setpoint2sh(pb, sencode(newseg)); + } + } + } + } else { + // It is a dangling segment (not belong to any facets). + // Get the two endpoints of this segment. + pa = idx2verlist[endpts[0]]; + pb = idx2verlist[endpts[1]]; + // Check if segment [a,b] already exists. + // TODO: Change the brute-force search. Slow! + point *ppt; + subsegs->traversalinit(); + segloop.sh = shellfacetraverse(subsegs); + while (segloop.sh != NULL) { + ppt = (point *) &(segloop.sh[3]); + if (((ppt[0] == pa) && (ppt[1] == pb)) || + ((ppt[0] == pb) && (ppt[1] == pa))) { + // Found! + newseg = segloop; + break; + } + segloop.sh = shellfacetraverse(subsegs); + } + if (newseg.sh == NULL) { + makeshellface(subsegs, &newseg); + setshvertices(newseg, pa, pb, NULL); + if (b->psc) { + if (pointtype(pa) == FREESEGVERTEX) { + setpoint2sh(pa, sencode(newseg)); + } + if (pointtype(pb) == FREESEGVERTEX) { + setpoint2sh(pb, sencode(newseg)); + } + } + } + } + + setshellmark(newseg, edgemarker); + + if (b->quality && (in->segmentconstraintlist != (REAL *) NULL)) { + for (i = 0; i < in->numberofsegmentconstraints; i++) { + e1 = (int) in->segmentconstraintlist[i * 3]; + e2 = (int) in->segmentconstraintlist[i * 3 + 1]; + if (((pointmark(pa) == e1) && (pointmark(pb) == e2)) || + ((pointmark(pa) == e2) && (pointmark(pb) == e1))) { + len = in->segmentconstraintlist[i * 3 + 2]; + setareabound(newseg, len); + break; + } + } + } + } // i + + + delete [] shperverlist; + delete [] idx2shlist; + + if (b->psc) { + // Removing all segments with a marker '-1'. + subsegs->traversalinit(); + segloop.sh = shellfacetraverse(subsegs); + while (segloop.sh != NULL) { + if (shellmark(segloop) == -1) { + shellfacedealloc(subsegs, segloop.sh); + } + segloop.sh = shellfacetraverse(subsegs); + } + + // Connecting subsegments at Steiner points. + face seg1, seg2; + // Re-use 'idx2shlist' and 'shperverlist'. + makepoint2submap(subsegs, idx2shlist, shperverlist); + + points->traversalinit(); + pa = pointtraverse(); + while (pa != NULL) { + if (pointtype(pa) == FREESEGVERTEX) { + idx = pointmark(pa) - in->firstnumber; + // There must be only two segments containing this vertex. + assert((idx2shlist[idx + 1] - idx2shlist[idx]) == 2); + i = idx2shlist[idx]; + seg1 = shperverlist[i]; + seg2 = shperverlist[i+1]; + senextself(seg1); + senextself(seg2); + sbond(seg1, seg2); + } + pa = pointtraverse(); + } + + delete [] shperverlist; + delete [] idx2shlist; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// meshsurface() Create a surface mesh of the input PLC. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::meshsurface() +{ + arraypool *ptlist, *conlist; + point *idx2verlist; + point tstart, tend, *pnewpt, *cons; + tetgenio::facet *f; + tetgenio::polygon *p; + int end1, end2; + int shmark, i, j; + + if (!b->quiet) { + printf("Creating surface mesh ...\n"); + } + + // Create a map from indices to points. + makeindex2pointmap(idx2verlist); + + // Initialize arrays (block size: 2^8 = 256). + ptlist = new arraypool(sizeof(point *), 8); + conlist = new arraypool(2 * sizeof(point *), 8); + + // Loop the facet list, triangulate each facet. + for (shmark = 1; shmark <= in->numberoffacets; shmark++) { + + // Get a facet F. + f = &in->facetlist[shmark - 1]; + + // Process the duplicated points first, they are marked with type + // DUPLICATEDVERTEX. If p and q are duplicated, and p'index > q's, + // then p is substituted by q. + if (dupverts > 0l) { + // Loop all polygons of this facet. + for (i = 0; i < f->numberofpolygons; i++) { + p = &(f->polygonlist[i]); + // Loop other vertices of this polygon. + for (j = 0; j < p->numberofvertices; j++) { + end1 = p->vertexlist[j]; + tstart = idx2verlist[end1]; + if (pointtype(tstart) == DUPLICATEDVERTEX) { + // Reset the index of vertex-j. + tend = point2ppt(tstart); + end2 = pointmark(tend); + p->vertexlist[j] = end2; + } + } + } + } + + // Loop polygons of F, get the set of vertices and segments. + for (i = 0; i < f->numberofpolygons; i++) { + // Get a polygon. + p = &(f->polygonlist[i]); + // Get the first vertex. + end1 = p->vertexlist[0]; + if ((end1 < in->firstnumber) || + (end1 >= in->firstnumber + in->numberofpoints)) { + if (!b->quiet) { + printf("Warning: Invalid the 1st vertex %d of polygon", end1); + printf(" %d in facet %d.\n", i + 1, shmark); + } + continue; // Skip this polygon. + } + tstart = idx2verlist[end1]; + // Add tstart to V if it haven't been added yet. + if (!pinfected(tstart)) { + pinfect(tstart); + ptlist->newindex((void **) &pnewpt); + *pnewpt = tstart; + } + // Loop other vertices of this polygon. + for (j = 1; j <= p->numberofvertices; j++) { + // get a vertex. + if (j < p->numberofvertices) { + end2 = p->vertexlist[j]; + } else { + end2 = p->vertexlist[0]; // Form a loop from last to first. + } + if ((end2 < in->firstnumber) || + (end2 >= in->firstnumber + in->numberofpoints)) { + if (!b->quiet) { + printf("Warning: Invalid vertex %d in polygon %d", end2, i + 1); + printf(" in facet %d.\n", shmark); + } + } else { + if (end1 != end2) { + // 'end1' and 'end2' form a segment. + tend = idx2verlist[end2]; + // Add tstart to V if it haven't been added yet. + if (!pinfected(tend)) { + pinfect(tend); + ptlist->newindex((void **) &pnewpt); + *pnewpt = tend; + } + // Save the segment in S (conlist). + conlist->newindex((void **) &cons); + cons[0] = tstart; + cons[1] = tend; + // Set the start for next continuous segment. + end1 = end2; + tstart = tend; + } else { + // Two identical vertices mean an isolated vertex of F. + if (p->numberofvertices > 2) { + // This may be an error in the input, anyway, we can continue + // by simply skipping this segment. + if (!b->quiet) { + printf("Warning: Polygon %d has two identical verts", i + 1); + printf(" in facet %d.\n", shmark); + } + } + // Ignore this vertex. + } + } + // Is the polygon degenerate (a segment or a vertex)? + if (p->numberofvertices == 2) break; + } + } + // Unmark vertices. + for (i = 0; i < ptlist->objects; i++) { + pnewpt = (point *) fastlookup(ptlist, i); + puninfect(*pnewpt); + } + + // Triangulate F into a CDT. + triangulate(shmark, ptlist, conlist, f->numberofholes, f->holelist); + + // Clear working lists. + ptlist->restart(); + conlist->restart(); + } + + if (!b->diagnose) { + // Remove redundant segments and build the face links. + unifysegments(); + if (!b->psc && !b->nomergefacet && !b->nobisect) { + // Merge adjacent coplanar facets. + mergefacets(); + } + if (in->numberofedges > 0) { // if (b->psc) + // There are segments specified by the user. Read and create them. + identifypscedges(idx2verlist); + } + if (!b->psc) { + // Mark all segment vertices to be RIDGEVERTEX. + face segloop; + point *ppt; + subsegs->traversalinit(); + segloop.sh = shellfacetraverse(subsegs); + while (segloop.sh != NULL) { + ppt = (point *) &(segloop.sh[3]); + setpointtype(ppt[0], RIDGEVERTEX); + setpointtype(ppt[1], RIDGEVERTEX); + segloop.sh = shellfacetraverse(subsegs); + } + } + } + + if (b->object == tetgenbehavior::STL) { + // Remove redundant vertices (for .stl input mesh). + jettisonnodes(); + } + + if (b->verbose) { + printf(" %ld (%ld) subfaces (segments).\n", subfaces->items, + subsegs->items); + } + + // The total number of iunput segments. + insegments = subsegs->items; + + delete [] idx2verlist; + delete ptlist; + delete conlist; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// interecursive() Recursively do intersection test on a set of triangles.// +// // +// Recursively split the set 'subfacearray' of subfaces into two sets using // +// a cut plane parallel to x-, or, y-, or z-axis. The split criteria are // +// follows. Assume the cut plane is H, and H+ denotes the left halfspace of // +// H, and H- denotes the right halfspace of H; and s be a subface: // +// // +// (1) If all points of s lie at H+, put it into left array; // +// (2) If all points of s lie at H-, put it into right array; // +// (3) If some points of s lie at H+ and some of lie at H-, or some // +// points lie on H, put it into both arraies. // +// // +// Partitions by x-axis if axis == '0'; by y-axis if axis == '1'; by z-axis // +// if axis == '2'. If current cut plane is parallel to the x-axis, the next // +// one will be parallel to y-axis, and the next one after the next is z-axis,// +// and then alternately return back to x-axis. // +// // +// Stop splitting when the number of triangles of the input array is not // +// decreased anymore. Do tests on the current set. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::interecursive(shellface** subfacearray, int arraysize, + int axis, REAL bxmin, REAL bxmax, REAL bymin, + REAL bymax, REAL bzmin, REAL bzmax, + int* internum) +{ + shellface **leftarray, **rightarray; + face sface1, sface2; + point p1, p2, p3; + point p4, p5, p6; + enum interresult intersect; + REAL split; + bool toleft, toright; + int leftsize, rightsize; + int i, j; + + if (b->verbose > 2) { + printf(" Recur %d faces. Bbox (%g, %g, %g),(%g, %g, %g). %s-axis\n", + arraysize, bxmin, bymin, bzmin, bxmax, bymax, bzmax, + axis == 0 ? "x" : (axis == 1 ? "y" : "z")); + } + + leftarray = new shellface*[arraysize]; + if (leftarray == NULL) { + terminatetetgen(this, 1); + } + rightarray = new shellface*[arraysize]; + if (rightarray == NULL) { + terminatetetgen(this, 1); + } + leftsize = rightsize = 0; + + if (axis == 0) { + // Split along x-axis. + split = 0.5 * (bxmin + bxmax); + } else if (axis == 1) { + // Split along y-axis. + split = 0.5 * (bymin + bymax); + } else { + // Split along z-axis. + split = 0.5 * (bzmin + bzmax); + } + + for (i = 0; i < arraysize; i++) { + sface1.sh = subfacearray[i]; + p1 = (point) sface1.sh[3]; + p2 = (point) sface1.sh[4]; + p3 = (point) sface1.sh[5]; + toleft = toright = false; + if (p1[axis] < split) { + toleft = true; + if (p2[axis] >= split || p3[axis] >= split) { + toright = true; + } + } else if (p1[axis] > split) { + toright = true; + if (p2[axis] <= split || p3[axis] <= split) { + toleft = true; + } + } else { + // p1[axis] == split; + toleft = true; + toright = true; + } + // At least one is true; + assert(!(toleft == false && toright == false)); + if (toleft) { + leftarray[leftsize] = sface1.sh; + leftsize++; + } + if (toright) { + rightarray[rightsize] = sface1.sh; + rightsize++; + } + } + + if (leftsize < arraysize && rightsize < arraysize) { + // Continue to partition the input set. Now 'subfacearray' has been + // split into two sets, it's memory can be freed. 'leftarray' and + // 'rightarray' will be freed in the next recursive (after they're + // partitioned again or performing tests). + delete [] subfacearray; + // Continue to split these two sets. + if (axis == 0) { + interecursive(leftarray, leftsize, 1, bxmin, split, bymin, bymax, + bzmin, bzmax, internum); + interecursive(rightarray, rightsize, 1, split, bxmax, bymin, bymax, + bzmin, bzmax, internum); + } else if (axis == 1) { + interecursive(leftarray, leftsize, 2, bxmin, bxmax, bymin, split, + bzmin, bzmax, internum); + interecursive(rightarray, rightsize, 2, bxmin, bxmax, split, bymax, + bzmin, bzmax, internum); + } else { + interecursive(leftarray, leftsize, 0, bxmin, bxmax, bymin, bymax, + bzmin, split, internum); + interecursive(rightarray, rightsize, 0, bxmin, bxmax, bymin, bymax, + split, bzmax, internum); + } + } else { + if (b->verbose > 1) { + printf(" Checking intersecting faces.\n"); + } + // Perform a brute-force compare on the set. + for (i = 0; i < arraysize; i++) { + sface1.sh = subfacearray[i]; + p1 = (point) sface1.sh[3]; + p2 = (point) sface1.sh[4]; + p3 = (point) sface1.sh[5]; + for (j = i + 1; j < arraysize; j++) { + sface2.sh = subfacearray[j]; + p4 = (point) sface2.sh[3]; + p5 = (point) sface2.sh[4]; + p6 = (point) sface2.sh[5]; + intersect = (enum interresult) tri_tri_inter(p1, p2, p3, p4, p5, p6); + if (intersect == INTERSECT || intersect == SHAREFACE) { + if (!b->quiet) { + if (intersect == INTERSECT) { + printf(" Facet #%d intersects facet #%d at triangles:\n", + shellmark(sface1), shellmark(sface2)); + printf(" (%4d, %4d, %4d) and (%4d, %4d, %4d)\n", + pointmark(p1), pointmark(p2), pointmark(p3), + pointmark(p4), pointmark(p5), pointmark(p6)); + } else { + printf(" Facet #%d duplicates facet #%d at triangle:\n", + shellmark(sface1), shellmark(sface2)); + printf(" (%4d, %4d, %4d) and (%4d, %4d, %4d)\n", + pointmark(p1), pointmark(p2), pointmark(p3), + pointmark(p4), pointmark(p5), pointmark(p6)); + } + } + // Increase the number of intersecting pairs. + (*internum)++; + // Infect these two faces (although they may already be infected). + sinfect(sface1); + sinfect(sface2); + } + } + } + // Don't forget to free all three arrays. No further partition. + delete [] leftarray; + delete [] rightarray; + delete [] subfacearray; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// detectinterfaces() Detect intersecting triangles. // +// // +// Given a set of triangles, find the pairs of intersecting triangles from // +// them. Here the set of triangles is in 'subfaces' which is a surface mesh // +// of a PLC (.poly or .smesh). // +// // +// To detect whether two triangles are intersecting is done by the routine // +// 'tri_tri_inter()'. The algorithm for the test is very simple and stable. // +// It is based on geometric orientation test which uses exact arithmetics. // +// // +// Use divide-and-conquer algorithm for reducing the number of intersection // +// tests. Start from the bounding box of the input point set, recursively // +// partition the box into smaller boxes, until the number of triangles in a // +// box is not decreased anymore. Then perform triangle-triangle tests on the // +// remaining set of triangles. The memory allocated in the input set is // +// freed immediately after it has been partitioned into two arrays. So it // +// can be re-used for the consequent partitions. // +// // +// On return, the pool 'subfaces' will be cleared, and only the intersecting // +// triangles remain for output (to a .face file). // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::detectinterfaces() +{ + shellface **subfacearray; + face shloop; + int internum; + int i; + + if (!b->quiet) { + printf("Detecting self-intersecting facets...\n"); + } + + // Construct a map from indices to subfaces; + subfacearray = new shellface*[subfaces->items]; + subfaces->traversalinit(); + shloop.sh = shellfacetraverse(subfaces); + i = 0; + while (shloop.sh != (shellface *) NULL) { + subfacearray[i] = shloop.sh; + shloop.sh = shellfacetraverse(subfaces); + i++; + } + + internum = 0; + // Recursively split the set of triangles into two sets using a cut plane + // parallel to x-, or, y-, or z-axis. Stop splitting when the number + // of subfaces is not decreasing anymore. Do tests on the current set. + interecursive(subfacearray, subfaces->items, 0, xmin, xmax, ymin, ymax, + zmin, zmax, &internum); + + if (!b->quiet) { + if (internum > 0) { + printf("\n!! Found %d pairs of faces are intersecting.\n\n", internum); + } else { + printf("\nNo faces are intersecting.\n\n"); + } + } + + if (internum > 0) { + // Traverse all subfaces, deallocate those have not been infected (they + // are not intersecting faces). Uninfect those have been infected. + // After this loop, only intersecting faces remain. + subfaces->traversalinit(); + shloop.sh = shellfacetraverse(subfaces); + while (shloop.sh != (shellface *) NULL) { + if (sinfected(shloop)) { + suninfect(shloop); + } else { + shellfacedealloc(subfaces, shloop.sh); + } + shloop.sh = shellfacetraverse(subfaces); + } + } else { + // Deallocate all subfaces. + subfaces->restart(); + } +} + +//// //// +//// //// +//// surface_cxx ////////////////////////////////////////////////////////////// + +//// constrained_cxx ////////////////////////////////////////////////////////// +//// //// +//// //// + +/////////////////////////////////////////////////////////////////////////////// +// // +// makesegmentendpointsmap() Create a map from a segment to its endpoints.// +// // +// The map is saved in the array 'segmentendpointslist'. The length of this // +// array is twice the number of segments. Each segment is assigned a unique // +// index (starting from 0). // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::makesegmentendpointsmap() +{ + arraypool *segptlist; + face segloop, prevseg, nextseg; + point eorg, edest, *parypt; + int segindex = 0, idx = 0; + int i; + + if (b->verbose > 0) { + printf(" Creating the segment-endpoints map.\n"); + } + + segptlist = new arraypool(2 * sizeof(point), 10); + + // A segment s may have been split into many subsegments. Operate the one + // which contains the origin of s. Then mark the rest of subsegments. + subsegs->traversalinit(); + segloop.sh = shellfacetraverse(subsegs); + segloop.shver = 0; + while (segloop.sh != NULL) { + senext2(segloop, prevseg); + spivotself(prevseg); + if (prevseg.sh == NULL) { + eorg = sorg(segloop); + edest = sdest(segloop); + setfacetindex(segloop, segindex); + senext(segloop, nextseg); + spivotself(nextseg); + while (nextseg.sh != NULL) { + setfacetindex(nextseg, segindex); + nextseg.shver = 0; + if (sorg(nextseg) != edest) sesymself(nextseg); + assert(sorg(nextseg) == edest); + edest = sdest(nextseg); + // Go the next connected subsegment at edest. + senextself(nextseg); + spivotself(nextseg); + } + segptlist->newindex((void **) &parypt); + parypt[0] = eorg; + parypt[1] = edest; + segindex++; + } + segloop.sh = shellfacetraverse(subsegs); + } + + if (b->verbose) { + printf(" Found %ld segments.\n", segptlist->objects); + } + + segmentendpointslist = new point[segptlist->objects * 2]; + + totalworkmemory += (segptlist->objects * 2) * sizeof(point *); + + for (i = 0; i < segptlist->objects; i++) { + parypt = (point *) fastlookup(segptlist, i); + segmentendpointslist[idx++] = parypt[0]; + segmentendpointslist[idx++] = parypt[1]; + } + + delete segptlist; +} + + +/////////////////////////////////////////////////////////////////////////////// +// // +// finddirection() Find the tet on the path from one point to another. // +// // +// The path starts from 'searchtet''s origin and ends at 'endpt'. On finish, // +// 'searchtet' contains a tet on the path, its origin does not change. // +// // +// The return value indicates one of the following cases (let 'searchtet' be // +// abcd, a is the origin of the path): // +// - ACROSSVERT, edge ab is collinear with the path; // +// - ACROSSEDGE, edge bc intersects with the path; // +// - ACROSSFACE, face bcd intersects with the path. // +// // +// WARNING: This routine is designed for convex triangulations, and will not // +// generally work after the holes and concavities have been carved. // +// // +/////////////////////////////////////////////////////////////////////////////// + +enum tetgenmesh::interresult + tetgenmesh::finddirection(triface* searchtet, point endpt) +{ + triface neightet; + point pa, pb, pc, pd; + enum {HMOVE, RMOVE, LMOVE} nextmove; + REAL hori, rori, lori; + int t1ver; + int s; + + // The origin is fixed. + pa = org(*searchtet); + if ((point) searchtet->tet[7] == dummypoint) { + // A hull tet. Choose the neighbor of its base face. + decode(searchtet->tet[3], *searchtet); + // Reset the origin to be pa. + if ((point) searchtet->tet[4] == pa) { + searchtet->ver = 11; + } else if ((point) searchtet->tet[5] == pa) { + searchtet->ver = 3; + } else if ((point) searchtet->tet[6] == pa) { + searchtet->ver = 7; + } else { + assert((point) searchtet->tet[7] == pa); + searchtet->ver = 0; + } + } + + pb = dest(*searchtet); + // Check whether the destination or apex is 'endpt'. + if (pb == endpt) { + // pa->pb is the search edge. + return ACROSSVERT; + } + + pc = apex(*searchtet); + if (pc == endpt) { + // pa->pc is the search edge. + eprevesymself(*searchtet); + return ACROSSVERT; + } + + // Walk through tets around pa until the right one is found. + while (1) { + + pd = oppo(*searchtet); + // Check whether the opposite vertex is 'endpt'. + if (pd == endpt) { + // pa->pd is the search edge. + esymself(*searchtet); + enextself(*searchtet); + return ACROSSVERT; + } + // Check if we have entered outside of the domain. + if (pd == dummypoint) { + // This is possible when the mesh is non-convex. + assert(nonconvex); + return ACROSSSUB; // Hit a bounday. + } + + // Now assume that the base face abc coincides with the horizon plane, + // and d lies above the horizon. The search point 'endpt' may lie + // above or below the horizon. We test the orientations of 'endpt' + // with respect to three planes: abc (horizon), bad (right plane), + // and acd (left plane). + hori = orient3d(pa, pb, pc, endpt); + rori = orient3d(pb, pa, pd, endpt); + lori = orient3d(pa, pc, pd, endpt); + + // Now decide the tet to move. It is possible there are more than one + // tets are viable moves. Is so, randomly choose one. + if (hori > 0) { + if (rori > 0) { + if (lori > 0) { + // Any of the three neighbors is a viable move. + s = randomnation(3); + if (s == 0) { + nextmove = HMOVE; + } else if (s == 1) { + nextmove = RMOVE; + } else { + nextmove = LMOVE; + } + } else { + // Two tets, below horizon and below right, are viable. + //s = randomnation(2); + if (randomnation(2)) { + nextmove = HMOVE; + } else { + nextmove = RMOVE; + } + } + } else { + if (lori > 0) { + // Two tets, below horizon and below left, are viable. + //s = randomnation(2); + if (randomnation(2)) { + nextmove = HMOVE; + } else { + nextmove = LMOVE; + } + } else { + // The tet below horizon is chosen. + nextmove = HMOVE; + } + } + } else { + if (rori > 0) { + if (lori > 0) { + // Two tets, below right and below left, are viable. + //s = randomnation(2); + if (randomnation(2)) { + nextmove = RMOVE; + } else { + nextmove = LMOVE; + } + } else { + // The tet below right is chosen. + nextmove = RMOVE; + } + } else { + if (lori > 0) { + // The tet below left is chosen. + nextmove = LMOVE; + } else { + // 'endpt' lies either on the plane(s) or across face bcd. + if (hori == 0) { + if (rori == 0) { + // pa->'endpt' is COLLINEAR with pa->pb. + return ACROSSVERT; + } + if (lori == 0) { + // pa->'endpt' is COLLINEAR with pa->pc. + eprevesymself(*searchtet); // // [a,c,d] + return ACROSSVERT; + } + // pa->'endpt' crosses the edge pb->pc. + return ACROSSEDGE; + } + if (rori == 0) { + if (lori == 0) { + // pa->'endpt' is COLLINEAR with pa->pd. + esymself(*searchtet); // face bad. + enextself(*searchtet); // face [a,d,b] + return ACROSSVERT; + } + // pa->'endpt' crosses the edge pb->pd. + esymself(*searchtet); // face bad. + enextself(*searchtet); // face adb + return ACROSSEDGE; + } + if (lori == 0) { + // pa->'endpt' crosses the edge pc->pd. + eprevesymself(*searchtet); // [a,c,d] + return ACROSSEDGE; + } + // pa->'endpt' crosses the face bcd. + return ACROSSFACE; + } + } + } + + // Move to the next tet, fix pa as its origin. + if (nextmove == RMOVE) { + fnextself(*searchtet); + } else if (nextmove == LMOVE) { + eprevself(*searchtet); + fnextself(*searchtet); + enextself(*searchtet); + } else { // HMOVE + fsymself(*searchtet); + enextself(*searchtet); + } + assert(org(*searchtet) == pa); + pb = dest(*searchtet); + pc = apex(*searchtet); + + } // while (1) + +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// scoutsegment() Search an edge in the tetrahedralization. // +// // +// If the edge is found, it returns SHAREEDGE, and 'searchtet' returns the // +// edge from startpt to endpt. // +// // +// If the edge is missing, it returns either ACROSSEDGE or ACROSSFACE, which // +// indicates that the edge intersects an edge or a face. If 'refpt' is NULL,// +// 'searchtet' returns the edge or face. If 'refpt' is not NULL, it returns // +// a vertex which encroaches upon this edge, and 'searchtet' returns a tet // +// which containing 'refpt'. // +// // +// The following cases can happen when the input PLC is not valid. // +// - ACROSSVERT, the edge intersects a vertex return by the origin of // +// 'searchtet'. // +// - ACROSSSEG, the edge intersects a segment returned by 'searchtet'. // +// - ACROSSSUB, the edge intersects a subface returned by 'searchtet'. // +// // +/////////////////////////////////////////////////////////////////////////////// + +enum tetgenmesh::interresult + tetgenmesh::scoutsegment(point startpt, point endpt, triface* searchtet, + point* refpt, arraypool* intfacelist) +{ + point pd; + enum interresult dir; + int t1ver; + + if (b->verbose > 2) { + printf(" Scout seg (%d, %d).\n",pointmark(startpt),pointmark(endpt)); + } + + point2tetorg(startpt, *searchtet); + dir = finddirection(searchtet, endpt); + + if (dir == ACROSSVERT) { + pd = dest(*searchtet); + if (pd == endpt) { + // The job is done. + return SHAREEDGE; + } else { + // A point is on the path. + // Let the origin of the searchtet be the vertex. + enextself(*searchtet); + if (refpt) *refpt = pd; + return ACROSSVERT; + } + } // if (dir == ACROSSVERT) + + // dir is either ACROSSEDGE or ACROSSFACE. + + enextesymself(*searchtet); // Go to the opposite face. + fsymself(*searchtet); // Enter the adjacent tet. + + if (dir == ACROSSEDGE) { + // Check whether two segments are intersecting. + if (issubseg(*searchtet)) { + return ACROSSSEG; + } + } else if (dir == ACROSSFACE) { + if (checksubfaceflag) { + // Check whether a segment and a subface are intersecting. + if (issubface(*searchtet)) { + return ACROSSSUB; + } + } + } + + if (refpt == NULL) { + // Do not need a reference point. Return. + return dir; + } + + triface neightet, reftet; + point pa, pb, pc; + REAL angmax, ang; + int types[2], poss[4]; + int pos = 0, i, j; + + pa = org(*searchtet); + angmax = interiorangle(pa, startpt, endpt, NULL); + *refpt = pa; + pb = dest(*searchtet); + ang = interiorangle(pb, startpt, endpt, NULL); + if (ang > angmax) { + angmax = ang; + *refpt = pb; + } + pc = apex(*searchtet); + ang = interiorangle(pc, startpt, endpt, NULL); + if (ang > angmax) { + angmax = ang; + *refpt = pc; + } + reftet = *searchtet; // Save the tet containing the refpt. + + // Search intersecting faces along the segment. + while (1) { + + + pd = oppo(*searchtet); + assert(pd != dummypoint); // SELF_CHECK + + + // Stop if we meet 'endpt'. + if (pd == endpt) break; + + ang = interiorangle(pd, startpt, endpt, NULL); + if (ang > angmax) { + angmax = ang; + *refpt = pd; + reftet = *searchtet; + } + + // Find a face intersecting the segment. + if (dir == ACROSSFACE) { + // One of the three oppo faces in 'searchtet' intersects the segment. + neightet = *searchtet; + j = (neightet.ver & 3); // j is the current face number. + for (i = j + 1; i < j + 4; i++) { + neightet.ver = (i % 4); + pa = org(neightet); + pb = dest(neightet); + pc = apex(neightet); + pd = oppo(neightet); // The above point. + if (tri_edge_test(pa, pb, pc, startpt, endpt, pd, 1, types, poss)) { + dir = (enum interresult) types[0]; + pos = poss[0]; + break; + } else { + dir = DISJOINT; + pos = 0; + } + } + assert(dir != DISJOINT); // SELF_CHECK + } else { // dir == ACROSSEDGE + // Check the two opposite faces (of the edge) in 'searchtet'. + for (i = 0; i < 2; i++) { + if (i == 0) { + enextesym(*searchtet, neightet); + } else { + eprevesym(*searchtet, neightet); + } + pa = org(neightet); + pb = dest(neightet); + pc = apex(neightet); + pd = oppo(neightet); // The above point. + if (tri_edge_test(pa, pb, pc, startpt, endpt, pd, 1, types, poss)) { + dir = (enum interresult) types[0]; + pos = poss[0]; + break; + } else { + dir = DISJOINT; + pos = 0; + } + } + if (dir == DISJOINT) { + // No intersection. Rotate to the next tet at the edge. + dir = ACROSSEDGE; + fnextself(*searchtet); + continue; + } + } + + if (dir == ACROSSVERT) { + // This segment passing a vertex. Choose it and return. + for (i = 0; i < pos; i++) { + enextself(neightet); + } + pd = org(neightet); + *refpt = pd; + // break; + return ACROSSVERT; + } else if (dir == ACROSSEDGE) { + // Get the edge intersects with the segment. + for (i = 0; i < pos; i++) { + enextself(neightet); + } + } + // Go to the next tet. + fsym(neightet, *searchtet); + + if (dir == ACROSSEDGE) { + // Check whether two segments are intersecting. + if (issubseg(*searchtet)) { + return ACROSSSEG; + } + } else if (dir == ACROSSFACE) { + if (checksubfaceflag) { + // Check whether a segment and a subface are intersecting. + if (issubface(*searchtet)) { + return ACROSSSUB; + } + } + } + + } // while (1) + + // A valid reference point should inside the diametrial circumsphere of + // the missing segment, i.e., it encroaches upon it. + if (2.0 * angmax < PI) { + *refpt = NULL; + } + + + *searchtet = reftet; + return dir; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// getsteinerpointonsegment() Get a Steiner point on a segment. // +// // +// Return '1' if 'refpt' lies on an adjacent segment of this segment. Other- // +// wise, return '0'. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::getsteinerptonsegment(face* seg, point refpt, point steinpt) +{ + point ei = sorg(*seg); + point ej = sdest(*seg); + int adjflag = 0, i; + + if (refpt != NULL) { + REAL L, L1, t; + + if (pointtype(refpt) == FREESEGVERTEX) { + face parentseg; + sdecode(point2sh(refpt), parentseg); + int sidx1 = getfacetindex(parentseg); + point far_pi = segmentendpointslist[sidx1 * 2]; + point far_pj = segmentendpointslist[sidx1 * 2 + 1]; + int sidx2 = getfacetindex(*seg); + point far_ei = segmentendpointslist[sidx2 * 2]; + point far_ej = segmentendpointslist[sidx2 * 2 + 1]; + if ((far_pi == far_ei) || (far_pj == far_ei)) { + // Create a Steiner point at the intersection of the segment + // [far_ei, far_ej] and the sphere centered at far_ei with + // radius |far_ei - refpt|. + L = distance(far_ei, far_ej); + L1 = distance(far_ei, refpt); + t = L1 / L; + for (i = 0; i < 3; i++) { + steinpt[i] = far_ei[i] + t * (far_ej[i] - far_ei[i]); + } + adjflag = 1; + } else if ((far_pi == far_ej) || (far_pj == far_ej)) { + L = distance(far_ei, far_ej); + L1 = distance(far_ej, refpt); + t = L1 / L; + for (i = 0; i < 3; i++) { + steinpt[i] = far_ej[i] + t * (far_ei[i] - far_ej[i]); + } + adjflag = 1; + } else { + // Cut the segment by the projection point of refpt. + projpt2edge(refpt, ei, ej, steinpt); + } + } else { + // Cut the segment by the projection point of refpt. + projpt2edge(refpt, ei, ej, steinpt); + } + + // Make sure that steinpt is not too close to ei and ej. + L = distance(ei, ej); + L1 = distance(steinpt, ei); + t = L1 / L; + if ((t < 0.2) || (t > 0.8)) { + // Split the point at the middle. + for (i = 0; i < 3; i++) { + steinpt[i] = ei[i] + 0.5 * (ej[i] - ei[i]); + } + } + } else { + // Split the point at the middle. + for (i = 0; i < 3; i++) { + steinpt[i] = ei[i] + 0.5 * (ej[i] - ei[i]); + } + } + + + return adjflag; +} + + + +/////////////////////////////////////////////////////////////////////////////// +// // +// delaunizesegments() Recover segments in a DT. // +// // +// All segments need to be recovered are in 'subsegstack' (Q). They will be // +// be recovered one by one (in a random order). // +// // +// Given a segment s in the Q, this routine first queries s in the DT, if s // +// matches an edge in DT, it is 'locked' at the edge. Otherwise, s is split // +// by inserting a new point p in both the DT and itself. The two new subseg- // +// ments of s are queued in Q. The process continues until Q is empty. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::delaunizesegments() +{ + triface searchtet, spintet; + face searchsh; + face sseg, *psseg; + point refpt, newpt; + enum interresult dir; + insertvertexflags ivf; + int t1ver; + + + ivf.bowywat = 1; // Use Bowyer-Watson insertion. + ivf.assignmeshsize = b->metric; + ivf.sloc = (int) ONEDGE; // on 'sseg'. + ivf.sbowywat = 1; // Use Bowyer-Watson insertion. + + // Loop until 'subsegstack' is empty. + while (subsegstack->objects > 0l) { + // seglist is used as a stack. + subsegstack->objects--; + psseg = (face *) fastlookup(subsegstack, subsegstack->objects); + sseg = *psseg; + + // Check if this segment has been recovered. + sstpivot1(sseg, searchtet); + if (searchtet.tet != NULL) { + continue; // Not a missing segment. + } + + // Search the segment. + dir = scoutsegment(sorg(sseg), sdest(sseg), &searchtet, &refpt, NULL); + + if (dir == SHAREEDGE) { + // Found this segment, insert it. + if (!issubseg(searchtet)) { + // Let the segment remember an adjacent tet. + sstbond1(sseg, searchtet); + // Bond the segment to all tets containing it. + spintet = searchtet; + do { + tssbond1(spintet, sseg); + fnextself(spintet); + } while (spintet.tet != searchtet.tet); + } else { + // Collision! Maybe a bug. + assert(0); + } + } else { + if ((dir == ACROSSFACE) || (dir == ACROSSEDGE)) { + // The segment is missing. Split it. + // Create a new point. + makepoint(&newpt, FREESEGVERTEX); + //setpointtype(newpt, FREESEGVERTEX); + getsteinerptonsegment(&sseg, refpt, newpt); + + // Start searching from 'searchtet'. + ivf.iloc = (int) OUTSIDE; + // Insert the new point into the tetrahedralization T. + // Missing segments and subfaces are queued for recovery. + // Note that T is convex (nonconvex = 0). + if (insertpoint(newpt, &searchtet, &searchsh, &sseg, &ivf)) { + // The new point has been inserted. + st_segref_count++; + if (steinerleft > 0) steinerleft--; + } else { + assert (ivf.iloc == (enum locateresult) NEARVERTEX); + terminatetetgen(this, 4); + } + } else { + // Indicate it is an input problem. + terminatetetgen(this, 3); + } + } + } // while +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// scoutsubface() Search subface in the tetrahedralization. // +// // +// 'searchsh' is searched in T. If it exists, it is 'locked' at the face in // +// T. 'searchtet' refers to the face. Otherwise, it is missing. // +// // +// The return value indicates one of the following cases: // +// - SHAREFACE, 'searchsh' exists and is inserted in T. // +// - COLLISIONFACE, 'searchsh' exists in T, but it conflicts with another // +// subface which was inserted earlier. It is not inserted. // +// // +/////////////////////////////////////////////////////////////////////////////// + +enum tetgenmesh::interresult + tetgenmesh::scoutsubface(face* searchsh, triface* searchtet) +{ + triface spintet; + point pa, pb, pc; + enum interresult dir; + int t1ver; + + pa = sorg(*searchsh); + pb = sdest(*searchsh); + + + // Get a tet whose origin is a. + point2tetorg(pa, *searchtet); + // Search the edge [a,b]. + dir = finddirection(searchtet, pb); + if (dir == ACROSSVERT) { + // Check validity of a PLC. + if (dest(*searchtet) != pb) { + // A vertex lies on the search edge. + enextself(*searchtet); + // It is possible a PLC self-intersection problem. + terminatetetgen(this, 3); + return TOUCHEDGE; + } + // The edge exists. Check if the face exists. + pc = sapex(*searchsh); + // Searchtet holds edge [a,b]. Search a face with apex c. + spintet = *searchtet; + while (1) { + if (apex(spintet) == pc) { + // Found a face matching to 'searchsh'! + if (!issubface(spintet)) { + // Insert 'searchsh'. + tsbond(spintet, *searchsh); + fsymself(spintet); + sesymself(*searchsh); + tsbond(spintet, *searchsh); + *searchtet = spintet; + return SHAREFACE; + } else { + // Another subface is already inserted. + face checksh; + tspivot(spintet, checksh); + assert(checksh.sh != searchsh->sh); // SELF_CHECK + // This is possibly an input problem, i.e., two facets overlap. + // Report this problem and exit. + printf("Warning: Found two facets nearly overlap.\n"); + terminatetetgen(this, 5); + // unifysubfaces(&checksh, searchsh); + *searchtet = spintet; + return COLLISIONFACE; + } + } + fnextself(spintet); + if (spintet.tet == searchtet->tet) break; + } + } + + // dir is either ACROSSEDGE or ACROSSFACE. + return dir; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// formregion() Form the missing region of a missing subface. // +// // +// 'missh' is a missing subface. From it we form a missing region R which is // +// a connected region formed by a set of missing subfaces of a facet. // +// Comment: There should be no segment inside R. // +// // +// 'missingshs' returns the list of subfaces in R. All subfaces in this list // +// are oriented as the 'missh'. 'missingshbds' returns the list of boundary // +// edges (tetrahedral handles) of R. 'missingshverts' returns all vertices // +// of R. They are all pmarktested. // +// // +// Except the first one (which is 'missh') in 'missingshs', each subface in // +// this list represents an internal edge of R, i.e., it is missing in the // +// tetrahedralization. Since R may contain interior vertices, not all miss- // +// ing edges can be found by this way. // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::formregion(face* missh, arraypool* missingshs, + arraypool* missingshbds, arraypool* missingshverts) +{ + triface searchtet, spintet; + face neighsh, *parysh; + face neighseg, fakeseg; + point pa, pb, *parypt; + enum interresult dir; + int t1ver; + int i, j; + + smarktest(*missh); + missingshs->newindex((void **) &parysh); + *parysh = *missh; + + // Incrementally find other missing subfaces. + for (i = 0; i < missingshs->objects; i++) { + missh = (face *) fastlookup(missingshs, i); + for (j = 0; j < 3; j++) { + pa = sorg(*missh); + pb = sdest(*missh); + point2tetorg(pa, searchtet); + dir = finddirection(&searchtet, pb); + if (dir != ACROSSVERT) { + // This edge is missing. Its neighbor is a missing subface. + spivot(*missh, neighsh); + if (!smarktested(neighsh)) { + // Adjust the face orientation. + if (sorg(neighsh) != pb) sesymself(neighsh); + smarktest(neighsh); + missingshs->newindex((void **) &parysh); + *parysh = neighsh; + } + } else { + if (dest(searchtet) != pb) { + // This might be a self-intersection problem. + terminatetetgen(this, 3); + } + } + // Collect the vertices of R. + if (!pmarktested(pa)) { + pmarktest(pa); + missingshverts->newindex((void **) &parypt); + *parypt = pa; + } + senextself(*missh); + } // j + } // i + + // Get the boundary edges of R. + for (i = 0; i < missingshs->objects; i++) { + missh = (face *) fastlookup(missingshs, i); + for (j = 0; j < 3; j++) { + spivot(*missh, neighsh); + if ((neighsh.sh == NULL) || !smarktested(neighsh)) { + // A boundary edge of R. + // Let the segment point to the adjacent tet. + point2tetorg(sorg(*missh), searchtet); + finddirection(&searchtet, sdest(*missh)); + missingshbds->newindex((void **) &parysh); + *parysh = *missh; + // Check if this edge is a segment. + sspivot(*missh, neighseg); + if (neighseg.sh == NULL) { + // Temporarily create a segment at this edge. + makeshellface(subsegs, &fakeseg); + setsorg(fakeseg, sorg(*missh)); + setsdest(fakeseg, sdest(*missh)); + sinfect(fakeseg); // Mark it as faked. + // Connect it to all tets at this edge. + spintet = searchtet; + while (1) { + tssbond1(spintet, fakeseg); + fnextself(spintet); + if (spintet.tet == searchtet.tet) break; + } + neighseg = fakeseg; + } + // Let the segment and the boundary edge point to each other. + ssbond(*missh, neighseg); + sstbond1(neighseg, searchtet); + } + senextself(*missh); + } // j + } // i + + + // Unmarktest collected missing subfaces. + for (i = 0; i < missingshs->objects; i++) { + parysh = (face *) fastlookup(missingshs, i); + sunmarktest(*parysh); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// scoutcrossedge() Search an edge that crosses the missing region. // +// // +// Return 1 if a crossing edge is found. It is returned by 'crosstet'. More- // +// over, the edge is oriented such that its origin lies below R. Return 0 // +// if no such edge is found. // +// // +// Assumption: All vertices of the missing region are marktested. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::scoutcrossedge(triface& crosstet, arraypool* missingshbds, + arraypool* missingshs) +{ + triface searchtet, spintet; + face *parysh; + face neighseg; + point pa, pb, pc, pd, pe; + enum interresult dir; + REAL ori; + int types[2], poss[4]; + int searchflag, interflag; + int t1ver; + int i, j; + + searchflag = 0; + + for (j = 0; j < missingshbds->objects && !searchflag; j++) { + parysh = (face *) fastlookup(missingshbds, j); + sspivot(*parysh, neighseg); + sstpivot1(neighseg, searchtet); + interflag = 0; + // Let 'spintet' be [#,#,d,e] where [#,#] is the boundary edge of R. + spintet = searchtet; + while (1) { + pd = apex(spintet); + pe = oppo(spintet); + // Skip a hull edge. + if ((pd != dummypoint) && (pe != dummypoint)) { + // Skip an edge containing a vertex of R. + if (!pmarktested(pd) && !pmarktested(pe)) { + // Check if [d,e] intersects R. + for (i = 0; i < missingshs->objects && !interflag; i++) { + parysh = (face *) fastlookup(missingshs, i); + pa = sorg(*parysh); + pb = sdest(*parysh); + pc = sapex(*parysh); + interflag=tri_edge_test(pa, pb, pc, pd, pe, NULL, 1, types, poss); + if (interflag > 0) { + if (interflag == 2) { + // They intersect at a single point. + dir = (enum interresult) types[0]; + if ((dir == ACROSSFACE) || (dir == ACROSSEDGE)) { + //pos = poss[0]; + // Go to the crossing edge [d,e,#,#]. + edestoppo(spintet, crosstet); // // [d,e,#,#]. + // Check if it is a segment. + if (issubseg(crosstet)) { + //face checkseg; + //tsspivot1(crosstet, checkseg); + //reportselfintersect(&checkseg, parysh); + terminatetetgen(this, 3); + } + // Adjust the edge such that d lies below [a,b,c]. + ori = orient3d(pa, pb, pc, pd); + assert(ori != 0); + if (ori < 0) { + esymself(crosstet); + } + searchflag = 1; + } + } + break; + } // if (interflag > 0) + } + } + } + // Leave search at this bdry edge if an intersection is found. + if (interflag > 0) break; + // Go to the next tetrahedron. + fnextself(spintet); + if (spintet.tet == searchtet.tet) break; + } // while (1) + } // j + + return searchflag; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// formcavity() Form the cavity of a missing region. // +// // +// The missing region R is formed by a set of missing subfaces 'missingshs'. // +// In the following, we assume R is horizontal and oriented. (All subfaces // +// of R are oriented in the same way.) 'searchtet' is a tetrahedron [d,e,#, // +// #] which intersects R in its interior, where the edge [d,e] intersects R, // +// and d lies below R. // +// // +// 'crosstets' returns the set of crossing tets. Every tet in it has the // +// form [d,e,#,#] where [d,e] is a crossing edge, and d lies below R. The // +// set of tets form the cavity C, which is divided into two parts by R, one // +// at top and one at bottom. 'topfaces' and 'botfaces' return the upper and // +// lower boundary faces of C. 'toppoints' contains vertices of 'crosstets' // +// in the top part of C, and so does 'botpoints'. Both 'toppoints' and // +// 'botpoints' contain vertices of R. // +// // +// Important: This routine assumes all vertices of the facet containing this // +// subface are marked, i.e., pmarktested(p) returns true. // +// // +/////////////////////////////////////////////////////////////////////////////// + +bool tetgenmesh::formcavity(triface* searchtet, arraypool* missingshs, + arraypool* crosstets, arraypool* topfaces, + arraypool* botfaces, arraypool* toppoints, + arraypool* botpoints) +{ + arraypool *crossedges; + triface spintet, neightet, *parytet; + face *parysh = NULL; + point pa, pd, pe, *parypt; + enum interresult dir; + bool testflag, invalidflag; + int types[2], poss[4]; + int t1ver; + int i, j, k; + + // Temporarily re-use 'topfaces' for all crossing edges. + crossedges = topfaces; + + if (b->verbose > 2) { + printf(" Form the cavity of a missing region.\n"); + } + // Mark this edge to avoid testing it later. + markedge(*searchtet); + crossedges->newindex((void **) &parytet); + *parytet = *searchtet; + + invalidflag = 0; + + // Collect all crossing tets. Each cross tet is saved in the standard + // form [d,e,#,#], where [d,e] is a crossing edge, d lies below R. + // NEITHER d NOR e is a vertex of R (!pmarktested). + for (i = 0; i < crossedges->objects; i++) { + // Get a crossing edge [d,e,#,#]. + searchtet = (triface *) fastlookup(crossedges, i); + + // Sort vertices into the bottom and top arrays. + pd = org(*searchtet); + if (!pinfected(pd)) { + pinfect(pd); + botpoints->newindex((void **) &parypt); + *parypt = pd; + } + pe = dest(*searchtet); + if (!pinfected(pe)) { + pinfect(pe); + toppoints->newindex((void **) &parypt); + *parypt = pe; + } + + // All tets sharing this edge are crossing tets. + spintet = *searchtet; + while (1) { + if (!infected(spintet)) { + infect(spintet); + crosstets->newindex((void **) &parytet); + *parytet = spintet; + } + // Go to the next crossing tet. + fnextself(spintet); + if (spintet.tet == searchtet->tet) break; + } // while (1) + + // Detect new crossing edges. + spintet = *searchtet; + while (1) { + // spintet is [d,e,a,#], where d lies below R, and e lies above R. + pa = apex(spintet); + if (pa != dummypoint) { + if (!pmarktested(pa)) { + // There exists a crossing edge, either [e,a] or [a,d]. First check + // if the crossing edge has already be added, i.e., check if a + // tetrahedron at this edge is marked. + testflag = true; + for (j = 0; j < 2 && testflag; j++) { + if (j == 0) { + enext(spintet, neightet); + } else { + eprev(spintet, neightet); + } + while (1) { + if (edgemarked(neightet)) { + // This crossing edge has already been tested. Skip it. + testflag = false; + break; + } + fnextself(neightet); + if (neightet.tet == spintet.tet) break; + } + } // j + if (testflag) { + // Test if [e,a] or [a,d] intersects R. + // Do a brute-force search in the set of subfaces of R. Slow! + // Need to be improved! + pd = org(spintet); + pe = dest(spintet); + for (k = 0; k < missingshs->objects; k++) { + parysh = (face *) fastlookup(missingshs, k); + if (tri_edge_test(sorg(*parysh), sdest(*parysh), sapex(*parysh), + pe, pa, NULL, 1, types, poss)) { + // Found intersection. 'a' lies below R. + enext(spintet, neightet); + dir = (enum interresult) types[0]; + if ((dir == ACROSSFACE) || (dir == ACROSSEDGE)) { + // A valid intersection. + } else { + // A non-valid intersection. Maybe a PLC problem. + invalidflag = 1; + } + break; + } + if (tri_edge_test(sorg(*parysh), sdest(*parysh), sapex(*parysh), + pa, pd, NULL, 1, types, poss)) { + // Found intersection. 'a' lies above R. + eprev(spintet, neightet); + dir = (enum interresult) types[0]; + if ((dir == ACROSSFACE) || (dir == ACROSSEDGE)) { + // A valid intersection. + } else { + // A non-valid intersection. Maybe a PLC problem. + invalidflag = 1; + } + break; + } + } // k + if (k < missingshs->objects) { + // Found a pair of triangle - edge intersection. + if (invalidflag) { + if (!b->quiet) { + printf("Warning: A non-valid facet - edge intersection\n"); + printf(" subface: (%d, %d, %d) edge: (%d, %d)\n", + pointmark(sorg(*parysh)), pointmark(sdest(*parysh)), + pointmark(sapex(*parysh)), pointmark(org(neightet)), + pointmark(dest(neightet))); + } + // It may be a PLC problem. + terminatetetgen(this, 3); + } + // Adjust the edge direction, so that its origin lies below R, + // and its destination lies above R. + esymself(neightet); + // Check if this edge is a segment. + if (issubseg(neightet)) { + // Invalid PLC! + //face checkseg; + //tsspivot1(neightet, checkseg); + //reportselfintersect(&checkseg, parysh); + terminatetetgen(this, 3); + } + // Mark this edge to avoid testing it again. + markedge(neightet); + crossedges->newindex((void **) &parytet); + *parytet = neightet; + } else { + // No intersection is found. It may be a PLC problem. + invalidflag = 1; + // Split the subface intersecting [d,e]. + for (k = 0; k < missingshs->objects; k++) { + parysh = (face *) fastlookup(missingshs, k); + // Test if this face intersects [e,a]. + if (tri_edge_test(sorg(*parysh),sdest(*parysh),sapex(*parysh), + pd, pe, NULL, 1, types, poss)) { + break; + } + } // k + if (k == missingshs->objects) { + // Not found such an edge. + // Arbitrarily choose an edge (except the first) to split. + k = randomnation(missingshs->objects - 1); + parysh = (face *) fastlookup(missingshs, k + 1); + } + recentsh = *parysh; + recenttet = spintet; // For point location. + break; // the while (1) loop + } // if (k == missingshs->objects) + } // if (testflag) + } // if (!pmarktested(pa) || b->psc) + } // if (pa != dummypoint) + // Go to the next crossing tet. + fnextself(spintet); + if (spintet.tet == searchtet->tet) break; + } // while (1) + + //if (b->psc) { + if (invalidflag) break; + //} + } // i + + if (b->verbose > 2) { + printf(" Formed cavity: %ld (%ld) cross tets (edges).\n", + crosstets->objects, crossedges->objects); + } + + // Unmark all marked edges. + for (i = 0; i < crossedges->objects; i++) { + searchtet = (triface *) fastlookup(crossedges, i); + assert(edgemarked(*searchtet)); // SELF_CHECK + unmarkedge(*searchtet); + } + crossedges->restart(); + + + if (invalidflag) { + // Unmark all collected tets. + for (i = 0; i < crosstets->objects; i++) { + searchtet = (triface *) fastlookup(crosstets, i); + uninfect(*searchtet); + } + // Unmark all collected vertices. + for (i = 0; i < botpoints->objects; i++) { + parypt = (point *) fastlookup(botpoints, i); + puninfect(*parypt); + } + for (i = 0; i < toppoints->objects; i++) { + parypt = (point *) fastlookup(toppoints, i); + puninfect(*parypt); + } + crosstets->restart(); + botpoints->restart(); + toppoints->restart(); + + // Randomly split an interior edge of R. + i = randomnation(missingshs->objects - 1); + recentsh = * (face *) fastlookup(missingshs, i); + return false; + } + + + // Collect the top and bottom faces and the middle vertices. Since all top + // and bottom vertices have been infected. Uninfected vertices must be + // middle vertices (i.e., the vertices of R). + // NOTE 1: Hull tets may be collected. Process them as a normal one. + // NOTE 2: Some previously recovered subfaces may be completely inside the + // cavity. In such case, we remove these subfaces from the cavity and put + // them into 'subfacstack'. They will be recovered later. + // NOTE 3: Some segments may be completely inside the cavity, e.g., they + // attached to a subface which is inside the cavity. Such segments are + // put in 'subsegstack'. They will be recovered later. + // NOTE4 : The interior subfaces and segments mentioned in NOTE 2 and 3 + // are identified in the routine "carvecavity()". + + for (i = 0; i < crosstets->objects; i++) { + searchtet = (triface *) fastlookup(crosstets, i); + // searchtet is [d,e,a,b]. + eorgoppo(*searchtet, spintet); + fsym(spintet, neightet); // neightet is [a,b,e,#] + if (!infected(neightet)) { + // A top face. + topfaces->newindex((void **) &parytet); + *parytet = neightet; + } + edestoppo(*searchtet, spintet); + fsym(spintet, neightet); // neightet is [b,a,d,#] + if (!infected(neightet)) { + // A bottom face. + botfaces->newindex((void **) &parytet); + *parytet = neightet; + } + // Add middle vertices if there are (skip dummypoint). + pa = org(neightet); + if (!pinfected(pa)) { + if (pa != dummypoint) { + pinfect(pa); + botpoints->newindex((void **) &parypt); + *parypt = pa; + toppoints->newindex((void **) &parypt); + *parypt = pa; + } + } + pa = dest(neightet); + if (!pinfected(pa)) { + if (pa != dummypoint) { + pinfect(pa); + botpoints->newindex((void **) &parypt); + *parypt = pa; + toppoints->newindex((void **) &parypt); + *parypt = pa; + } + } + } // i + + // Uninfect all collected top, bottom, and middle vertices. + for (i = 0; i < toppoints->objects; i++) { + parypt = (point *) fastlookup(toppoints, i); + puninfect(*parypt); + } + for (i = 0; i < botpoints->objects; i++) { + parypt = (point *) fastlookup(botpoints, i); + puninfect(*parypt); + } + cavitycount++; + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// delaunizecavity() Fill a cavity by Delaunay tetrahedra. // +// // +// The cavity C to be tetrahedralized is the top or bottom part of a whole // +// cavity. 'cavfaces' contains the boundary faces of C. NOTE: faces in 'cav- // +// faces' do not form a closed polyhedron. The "open" side are subfaces of // +// the missing facet. These faces will be recovered later in fillcavity(). // +// // +// This routine first constructs the DT of the vertices. Then it identifies // +// the half boundary faces of the cavity in DT. Possiblely the cavity C will // +// be enlarged. // +// // +// The DT is returned in 'newtets'. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::delaunizecavity(arraypool *cavpoints, arraypool *cavfaces, + arraypool *cavshells, arraypool *newtets, + arraypool *crosstets, arraypool *misfaces) +{ + triface searchtet, neightet, *parytet, *parytet1; + face tmpsh, *parysh; + point pa, pb, pc, pd, pt[3], *parypt; + enum interresult dir; + insertvertexflags ivf; + REAL ori; + long baknum, bakhullsize; + int bakchecksubsegflag, bakchecksubfaceflag; + int t1ver; + int i, j; + + if (b->verbose > 2) { + printf(" Delaunizing cavity: %ld points, %ld faces.\n", + cavpoints->objects, cavfaces->objects); + } + // Remember the current number of crossing tets. It may be enlarged later. + baknum = crosstets->objects; + bakhullsize = hullsize; + bakchecksubsegflag = checksubsegflag; + bakchecksubfaceflag = checksubfaceflag; + hullsize = 0l; + checksubsegflag = 0; + checksubfaceflag = 0; + b->verbose--; // Suppress informations for creating Delaunay tetra. + b->plc = 0; // Do not check near vertices. + + ivf.bowywat = 1; // Use Bowyer-Watson algorithm. + + // Get four non-coplanar points (no dummypoint). + pa = pb = pc = NULL; + for (i = 0; i < cavfaces->objects; i++) { + parytet = (triface *) fastlookup(cavfaces, i); + parytet->ver = epivot[parytet->ver]; + if (apex(*parytet) != dummypoint) { + pa = org(*parytet); + pb = dest(*parytet); + pc = apex(*parytet); + break; + } + } + pd = NULL; + for (; i < cavfaces->objects; i++) { + parytet = (triface *) fastlookup(cavfaces, i); + pt[0] = org(*parytet); + pt[1] = dest(*parytet); + pt[2] = apex(*parytet); + for (j = 0; j < 3; j++) { + if (pt[j] != dummypoint) { // Do not include a hull point. + ori = orient3d(pa, pb, pc, pt[j]); + if (ori != 0) { + pd = pt[j]; + if (ori > 0) { // Swap pa and pb. + pt[j] = pa; pa = pb; pb = pt[j]; + } + break; + } + } + } + if (pd != NULL) break; + } + assert(i < cavfaces->objects); // SELF_CHECK + + // Create an init DT. + initialdelaunay(pa, pb, pc, pd); + + // Incrementally insert the vertices (duplicated vertices are ignored). + for (i = 0; i < cavpoints->objects; i++) { + pt[0] = * (point *) fastlookup(cavpoints, i); + searchtet = recenttet; + ivf.iloc = (int) OUTSIDE; + insertpoint(pt[0], &searchtet, NULL, NULL, &ivf); + } + + if (b->verbose > 2) { + printf(" Identifying %ld boundary faces of the cavity.\n", + cavfaces->objects); + } + + while (1) { + + // Identify boundary faces. Mark interior tets. Save missing faces. + for (i = 0; i < cavfaces->objects; i++) { + parytet = (triface *) fastlookup(cavfaces, i); + // Skip an interior face (due to the enlargement of the cavity). + if (infected(*parytet)) continue; + parytet->ver = epivot[parytet->ver]; + pt[0] = org(*parytet); + pt[1] = dest(*parytet); + pt[2] = apex(*parytet); + // Create a temp subface. + makeshellface(subfaces, &tmpsh); + setshvertices(tmpsh, pt[0], pt[1], pt[2]); + // Insert tmpsh in DT. + searchtet.tet = NULL; + dir = scoutsubface(&tmpsh, &searchtet); + if (dir == SHAREFACE) { + // Inserted! 'tmpsh' must face toward the inside of the cavity. + // Remember the boundary tet (outside the cavity) in tmpsh + // (use the adjacent tet slot). + tmpsh.sh[0] = (shellface) encode(*parytet); + // Save this subface. + cavshells->newindex((void **) &parysh); + *parysh = tmpsh; + } + else { + // This boundary face is missing. + shellfacedealloc(subfaces, tmpsh.sh); + // Save this face in list. + misfaces->newindex((void **) &parytet1); + *parytet1 = *parytet; + } + } // i + + if (misfaces->objects > 0) { + if (b->verbose > 2) { + printf(" Enlarging the cavity. %ld missing bdry faces\n", + misfaces->objects); + } + + // Removing all temporary subfaces. + for (i = 0; i < cavshells->objects; i++) { + parysh = (face *) fastlookup(cavshells, i); + stpivot(*parysh, neightet); + tsdissolve(neightet); // Detach it from adj. tets. + fsymself(neightet); + tsdissolve(neightet); + shellfacedealloc(subfaces, parysh->sh); + } + cavshells->restart(); + + // Infect the points which are of the cavity. + for (i = 0; i < cavpoints->objects; i++) { + pt[0] = * (point *) fastlookup(cavpoints, i); + pinfect(pt[0]); // Mark it as inserted. + } + + // Enlarge the cavity. + for (i = 0; i < misfaces->objects; i++) { + // Get a missing face. + parytet = (triface *) fastlookup(misfaces, i); + if (!infected(*parytet)) { + // Put it into crossing tet list. + infect(*parytet); + crosstets->newindex((void **) &parytet1); + *parytet1 = *parytet; + // Insert the opposite point if it is not in DT. + pd = oppo(*parytet); + if (!pinfected(pd)) { + searchtet = recenttet; + ivf.iloc = (int) OUTSIDE; + insertpoint(pd, &searchtet, NULL, NULL, &ivf); + pinfect(pd); + cavpoints->newindex((void **) &parypt); + *parypt = pd; + } + // Add three opposite faces into the boundary list. + for (j = 0; j < 3; j++) { + esym(*parytet, neightet); + fsymself(neightet); + if (!infected(neightet)) { + cavfaces->newindex((void **) &parytet1); + *parytet1 = neightet; + } + enextself(*parytet); + } // j + } // if (!infected(parytet)) + } // i + + // Uninfect the points which are of the cavity. + for (i = 0; i < cavpoints->objects; i++) { + pt[0] = * (point *) fastlookup(cavpoints, i); + puninfect(pt[0]); + } + + misfaces->restart(); + continue; + } // if (misfaces->objects > 0) + + break; + + } // while (1) + + // Collect all tets of the DT. All new tets are marktested. + marktest(recenttet); + newtets->newindex((void **) &parytet); + *parytet = recenttet; + for (i = 0; i < newtets->objects; i++) { + searchtet = * (triface *) fastlookup(newtets, i); + for (j = 0; j < 4; j++) { + decode(searchtet.tet[j], neightet); + if (!marktested(neightet)) { + marktest(neightet); + newtets->newindex((void **) &parytet); + *parytet = neightet; + } + } + } + + cavpoints->restart(); + cavfaces->restart(); + + if (crosstets->objects > baknum) { + // The cavity has been enlarged. + cavityexpcount++; + } + + // Restore the original values. + hullsize = bakhullsize; + checksubsegflag = bakchecksubsegflag; + checksubfaceflag = bakchecksubfaceflag; + b->verbose++; + b->plc = 1; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// fillcavity() Fill new tets into the cavity. // +// // +// The new tets are stored in two disjoint sets(which share the same facet). // +// 'topfaces' and 'botfaces' are the boundaries of these two sets, respect- // +// ively. 'midfaces' is empty on input, and will store faces in the facet. // +// // +// Important: This routine assumes all vertices of the missing region R are // +// marktested, i.e., pmarktested(p) returns true. // +// // +/////////////////////////////////////////////////////////////////////////////// + +bool tetgenmesh::fillcavity(arraypool* topshells, arraypool* botshells, + arraypool* midfaces, arraypool* missingshs, + arraypool* topnewtets, arraypool* botnewtets, + triface* crossedge) +{ + arraypool *cavshells; + triface bdrytet, neightet, *parytet; + triface searchtet, spintet; + face *parysh; + face checkseg; + point pa, pb, pc; + bool mflag; + int t1ver; + int i, j; + + // Connect newtets to tets outside the cavity. These connections are needed + // for identifying the middle faces (which belong to R). + for (j = 0; j < 2; j++) { + cavshells = (j == 0 ? topshells : botshells); + if (cavshells != NULL) { + for (i = 0; i < cavshells->objects; i++) { + // Get a temp subface. + parysh = (face *) fastlookup(cavshells, i); + // Get the boundary tet outside the cavity (saved in sh[0]). + decode(parysh->sh[0], bdrytet); + pa = org(bdrytet); + pb = dest(bdrytet); + pc = apex(bdrytet); + // Get the adjacent new tet inside the cavity. + stpivot(*parysh, neightet); + // Mark neightet as an interior tet of this cavity. + infect(neightet); + // Connect the two tets (the old connections are replaced). + bond(bdrytet, neightet); + tsdissolve(neightet); // Clear the pointer to tmpsh. + // Update the point-to-tets map. + setpoint2tet(pa, (tetrahedron) neightet.tet); + setpoint2tet(pb, (tetrahedron) neightet.tet); + setpoint2tet(pc, (tetrahedron) neightet.tet); + } // i + } // if (cavshells != NULL) + } // j + + if (crossedge != NULL) { + // Glue top and bottom tets at their common facet. + triface toptet, bottet, spintet, *midface; + point pd, pe; + REAL ori; + int types[2], poss[4]; + int interflag; + int bflag; + + mflag = false; + pd = org(*crossedge); + pe = dest(*crossedge); + + // Search the first (middle) face in R. + // Since R may be non-convex, we must make sure that the face is in the + // interior of R. We search a face in 'topnewtets' whose three vertices + // are on R and it intersects 'crossedge' in its interior. Then search + // a matching face in 'botnewtets'. + for (i = 0; i < topnewtets->objects && !mflag; i++) { + searchtet = * (triface *) fastlookup(topnewtets, i); + for (searchtet.ver = 0; searchtet.ver < 4 && !mflag; searchtet.ver++) { + pa = org(searchtet); + if (pmarktested(pa)) { + pb = dest(searchtet); + if (pmarktested(pb)) { + pc = apex(searchtet); + if (pmarktested(pc)) { + // Check if this face intersects [d,e]. + interflag = tri_edge_test(pa,pb,pc,pd,pe,NULL,1,types,poss); + if (interflag == 2) { + // They intersect at a single point. Found. + toptet = searchtet; + // The face lies in the interior of R. + // Get the tet (in topnewtets) which lies above R. + ori = orient3d(pa, pb, pc, pd); + assert(ori != 0); + if (ori < 0) { + fsymself(toptet); + pa = org(toptet); + pb = dest(toptet); + } + // Search the face [b,a,c] in 'botnewtets'. + for (j = 0; j < botnewtets->objects; j++) { + neightet = * (triface *) fastlookup(botnewtets, j); + // Is neightet contains 'b'. + if ((point) neightet.tet[4] == pb) { + neightet.ver = 11; + } else if ((point) neightet.tet[5] == pb) { + neightet.ver = 3; + } else if ((point) neightet.tet[6] == pb) { + neightet.ver = 7; + } else if ((point) neightet.tet[7] == pb) { + neightet.ver = 0; + } else { + continue; + } + // Is the 'neightet' contains edge [b,a]. + if (dest(neightet) == pa) { + // 'neightet' is just the edge. + } else if (apex(neightet) == pa) { + eprevesymself(neightet); + } else if (oppo(neightet) == pa) { + esymself(neightet); + enextself(neightet); + } else { + continue; + } + // Is 'neightet' the face [b,a,c]. + if (apex(neightet) == pc) { + bottet = neightet; + mflag = true; + break; + } + } // j + } // if (interflag == 2) + } // pc + } // pb + } // pa + } // toptet.ver + } // i + + if (mflag) { + // Found a pair of matched faces in 'toptet' and 'bottet'. + bond(toptet, bottet); + // Both are interior tets. + infect(toptet); + infect(bottet); + // Add this face into search list. + markface(toptet); + midfaces->newindex((void **) &parytet); + *parytet = toptet; + } else { + // No pair of 'toptet' and 'bottet'. + toptet.tet = NULL; + // Randomly split an interior edge of R. + i = randomnation(missingshs->objects - 1); + recentsh = * (face *) fastlookup(missingshs, i); + } + + // Find other middle faces, connect top and bottom tets. + for (i = 0; i < midfaces->objects && mflag; i++) { + // Get a matched middle face [a, b, c] + midface = (triface *) fastlookup(midfaces, i); + // The tet must be a new created tet (marktested). + assert(marktested(*midface)); // SELF_CHECK + // Check the neighbors at the edges of this face. + for (j = 0; j < 3 && mflag; j++) { + toptet = *midface; + bflag = false; + while (1) { + // Go to the next face in the same tet. + esymself(toptet); + pc = apex(toptet); + if (pmarktested(pc)) { + break; // Find a subface. + } + if (pc == dummypoint) { + assert(0); // Check this case. + break; // Find a subface. + } + // Go to the adjacent tet. + fsymself(toptet); + // Do we walk outside the cavity? + if (!marktested(toptet)) { + // Yes, the adjacent face is not a middle face. + bflag = true; break; + } + } + if (!bflag) { + // assert(marktested(toptet)); // SELF_CHECK + if (!facemarked(toptet)) { + fsym(*midface, bottet); + spintet = bottet; + while (1) { + esymself(bottet); + pd = apex(bottet); + if (pd == pc) break; // Face matched. + fsymself(bottet); + if (bottet.tet == spintet.tet) { + // Not found a matched bottom face. + mflag = false; + break; + } + } // while (1) + if (mflag) { + if (marktested(bottet)) { + // Connect two tets together. + bond(toptet, bottet); + // Both are interior tets. + infect(toptet); + infect(bottet); + // Add this face into list. + markface(toptet); + midfaces->newindex((void **) &parytet); + *parytet = toptet; + } + } else { // mflag == false + // Adjust 'toptet' and 'bottet' to be the crossing edges. + fsym(*midface, bottet); + spintet = bottet; + while (1) { + esymself(bottet); + pd = apex(bottet); + if (pmarktested(pd)) { + // assert(pd != pc); + // Let 'toptet' be [a,b,c,#], and 'bottet' be [b,a,d,*]. + // Adjust 'toptet' and 'bottet' to be the crossing edges. + // Test orient3d(b,c,#,d). + ori = orient3d(dest(toptet), pc, oppo(toptet), pd); + if (ori < 0) { + // Edges [a,d] and [b,c] cross each other. + enextself(toptet); // [b,c] + enextself(bottet); // [a,d] + } else if (ori > 0) { + // Edges [a,c] and [b,d] cross each other. + eprevself(toptet); // [c,a] + eprevself(bottet); // [d,b] + } else { + // b,c,#,and d are coplanar!. + assert(0); + } + break; // Not matched + } + fsymself(bottet); + assert (bottet.tet != spintet.tet); + } + } // if (!mflag) + } // if (!facemarked(toptet)) + } // if (!bflag) + enextself(*midface); + } // j + } // i + + if (mflag) { + if (b->verbose > 2) { + printf(" Found %ld middle subfaces.\n", midfaces->objects); + } + face oldsh, newsh, casout, casin, neighsh; + + oldsh = * (face *) fastlookup(missingshs, 0); + + // Create new subfaces to fill the region R. + for (i = 0; i < midfaces->objects; i++) { + // Get a matched middle face [a, b, c] + midface = (triface *) fastlookup(midfaces, i); + unmarkface(*midface); + makeshellface(subfaces, &newsh); + setsorg(newsh, org(*midface)); + setsdest(newsh, dest(*midface)); + setsapex(newsh, apex(*midface)); + // The new subface gets its markers from the old one. + setshellmark(newsh, shellmark(oldsh)); + if (checkconstraints) { + setareabound(newsh, areabound(oldsh)); + } + // Connect the new subface to adjacent tets. + tsbond(*midface, newsh); + fsym(*midface, neightet); + sesymself(newsh); + tsbond(neightet, newsh); + } + + // Connect new subfaces together and to the bdry of R. + // Delete faked segments. + for (i = 0; i < midfaces->objects; i++) { + // Get a matched middle face [a, b, c] + midface = (triface *) fastlookup(midfaces, i); + for (j = 0; j < 3; j++) { + tspivot(*midface, newsh); + spivot(newsh, casout); + if (casout.sh == NULL) { + // Search its neighbor. + fnext(*midface, searchtet); + while (1) { + // (1) First check if this side is a bdry edge of R. + tsspivot1(searchtet, checkseg); + if (checkseg.sh != NULL) { + // It's a bdry edge of R. + assert(!infected(searchtet)); // It must not be a cavity tet. + // Get the old subface. + checkseg.shver = 0; + spivot(checkseg, oldsh); + if (sinfected(checkseg)) { + // It's a faked segment. Delete it. + spintet = searchtet; + while (1) { + tssdissolve1(spintet); + fnextself(spintet); + if (spintet.tet == searchtet.tet) break; + } + shellfacedealloc(subsegs, checkseg.sh); + ssdissolve(oldsh); + checkseg.sh = NULL; + } + spivot(oldsh, casout); + if (casout.sh != NULL) { + casin = casout; + if (checkseg.sh != NULL) { + // Make sure that the subface has the right ori at the + // segment. + checkseg.shver = 0; + if (sorg(newsh) != sorg(checkseg)) { + sesymself(newsh); + } + spivot(casin, neighsh); + while (neighsh.sh != oldsh.sh) { + casin = neighsh; + spivot(casin, neighsh); + } + } + sbond1(newsh, casout); + sbond1(casin, newsh); + } + if (checkseg.sh != NULL) { + ssbond(newsh, checkseg); + } + break; + } // if (checkseg.sh != NULL) + // (2) Second check if this side is an interior edge of R. + tspivot(searchtet, neighsh); + if (neighsh.sh != NULL) { + // Found an adjacent subface of newsh (an interior edge). + sbond(newsh, neighsh); + break; + } + fnextself(searchtet); + assert(searchtet.tet != midface->tet); + } // while (1) + } // if (casout.sh == NULL) + enextself(*midface); + } // j + } // i + + // Delete old subfaces. + for (i = 0; i < missingshs->objects; i++) { + parysh = (face *) fastlookup(missingshs, i); + shellfacedealloc(subfaces, parysh->sh); + } + } else { + if (toptet.tet != NULL) { + // Faces at top and bottom are not matched. + // Choose a Steiner point in R. + // Split one of the crossing edges. + pa = org(toptet); + pb = dest(toptet); + pc = org(bottet); + pd = dest(bottet); + // Search an edge in R which is either [a,b] or [c,d]. + // Reminder: Subfaces in this list 'missingshs', except the first + // one, represents an interior edge of R. + for (i = 1; i < missingshs->objects; i++) { + parysh = (face *) fastlookup(missingshs, i); + if (((sorg(*parysh) == pa) && (sdest(*parysh) == pb)) || + ((sorg(*parysh) == pb) && (sdest(*parysh) == pa))) break; + if (((sorg(*parysh) == pc) && (sdest(*parysh) == pd)) || + ((sorg(*parysh) == pd) && (sdest(*parysh) == pc))) break; + } + if (i < missingshs->objects) { + // Found. Return it. + recentsh = *parysh; + } else { + assert(0); + } + } + } + + midfaces->restart(); + } else { + mflag = true; + } + + // Delete the temp subfaces. + for (j = 0; j < 2; j++) { + cavshells = (j == 0 ? topshells : botshells); + if (cavshells != NULL) { + for (i = 0; i < cavshells->objects; i++) { + parysh = (face *) fastlookup(cavshells, i); + shellfacedealloc(subfaces, parysh->sh); + } + } + } + + topshells->restart(); + if (botshells != NULL) { + botshells->restart(); + } + + return mflag; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// carvecavity() Delete old tets and outer new tets of the cavity. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::carvecavity(arraypool *crosstets, arraypool *topnewtets, + arraypool *botnewtets) +{ + arraypool *newtets; + shellface *sptr, *ssptr; + triface *parytet, *pnewtet, newtet, neightet, spintet; + face checksh, *parysh; + face checkseg, *paryseg; + int t1ver; + int i, j; + + if (b->verbose > 2) { + printf(" Carve cavity: %ld old tets.\n", crosstets->objects); + } + + // First process subfaces and segments which are adjacent to the cavity. + // They must be re-connected to new tets in the cavity. + // Comment: It is possible that some subfaces and segments are completely + // inside the cavity. This can happen even if the cavity is not enlarged. + // Before deleting the old tets, find and queue all interior subfaces + // and segments. They will be recovered later. 2010-05-06. + + // Collect all subfaces and segments which attached to the old tets. + for (i = 0; i < crosstets->objects; i++) { + parytet = (triface *) fastlookup(crosstets, i); + if ((sptr = (shellface*) parytet->tet[9]) != NULL) { + for (j = 0; j < 4; j++) { + if (sptr[j]) { + sdecode(sptr[j], checksh); + if (!sinfected(checksh)) { + sinfect(checksh); + cavetetshlist->newindex((void **) &parysh); + *parysh = checksh; + } + } + } // j + } + if ((ssptr = (shellface*) parytet->tet[8]) != NULL) { + for (j = 0; j < 6; j++) { + if (ssptr[j]) { + sdecode(ssptr[j], checkseg); + // Skip a deleted segment (was a faked segment) + if (checkseg.sh[3] != NULL) { + if (!sinfected(checkseg)) { + sinfect(checkseg); + cavetetseglist->newindex((void **) &paryseg); + *paryseg = checkseg; + } + } + } + } // j + } + } // i + + // Uninfect collected subfaces. + for (i = 0; i < cavetetshlist->objects; i++) { + parysh = (face *) fastlookup(cavetetshlist, i); + suninfect(*parysh); + } + // Uninfect collected segments. + for (i = 0; i < cavetetseglist->objects; i++) { + paryseg = (face *) fastlookup(cavetetseglist, i); + suninfect(*paryseg); + } + + // Connect subfaces to new tets. + for (i = 0; i < cavetetshlist->objects; i++) { + parysh = (face *) fastlookup(cavetetshlist, i); + // Get an adjacent tet at this subface. + stpivot(*parysh, neightet); + // Does this tet lie inside the cavity. + if (infected(neightet)) { + // Yes. Get the other adjacent tet at this subface. + sesymself(*parysh); + stpivot(*parysh, neightet); + // Does this tet lie inside the cavity. + if (infected(neightet)) { + checksh = *parysh; + stdissolve(checksh); + caveencshlist->newindex((void **) &parysh); + *parysh = checksh; + } + } + if (!infected(neightet)) { + // Found an outside tet. Re-connect this subface to a new tet. + fsym(neightet, newtet); + assert(marktested(newtet)); // It's a new tet. + sesymself(*parysh); + tsbond(newtet, *parysh); + } + } // i + + + for (i = 0; i < cavetetseglist->objects; i++) { + checkseg = * (face *) fastlookup(cavetetseglist, i); + // Check if the segment is inside the cavity. + sstpivot1(checkseg, neightet); + spintet = neightet; + while (1) { + if (!infected(spintet)) { + // This segment is on the boundary of the cavity. + break; + } + fnextself(spintet); + if (spintet.tet == neightet.tet) { + sstdissolve1(checkseg); + caveencseglist->newindex((void **) &paryseg); + *paryseg = checkseg; + break; + } + } + if (!infected(spintet)) { + // A boundary segment. Connect this segment to the new tets. + sstbond1(checkseg, spintet); + neightet = spintet; + while (1) { + tssbond1(spintet, checkseg); + fnextself(spintet); + if (spintet.tet == neightet.tet) break; + } + } + } // i + + + cavetetshlist->restart(); + cavetetseglist->restart(); + + // Delete the old tets in cavity. + for (i = 0; i < crosstets->objects; i++) { + parytet = (triface *) fastlookup(crosstets, i); + if (ishulltet(*parytet)) { + hullsize--; + } + tetrahedrondealloc(parytet->tet); + } + + crosstets->restart(); // crosstets will be re-used. + + // Collect new tets in cavity. Some new tets have already been found + // (and infected) in the fillcavity(). We first collect them. + for (j = 0; j < 2; j++) { + newtets = (j == 0 ? topnewtets : botnewtets); + if (newtets != NULL) { + for (i = 0; i < newtets->objects; i++) { + parytet = (triface *) fastlookup(newtets, i); + if (infected(*parytet)) { + crosstets->newindex((void **) &pnewtet); + *pnewtet = *parytet; + } + } // i + } + } // j + + // Now we collect all new tets in cavity. + for (i = 0; i < crosstets->objects; i++) { + parytet = (triface *) fastlookup(crosstets, i); + for (j = 0; j < 4; j++) { + decode(parytet->tet[j], neightet); + if (marktested(neightet)) { // Is it a new tet? + if (!infected(neightet)) { + // Find an interior tet. + //assert((point) neightet.tet[7] != dummypoint); // SELF_CHECK + infect(neightet); + crosstets->newindex((void **) &pnewtet); + *pnewtet = neightet; + } + } + } // j + } // i + + parytet = (triface *) fastlookup(crosstets, 0); + recenttet = *parytet; // Remember a live handle. + + // Delete outer new tets. + for (j = 0; j < 2; j++) { + newtets = (j == 0 ? topnewtets : botnewtets); + if (newtets != NULL) { + for (i = 0; i < newtets->objects; i++) { + parytet = (triface *) fastlookup(newtets, i); + if (infected(*parytet)) { + // This is an interior tet. + uninfect(*parytet); + unmarktest(*parytet); + if (ishulltet(*parytet)) { + hullsize++; + } + } else { + // An outer tet. Delete it. + tetrahedrondealloc(parytet->tet); + } + } + } + } + + crosstets->restart(); + topnewtets->restart(); + if (botnewtets != NULL) { + botnewtets->restart(); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// restorecavity() Reconnect old tets and delete new tets of the cavity. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::restorecavity(arraypool *crosstets, arraypool *topnewtets, + arraypool *botnewtets, arraypool *missingshbds) +{ + triface *parytet, neightet, spintet; + face *parysh; + face checkseg; + point *ppt; + int t1ver; + int i, j; + + // Reconnect crossing tets to cavity boundary. + for (i = 0; i < crosstets->objects; i++) { + parytet = (triface *) fastlookup(crosstets, i); + assert(infected(*parytet)); // SELF_CHECK + parytet->ver = 0; + for (parytet->ver = 0; parytet->ver < 4; parytet->ver++) { + fsym(*parytet, neightet); + if (!infected(neightet)) { + // Restore the old connections of tets. + bond(*parytet, neightet); + } + } + // Update the point-to-tet map. + parytet->ver = 0; + ppt = (point *) &(parytet->tet[4]); + for (j = 0; j < 4; j++) { + setpoint2tet(ppt[j], encode(*parytet)); + } + } + + // Uninfect all crossing tets. + for (i = 0; i < crosstets->objects; i++) { + parytet = (triface *) fastlookup(crosstets, i); + uninfect(*parytet); + } + + // Remember a live handle. + recenttet = * (triface *) fastlookup(crosstets, 0); + + // Delete faked segments. + for (i = 0; i < missingshbds->objects; i++) { + parysh = (face *) fastlookup(missingshbds, i); + sspivot(*parysh, checkseg); + assert(checkseg.sh != NULL); + if (checkseg.sh[3] != NULL) { + if (sinfected(checkseg)) { + // It's a faked segment. Delete it. + sstpivot1(checkseg, neightet); + spintet = neightet; + while (1) { + tssdissolve1(spintet); + fnextself(spintet); + if (spintet.tet == neightet.tet) break; + } + shellfacedealloc(subsegs, checkseg.sh); + ssdissolve(*parysh); + //checkseg.sh = NULL; + } + } + } // i + + // Delete new tets. + for (i = 0; i < topnewtets->objects; i++) { + parytet = (triface *) fastlookup(topnewtets, i); + tetrahedrondealloc(parytet->tet); + } + + if (botnewtets != NULL) { + for (i = 0; i < botnewtets->objects; i++) { + parytet = (triface *) fastlookup(botnewtets, i); + tetrahedrondealloc(parytet->tet); + } + } + + crosstets->restart(); + topnewtets->restart(); + if (botnewtets != NULL) { + botnewtets->restart(); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// flipcertify() Insert a crossing face into priority queue. // +// // +// A crossing face of a facet must have at least one top and one bottom ver- // +// tex of the facet. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::flipcertify(triface *chkface,badface **pqueue,point plane_pa, + point plane_pb, point plane_pc) +{ + badface *parybf, *prevbf, *nextbf; + triface neightet; + face checksh; + point p[5]; + REAL w[5]; + REAL insph, ori4; + int topi, boti; + int i; + + // Compute the flip time \tau. + fsym(*chkface, neightet); + + p[0] = org(*chkface); + p[1] = dest(*chkface); + p[2] = apex(*chkface); + p[3] = oppo(*chkface); + p[4] = oppo(neightet); + + // Check if the face is a crossing face. + topi = boti = 0; + for (i = 0; i < 3; i++) { + if (pmarktest2ed(p[i])) topi++; + if (pmarktest3ed(p[i])) boti++; + } + if ((topi == 0) || (boti == 0)) { + // It is not a crossing face. + // return; + for (i = 3; i < 5; i++) { + if (pmarktest2ed(p[i])) topi++; + if (pmarktest3ed(p[i])) boti++; + } + if ((topi == 0) || (boti == 0)) { + // The two tets sharing at this face are on one side of the facet. + // Check if this face is locally Delaunay (due to rounding error). + if ((p[3] != dummypoint) && (p[4] != dummypoint)) { + // Do not check it if it is a subface. + tspivot(*chkface, checksh); + if (checksh.sh == NULL) { + insph = insphere_s(p[1], p[0], p[2], p[3], p[4]); + assert(insph != 0); + if (insph > 0) { + // Add the face into queue. + if (b->verbose > 2) { + printf(" A locally non-Delanay face (%d, %d, %d)-%d,%d\n", + pointmark(p[0]), pointmark(p[1]), pointmark(p[2]), + pointmark(p[3]), pointmark(p[4])); + } + parybf = (badface *) flippool->alloc(); + parybf->key = 0.; // tau = 0, do immediately. + parybf->tt = *chkface; + parybf->forg = p[0]; + parybf->fdest = p[1]; + parybf->fapex = p[2]; + parybf->foppo = p[3]; + parybf->noppo = p[4]; + // Add it at the top of the priority queue. + if (*pqueue == NULL) { + *pqueue = parybf; + parybf->nextitem = NULL; + } else { + parybf->nextitem = *pqueue; + *pqueue = parybf; + } + } // if (insph > 0) + } // if (checksh.sh == NULL) + } + //return; + } + return; // Test: omit this face. + } + + // Decide the "height" for each point. + for (i = 0; i < 5; i++) { + if (pmarktest2ed(p[i])) { + // A top point has a positive weight. + w[i] = orient3dfast(plane_pa, plane_pb, plane_pc, p[i]); + if (w[i] < 0) w[i] = -w[i]; + assert(w[i] != 0); + } else { + w[i] = 0; + } + } + + // Make sure orient3d(p[1], p[0], p[2], p[3]) > 0; + // Hence if (insphere(p[1], p[0], p[2], p[3], p[4]) > 0) means that + // p[4] lies inside the circumsphere of p[1], p[0], p[2], p[3]. + // The same if orient4d(p[1], p[0], p[2], p[3], p[4]) > 0 means that + // p[4] lies below the oriented hyperplane passing through + // p[1], p[0], p[2], p[3]. + + insph = insphere(p[1], p[0], p[2], p[3], p[4]); + ori4 = orient4d(p[1], p[0], p[2], p[3], p[4], w[1], w[0], w[2], w[3], w[4]); + + if (b->verbose > 2) { + printf(" Heights: (%g, %g, %g, %g, %g)\n", w[0],w[1],w[2],w[3],w[4]); + printf(" Insph: %g, ori4: %g, tau = %g\n", insph, ori4, -insph/ori4); + } + + if (ori4 > 0) { + // Add the face into queue. + if (b->verbose > 2) { + printf(" Insert face (%d, %d, %d) - %d, %d\n", pointmark(p[0]), + pointmark(p[1]), pointmark(p[2]), pointmark(p[3]), pointmark(p[4])); + } + + parybf = (badface *) flippool->alloc(); + + parybf->key = -insph / ori4; + parybf->tt = *chkface; + parybf->forg = p[0]; + parybf->fdest = p[1]; + parybf->fapex = p[2]; + parybf->foppo = p[3]; + parybf->noppo = p[4]; + + // Push the face into priority queue. + //pq.push(bface); + if (*pqueue == NULL) { + *pqueue = parybf; + parybf->nextitem = NULL; + } else { + // Search an item whose key is larger or equal to current key. + prevbf = NULL; + nextbf = *pqueue; + //if (!b->flipinsert_random) { // Default use a priority queue. + // Insert the item into priority queue. + while (nextbf != NULL) { + if (nextbf->key < parybf->key) { + prevbf = nextbf; + nextbf = nextbf->nextitem; + } else { + break; + } + } + //} // if (!b->flipinsert_random) + // Insert the new item between prev and next items. + if (prevbf == NULL) { + *pqueue = parybf; + } else { + prevbf->nextitem = parybf; + } + parybf->nextitem = nextbf; + } + } else if (ori4 == 0) { + + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// flipinsertfacet() Insert a facet into a CDT by flips. // +// // +// The algorithm is described in Shewchuk's paper "Updating and Constructing // +// Constrained Delaunay and Constrained Regular Triangulations by Flips", in // +// Proc. 19th Ann. Symp. on Comput. Geom., 86--95, 2003. // +// // +// 'crosstets' contains the set of crossing tetrahedra (infected) of the // +// facet. 'toppoints' and 'botpoints' are points lies above and below the // +// facet, not on the facet. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::flipinsertfacet(arraypool *crosstets, arraypool *toppoints, + arraypool *botpoints, arraypool *midpoints) +{ + arraypool *crossfaces, *bfacearray; + triface fliptets[6], baktets[2], fliptet, newface; + triface neightet, *parytet; + face checksh; + face checkseg; + badface *pqueue; + badface *popbf, bface; + point plane_pa, plane_pb, plane_pc; + point p1, p2, pd, pe; + point *parypt; + flipconstraints fc; + REAL ori[3]; + int convcount, copcount; + int flipflag, fcount; + int n, i; + long f23count, f32count, f44count; + long totalfcount; + + f23count = flip23count; + f32count = flip32count; + f44count = flip44count; + + // Get three affinely independent vertices in the missing region R. + calculateabovepoint(midpoints, &plane_pa, &plane_pb, &plane_pc); + + // Mark top and bottom points. Do not mark midpoints. + for (i = 0; i < toppoints->objects; i++) { + parypt = (point *) fastlookup(toppoints, i); + if (!pmarktested(*parypt)) { + pmarktest2(*parypt); + } + } + for (i = 0; i < botpoints->objects; i++) { + parypt = (point *) fastlookup(botpoints, i); + if (!pmarktested(*parypt)) { + pmarktest3(*parypt); + } + } + + // Collect crossing faces. + crossfaces = cavetetlist; // Re-use array 'cavetetlist'. + + // Each crossing face contains at least one bottom vertex and + // one top vertex. + for (i = 0; i < crosstets->objects; i++) { + parytet = (triface *) fastlookup(crosstets, i); + fliptet = *parytet; + for (fliptet.ver = 0; fliptet.ver < 4; fliptet.ver++) { + fsym(fliptet, neightet); + if (infected(neightet)) { // It is an interior face. + if (!marktested(neightet)) { // It is an unprocessed face. + crossfaces->newindex((void **) &parytet); + *parytet = fliptet; + } + } + } + marktest(fliptet); + } + + if (b->verbose > 1) { + printf(" Found %ld crossing faces.\n", crossfaces->objects); + } + + for (i = 0; i < crosstets->objects; i++) { + parytet = (triface *) fastlookup(crosstets, i); + unmarktest(*parytet); + uninfect(*parytet); + } + + // Initialize the priority queue. + pqueue = NULL; + + for (i = 0; i < crossfaces->objects; i++) { + parytet = (triface *) fastlookup(crossfaces, i); + flipcertify(parytet, &pqueue, plane_pa, plane_pb, plane_pc); + } + crossfaces->restart(); + + // The list for temporarily storing unflipable faces. + bfacearray = new arraypool(sizeof(triface), 4); + + + fcount = 0; // Count the number of flips. + + // Flip insert the facet. + while (pqueue != NULL) { + + // Pop a face from the priority queue. + popbf = pqueue; + bface = *popbf; + + // Update the queue. + pqueue = pqueue->nextitem; + + // Delete the popped item from the pool. + flippool->dealloc((void *) popbf); + + if (!isdeadtet(bface.tt)) { + if ((org(bface.tt) == bface.forg) && (dest(bface.tt) == bface.fdest) && + (apex(bface.tt) == bface.fapex) && (oppo(bface.tt) == bface.foppo)) { + // It is still a crossing face of R. + fliptet = bface.tt; + fsym(fliptet, neightet); + assert(!isdeadtet(neightet)); + if (oppo(neightet) == bface.noppo) { + pd = oppo(fliptet); + pe = oppo(neightet); + + if (b->verbose > 2) { + printf(" Get face (%d, %d, %d) - %d, %d, tau = %.17g\n", + pointmark(bface.forg), pointmark(bface.fdest), + pointmark(bface.fapex), pointmark(bface.foppo), + pointmark(bface.noppo), bface.key); + } + flipflag = 0; + + // Check for which type of flip can we do. + convcount = 3; + copcount = 0; + for (i = 0; i < 3; i++) { + p1 = org(fliptet); + p2 = dest(fliptet); + ori[i] = orient3d(p1, p2, pd, pe); + if (ori[i] < 0) { + convcount--; + //break; + } else if (ori[i] == 0) { + convcount--; // Possible 4-to-4 flip. + copcount++; + //break; + } + enextself(fliptet); + } + + if (convcount == 3) { + // A 2-to-3 flip is found. + // The face should not be a subface. + tspivot(fliptet, checksh); + assert(checksh.sh == NULL); + + fliptets[0] = fliptet; // abcd, d may be the new vertex. + fliptets[1] = neightet; // bace. + flip23(fliptets, 1, &fc); + // Put the link faces into check list. + for (i = 0; i < 3; i++) { + eprevesym(fliptets[i], newface); + crossfaces->newindex((void **) &parytet); + *parytet = newface; + } + for (i = 0; i < 3; i++) { + enextesym(fliptets[i], newface); + crossfaces->newindex((void **) &parytet); + *parytet = newface; + } + flipflag = 1; + } else if (convcount == 2) { + assert(copcount <= 1); + //if (copcount <= 1) { + // A 3-to-2 or 4-to-4 may be possible. + // Get the edge which is locally non-convex or flat. + for (i = 0; i < 3; i++) { + if (ori[i] <= 0) break; + enextself(fliptet); + } + // The edge should not be a segment. + tsspivot1(fliptet, checkseg); + assert(checkseg.sh == NULL); + + // Collect tets sharing at this edge. + // NOTE: This operation may collect tets which lie outside the + // cavity, e.g., when the edge lies on the boundary of the + // cavity. Do not flip if there are outside tets at this edge. + // 2012-07-27. + esym(fliptet, fliptets[0]); // [b,a,d,c] + n = 0; + do { + p1 = apex(fliptets[n]); + if (!(pmarktested(p1) || pmarktest2ed(p1) || pmarktest3ed(p1))) { + // This apex is not on the cavity. Hence the face does not + // lie inside the cavity. Do not flip this edge. + n = 1000; break; + } + fnext(fliptets[n], fliptets[n + 1]); + n++; + } while ((fliptets[n].tet != fliptet.tet) && (n < 5)); + + if (n == 3) { + // Found a 3-to-2 flip. + flip32(fliptets, 1, &fc); + // Put the link faces into check list. + for (i = 0; i < 3; i++) { + esym(fliptets[0], newface); + crossfaces->newindex((void **) &parytet); + *parytet = newface; + enextself(fliptets[0]); + } + for (i = 0; i < 3; i++) { + esym(fliptets[1], newface); + crossfaces->newindex((void **) &parytet); + *parytet = newface; + enextself(fliptets[1]); + } + flipflag = 1; + } else if (n == 4) { + if (copcount == 1) { + // Found a 4-to-4 flip. + // Let the six vertices are: a,b,c,d,e,f, where + // fliptets[0] = [b,a,d,c] + // [1] = [b,a,c,e] + // [2] = [b,a,e,f] + // [3] = [b,a,f,d] + // After the 4-to-4 flip, edge [a,b] is flipped, edge [e,d] + // is created. + // First do a 2-to-3 flip. + // Comment: This flip temporarily creates a degenerated + // tet (whose volume is zero). It will be removed by the + // followed 3-to-2 flip. + fliptets[0] = fliptet; // = [a,b,c,d], d is the new vertex. + // fliptets[1]; // = [b,a,c,e]. + baktets[0] = fliptets[2]; // = [b,a,e,f] + baktets[1] = fliptets[3]; // = [b,a,f,d] + // The flip may involve hull tets. + flip23(fliptets, 1, &fc); + // Put the "outer" link faces into check list. + // fliptets[0] = [e,d,a,b] => will be flipped, so + // [a,b,d] and [a,b,e] are not "outer" link faces. + for (i = 1; i < 3; i++) { + eprevesym(fliptets[i], newface); + crossfaces->newindex((void **) &parytet); + *parytet = newface; + } + for (i = 1; i < 3; i++) { + enextesym(fliptets[i], newface); + crossfaces->newindex((void **) &parytet); + *parytet = newface; + } + // Then do a 3-to-2 flip. + enextesymself(fliptets[0]); // fliptets[0] is [e,d,a,b]. + eprevself(fliptets[0]); // = [b,a,d,c], d is the new vertex. + fliptets[1] = baktets[0]; // = [b,a,e,f] + fliptets[2] = baktets[1]; // = [b,a,f,d] + flip32(fliptets, 1, &fc); + // Put the "outer" link faces into check list. + // fliptets[0] = [d,e,f,a] + // fliptets[1] = [e,d,f,b] + // Faces [a,b,d] and [a,b,e] are not "outer" link faces. + enextself(fliptets[0]); + for (i = 1; i < 3; i++) { + esym(fliptets[0], newface); + crossfaces->newindex((void **) &parytet); + *parytet = newface; + enextself(fliptets[0]); + } + enextself(fliptets[1]); + for (i = 1; i < 3; i++) { + esym(fliptets[1], newface); + crossfaces->newindex((void **) &parytet); + *parytet = newface; + enextself(fliptets[1]); + } + flip23count--; + flip32count--; + flip44count++; + flipflag = 1; + } else { + //n == 4, convflag != 0; assert(0); + } + } else { + // n > 4 => unflipable. //assert(0); + } + } else { + // There are more than 1 non-convex or coplanar cases. + flipflag = -1; // Ignore this face. + if (b->verbose > 2) { + printf(" Ignore face (%d, %d, %d) - %d, %d, tau = %.17g\n", + pointmark(bface.forg), pointmark(bface.fdest), + pointmark(bface.fapex), pointmark(bface.foppo), + pointmark(bface.noppo), bface.key); + } + } // if (convcount == 1) + + if (flipflag == 1) { + // Update the priority queue. + for (i = 0; i < crossfaces->objects; i++) { + parytet = (triface *) fastlookup(crossfaces, i); + flipcertify(parytet, &pqueue, plane_pa, plane_pb, plane_pc); + } + crossfaces->restart(); + if (1) { // if (!b->flipinsert_random) { + // Insert all queued unflipped faces. + for (i = 0; i < bfacearray->objects; i++) { + parytet = (triface *) fastlookup(bfacearray, i); + // This face may be changed. + if (!isdeadtet(*parytet)) { + flipcertify(parytet, &pqueue, plane_pa, plane_pb, plane_pc); + } + } + bfacearray->restart(); + } + fcount++; + } else if (flipflag == 0) { + // Queue an unflippable face. To process it later. + bfacearray->newindex((void **) &parytet); + *parytet = fliptet; + } + } // if (pe == bface.noppo) + } // if ((pa == bface.forg) && ...) + } // if (bface.tt != NULL) + + } // while (pqueue != NULL) + + if (bfacearray->objects > 0) { + if (fcount == 0) { + printf("!! No flip is found in %ld faces.\n", bfacearray->objects); + assert(0); + } + } + + // 'bfacearray' may be not empty (for what reason ??). + //dbg_unflip_facecount += bfacearray->objects; + + assert(flippool->items == 0l); + delete bfacearray; + + // Un-mark top and bottom points. + for (i = 0; i < toppoints->objects; i++) { + parypt = (point *) fastlookup(toppoints, i); + punmarktest2(*parypt); + } + for (i = 0; i < botpoints->objects; i++) { + parypt = (point *) fastlookup(botpoints, i); + punmarktest3(*parypt); + } + + f23count = flip23count - f23count; + f32count = flip32count - f32count; + f44count = flip44count - f44count; + totalfcount = f23count + f32count + f44count; + if (b->verbose > 2) { + printf(" Total %ld flips. f23(%ld), f32(%ld), f44(%ld).\n", + totalfcount, f23count, f32count, f44count); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// fillregion() Fill the missing region by a set of new subfaces. // +// // +// 'missingshs' contains the list of subfaces in R. Moreover, each subface // +// (except the first one) in this list represents an interior edge of R. // +// // +// Note: We assume that all vertices of R are marktested so we can detect // +// new subface by checking the flag in apexes. // +// // +/////////////////////////////////////////////////////////////////////////////// + +bool tetgenmesh::fillregion(arraypool* missingshs, arraypool* missingshbds, + arraypool* newshs) +{ + badface *newflipface, *popface; + triface searchtet, spintet, neightet; + face oldsh, newsh, opensh, *parysh; + face casout, casin, neighsh, checksh; + face neighseg, checkseg; + point pc; + int success; + int t1ver; + int i, j; + + + // Search the first new subface to fill the region. + for (i = 0; i < missingshbds->objects; i++) { + parysh = (face *) fastlookup(missingshbds, i); + sspivot(*parysh, neighseg); + sstpivot1(neighseg, searchtet); + j = 0; // Count the number of passes of R. + spintet = searchtet; + while (1) { + pc = apex(spintet); + if (pmarktested(pc)) { + neightet = spintet; + j++; + } + fnextself(spintet); + if (spintet.tet == searchtet.tet) break; + } + assert(j >= 1); + if (j == 1) { + // Found an interior new subface. + searchtet = neightet; + oldsh = *parysh; + break; + } + } // i + + if (i == missingshbds->objects) { + // Failed to find any interior subface. + // Need Steiner points. + return false; + } + + makeshellface(subfaces, &newsh); + setsorg(newsh, org(searchtet)); + setsdest(newsh, dest(searchtet)); + setsapex(newsh, apex(searchtet)); + // The new subface gets its markers from the old one. + setshellmark(newsh, shellmark(oldsh)); + if (checkconstraints) { + setareabound(newsh, areabound(oldsh)); + } + // Connect the new subface to adjacent tets. + tsbond(searchtet, newsh); + fsymself(searchtet); + sesymself(newsh); + tsbond(searchtet, newsh); + // Connect newsh to outer subfaces. + sspivot(oldsh, checkseg); + if (sinfected(checkseg)) { + // It's a faked segment. Delete it. + spintet = searchtet; + while (1) { + tssdissolve1(spintet); + fnextself(spintet); + if (spintet.tet == searchtet.tet) break; + } + shellfacedealloc(subsegs, checkseg.sh); + ssdissolve(oldsh); + checkseg.sh = NULL; + } + spivot(oldsh, casout); + if (casout.sh != NULL) { + casin = casout; + if (checkseg.sh != NULL) { + // Make sure that the subface has the right ori at the segment. + checkseg.shver = 0; + if (sorg(newsh) != sorg(checkseg)) { + sesymself(newsh); + } + spivot(casin, neighsh); + while (neighsh.sh != oldsh.sh) { + casin = neighsh; + spivot(casin, neighsh); + } + } + sbond1(newsh, casout); + sbond1(casin, newsh); + } + if (checkseg.sh != NULL) { + ssbond(newsh, checkseg); + } + // Add this new subface into list. + sinfect(newsh); + newshs->newindex((void **) &parysh); + *parysh = newsh; + + // Push two "open" side of the new subface into stack. + for (i = 0; i < 2; i++) { + senextself(newsh); + newflipface = (badface *) flippool->alloc(); + newflipface->ss = newsh; + newflipface->nextitem = flipstack; + flipstack = newflipface; + } + + success = 1; + + // Loop until 'flipstack' is empty. + while ((flipstack != NULL) && success) { + // Pop an "open" side from the stack. + popface = flipstack; + opensh = popface->ss; + flipstack = popface->nextitem; // The next top item in stack. + flippool->dealloc((void *) popface); + + // opensh is either (1) an interior edge or (2) a bdry edge. + stpivot(opensh, searchtet); + tsspivot1(searchtet, checkseg); + if (checkseg.sh == NULL) { + // No segment. It is an interior edge of R. + // Search for a new face in R. + spintet = searchtet; + fnextself(spintet); // Skip the current face. + while (1) { + pc = apex(spintet); + if (pmarktested(pc)) { + // 'opensh' is an interior edge. + if (!issubface(spintet)) { + // Create a new subface. + makeshellface(subfaces, &newsh); + setsorg(newsh, org(spintet)); + setsdest(newsh, dest(spintet)); + setsapex(newsh, pc); + // The new subface gets its markers from its neighbor. + setshellmark(newsh, shellmark(opensh)); + if (checkconstraints) { + setareabound(newsh, areabound(opensh)); + } + // Connect the new subface to adjacent tets. + tsbond(spintet, newsh); + fsymself(spintet); + sesymself(newsh); + tsbond(spintet, newsh); + // Connect newsh to its adjacent subface. + sbond(newsh, opensh); + // Add this new subface into list. + sinfect(newsh); + newshs->newindex((void **) &parysh); + *parysh = newsh; + // Push two "open" side of the new subface into stack. + for (i = 0; i < 2; i++) { + senextself(newsh); + newflipface = (badface *) flippool->alloc(); + newflipface->ss = newsh; + newflipface->nextitem = flipstack; + flipstack = newflipface; + } + } else { + // Connect to another open edge. + tspivot(spintet, checksh); + sbond(opensh, checksh); + } + break; + } // if (pmarktested(pc)) + fnextself(spintet); + if (spintet.tet == searchtet.tet) { + // Not find any face to fill in R at this side. + // Suggest a point to split the edge. + success = 0; + break; + } + } // while (1) + } else { + // This side coincident with a boundary edge of R. + checkseg.shver = 0; + spivot(checkseg, oldsh); + if (sinfected(checkseg)) { + // It's a faked segment. Delete it. + spintet = searchtet; + while (1) { + tssdissolve1(spintet); + fnextself(spintet); + if (spintet.tet == searchtet.tet) break; + } + shellfacedealloc(subsegs, checkseg.sh); + ssdissolve(oldsh); + checkseg.sh = NULL; + } + spivot(oldsh, casout); + if (casout.sh != NULL) { + casin = casout; + if (checkseg.sh != NULL) { + // Make sure that the subface has the right ori at the segment. + checkseg.shver = 0; + if (sorg(opensh) != sorg(checkseg)) { + sesymself(opensh); + } + spivot(casin, neighsh); + while (neighsh.sh != oldsh.sh) { + casin = neighsh; + spivot(casin, neighsh); + } + } + sbond1(opensh, casout); + sbond1(casin, opensh); + } + if (checkseg.sh != NULL) { + ssbond(opensh, checkseg); + } + } // if (checkseg.sh != NULL) + } // while ((flipstack != NULL) && success) + + if (success) { + // Uninfect all new subfaces. + for (i = 0; i < newshs->objects; i++) { + parysh = (face *) fastlookup(newshs, i); + suninfect(*parysh); + } + // Delete old subfaces. + for (i = 0; i < missingshs->objects; i++) { + parysh = (face *) fastlookup(missingshs, i); + shellfacedealloc(subfaces, parysh->sh); + } + fillregioncount++; + } else { + // Failed to fill the region. + // Re-connect old subfaces at boundaries of R. + // Also delete fake segments. + for (i = 0; i < missingshbds->objects; i++) { + parysh = (face *) fastlookup(missingshbds, i); + // It still connect to 'casout'. + // Re-connect 'casin' to it. + spivot(*parysh, casout); + casin = casout; + spivot(casin, neighsh); + while (1) { + if (sinfected(neighsh)) break; + if (neighsh.sh == parysh->sh) break; + casin = neighsh; + spivot(casin, neighsh); + } + if (sinfected(neighsh)) { + sbond1(casin, *parysh); + } + sspivot(*parysh, checkseg); + if (checkseg.sh != NULL) { + if (checkseg.sh[3] != NULL) { + if (sinfected(checkseg)) { + sstpivot1(checkseg, searchtet); + spintet = searchtet; + while (1) { + tssdissolve1(spintet); + fnextself(spintet); + if (spintet.tet == searchtet.tet) break; + } + ssdissolve(*parysh); + shellfacedealloc(subsegs, checkseg.sh); + } + } + } + } + // Delete all new subfaces. + for (i = 0; i < newshs->objects; i++) { + parysh = (face *) fastlookup(newshs, i); + shellfacedealloc(subfaces, parysh->sh); + } + // Clear the flip pool. + flippool->restart(); + flipstack = NULL; + + // Choose an interior edge of R to split. + assert(missingshs->objects > 1); + // Skip the first subface in 'missingshs'. + i = randomnation(missingshs->objects - 1) + 1; + parysh = (face *) fastlookup(missingshs, i); + recentsh = *parysh; + } + + newshs->restart(); + + return success; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// insertpoint_cdt() Insert a new point into a CDT. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::insertpoint_cdt(point newpt, triface *searchtet, face *splitsh, + face *splitseg, insertvertexflags *ivf, + arraypool *cavpoints, arraypool *cavfaces, + arraypool *cavshells, arraypool *newtets, + arraypool *crosstets, arraypool *misfaces) +{ + triface neightet, *parytet; + face checksh, *parysh, *parysh1; + face *paryseg, *paryseg1; + point *parypt; + int t1ver; + int i; + + if (b->verbose > 2) { + printf(" Insert point %d into CDT\n", pointmark(newpt)); + } + + if (!insertpoint(newpt, searchtet, NULL, NULL, ivf)) { + // Point is not inserted. Check ivf->iloc for reason. + return 0; + } + + + for (i = 0; i < cavetetvertlist->objects; i++) { + cavpoints->newindex((void **) &parypt); + *parypt = * (point *) fastlookup(cavetetvertlist, i); + } + // Add the new point into the point list. + cavpoints->newindex((void **) &parypt); + *parypt = newpt; + + for (i = 0; i < cavebdrylist->objects; i++) { + cavfaces->newindex((void **) &parytet); + *parytet = * (triface *) fastlookup(cavebdrylist, i); + } + + for (i = 0; i < caveoldtetlist->objects; i++) { + crosstets->newindex((void **) &parytet); + *parytet = * (triface *) fastlookup(caveoldtetlist, i); + } + + cavetetvertlist->restart(); + cavebdrylist->restart(); + caveoldtetlist->restart(); + + // Insert the point using the cavity algorithm. + delaunizecavity(cavpoints, cavfaces, cavshells, newtets, crosstets, + misfaces); + fillcavity(cavshells, NULL, NULL, NULL, NULL, NULL, NULL); + carvecavity(crosstets, newtets, NULL); + + if ((splitsh != NULL) || (splitseg != NULL)) { + // Insert the point into the surface mesh. + sinsertvertex(newpt, splitsh, splitseg, ivf->sloc, ivf->sbowywat, 0); + + // Put all new subfaces into stack. + for (i = 0; i < caveshbdlist->objects; i++) { + // Get an old subface at edge [a, b]. + parysh = (face *) fastlookup(caveshbdlist, i); + spivot(*parysh, checksh); // The new subface [a, b, p]. + // Do not recover a deleted new face (degenerated). + if (checksh.sh[3] != NULL) { + subfacstack->newindex((void **) &parysh); + *parysh = checksh; + } + } + + if (splitseg != NULL) { + // Queue two new subsegments in C(p) for recovery. + for (i = 0; i < cavesegshlist->objects; i++) { + paryseg = (face *) fastlookup(cavesegshlist, i); + subsegstack->newindex((void **) &paryseg1); + *paryseg1 = *paryseg; + } + } // if (splitseg != NULL) + + // Delete the old subfaces in sC(p). + for (i = 0; i < caveshlist->objects; i++) { + parysh = (face *) fastlookup(caveshlist, i); + if (checksubfaceflag) { + // It is possible that this subface still connects to adjacent + // tets which are not in C(p). If so, clear connections in the + // adjacent tets at this subface. + stpivot(*parysh, neightet); + if (neightet.tet != NULL) { + if (neightet.tet[4] != NULL) { + // Found an adjacent tet. It must be not in C(p). + assert(!infected(neightet)); + tsdissolve(neightet); + fsymself(neightet); + assert(!infected(neightet)); + tsdissolve(neightet); + } + } + } + shellfacedealloc(subfaces, parysh->sh); + } + if (splitseg != NULL) { + // Delete the old segment in sC(p). + shellfacedealloc(subsegs, splitseg->sh); + } + + // Clear working lists. + caveshlist->restart(); + caveshbdlist->restart(); + cavesegshlist->restart(); + } // if ((splitsh != NULL) || (splitseg != NULL)) + + // Put all interior subfaces into stack for recovery. + // They were collected in carvecavity(). + // Note: Some collected subfaces may be deleted by sinsertvertex(). + for (i = 0; i < caveencshlist->objects; i++) { + parysh = (face *) fastlookup(caveencshlist, i); + if (parysh->sh[3] != NULL) { + subfacstack->newindex((void **) &parysh1); + *parysh1 = *parysh; + } + } + + // Put all interior segments into stack for recovery. + // They were collected in carvecavity(). + // Note: Some collected segments may be deleted by sinsertvertex(). + for (i = 0; i < caveencseglist->objects; i++) { + paryseg = (face *) fastlookup(caveencseglist, i); + if (paryseg->sh[3] != NULL) { + subsegstack->newindex((void **) &paryseg1); + *paryseg1 = *paryseg; + } + } + + caveencshlist->restart(); + caveencseglist->restart(); + + return 1; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// refineregion() Refine a missing region by inserting points. // +// // +// 'splitsh' represents an edge of the facet to be split. It must be not a // +// segment. +// // +// Assumption: The current mesh is a CDT and is convex. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::refineregion(face &splitsh, arraypool *cavpoints, + arraypool *cavfaces, arraypool *cavshells, + arraypool *newtets, arraypool *crosstets, + arraypool *misfaces) +{ + triface searchtet, spintet; + face splitseg, *paryseg; + point steinpt, pa, pb, refpt; + insertvertexflags ivf; + enum interresult dir; + long baknum = points->items; + int t1ver; + int i; + + if (b->verbose > 2) { + printf(" Refining region at edge (%d, %d, %d).\n", + pointmark(sorg(splitsh)), pointmark(sdest(splitsh)), + pointmark(sapex(splitsh))); + } + + // Add the Steiner point at the barycenter of the face. + pa = sorg(splitsh); + pb = sdest(splitsh); + // Create a new point. + makepoint(&steinpt, FREEFACETVERTEX); + for (i = 0; i < 3; i++) { + steinpt[i] = 0.5 * (pa[i] + pb[i]); + } + + ivf.bowywat = 1; // Use the Bowyer-Watson algorrithm. + ivf.cdtflag = 1; // Only create the initial cavity. + ivf.sloc = (int) ONEDGE; + ivf.sbowywat = 1; + ivf.assignmeshsize = b->metric; + + point2tetorg(pa, searchtet); // Start location from it. + ivf.iloc = (int) OUTSIDE; + + ivf.rejflag = 1; // Reject it if it encroaches upon any segment. + if (!insertpoint_cdt(steinpt, &searchtet, &splitsh, NULL, &ivf, cavpoints, + cavfaces, cavshells, newtets, crosstets, misfaces)) { + if (ivf.iloc == (int) ENCSEGMENT) { + pointdealloc(steinpt); + // Split an encroached segment. + assert(encseglist->objects > 0); + i = randomnation(encseglist->objects); + paryseg = (face *) fastlookup(encseglist, i); + splitseg = *paryseg; + encseglist->restart(); + + // Split the segment. + pa = sorg(splitseg); + pb = sdest(splitseg); + // Create a new point. + makepoint(&steinpt, FREESEGVERTEX); + for (i = 0; i < 3; i++) { + steinpt[i] = 0.5 * (pa[i] + pb[i]); + } + point2tetorg(pa, searchtet); + ivf.iloc = (int) OUTSIDE; + ivf.rejflag = 0; + if (!insertpoint_cdt(steinpt, &searchtet, &splitsh, &splitseg, &ivf, + cavpoints, cavfaces, cavshells, newtets, + crosstets, misfaces)) { + assert(0); + } + st_segref_count++; + if (steinerleft > 0) steinerleft--; + } else { + assert(0); + } + } else { + st_facref_count++; + if (steinerleft > 0) steinerleft--; + } + + while (subsegstack->objects > 0l) { + // seglist is used as a stack. + subsegstack->objects--; + paryseg = (face *) fastlookup(subsegstack, subsegstack->objects); + splitseg = *paryseg; + + // Check if this segment has been recovered. + sstpivot1(splitseg, searchtet); + if (searchtet.tet != NULL) continue; + + // Search the segment. + dir = scoutsegment(sorg(splitseg), sdest(splitseg), &searchtet, &refpt, + NULL); + if (dir == SHAREEDGE) { + // Found this segment, insert it. + if (!issubseg(searchtet)) { + // Let the segment remember an adjacent tet. + sstbond1(splitseg, searchtet); + // Bond the segment to all tets containing it. + spintet = searchtet; + do { + tssbond1(spintet, splitseg); + fnextself(spintet); + } while (spintet.tet != searchtet.tet); + } else { + // Collision! Should not happen. + assert(0); + } + } else { + if ((dir == ACROSSFACE) || (dir == ACROSSEDGE)) { + // Split the segment. + // Create a new point. + makepoint(&steinpt, FREESEGVERTEX); + //setpointtype(newpt, FREESEGVERTEX); + getsteinerptonsegment(&splitseg, refpt, steinpt); + ivf.iloc = (int) OUTSIDE; + ivf.rejflag = 0; + if (!insertpoint_cdt(steinpt, &searchtet, &splitsh, &splitseg, &ivf, + cavpoints, cavfaces, cavshells, newtets, + crosstets, misfaces)) { + assert(0); + } + st_segref_count++; + if (steinerleft > 0) steinerleft--; + } else { + // Maybe a PLC problem. + assert(0); + } + } + } // while + + if (b->verbose > 2) { + printf(" Added %ld Steiner points.\n", points->items - baknum); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// constrainedfacets() Recover constrained facets in a CDT. // +// // +// All unrecovered subfaces are queued in 'subfacestack'. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::constrainedfacets() +{ + arraypool *tg_crosstets, *tg_topnewtets, *tg_botnewtets; + arraypool *tg_topfaces, *tg_botfaces, *tg_midfaces; + arraypool *tg_topshells, *tg_botshells, *tg_facfaces; + arraypool *tg_toppoints, *tg_botpoints; + arraypool *tg_missingshs, *tg_missingshbds, *tg_missingshverts; + triface searchtet, neightet, crossedge; + face searchsh, *parysh, *parysh1; + face *paryseg; + point *parypt; + enum interresult dir; + int facetcount; + int success; + int t1ver; + int i, j; + + // Initialize arrays. + tg_crosstets = new arraypool(sizeof(triface), 10); + tg_topnewtets = new arraypool(sizeof(triface), 10); + tg_botnewtets = new arraypool(sizeof(triface), 10); + tg_topfaces = new arraypool(sizeof(triface), 10); + tg_botfaces = new arraypool(sizeof(triface), 10); + tg_midfaces = new arraypool(sizeof(triface), 10); + tg_toppoints = new arraypool(sizeof(point), 8); + tg_botpoints = new arraypool(sizeof(point), 8); + tg_facfaces = new arraypool(sizeof(face), 10); + tg_topshells = new arraypool(sizeof(face), 10); + tg_botshells = new arraypool(sizeof(face), 10); + tg_missingshs = new arraypool(sizeof(face), 10); + tg_missingshbds = new arraypool(sizeof(face), 10); + tg_missingshverts = new arraypool(sizeof(point), 8); + // This is a global array used by refineregion(). + encseglist = new arraypool(sizeof(face), 4); + + facetcount = 0; + + while (subfacstack->objects > 0l) { + + subfacstack->objects--; + parysh = (face *) fastlookup(subfacstack, subfacstack->objects); + searchsh = *parysh; + + if (searchsh.sh[3] == NULL) continue; // It is dead. + if (isshtet(searchsh)) continue; // It is recovered. + + // Collect all unrecovered subfaces which are co-facet. + smarktest(searchsh); + tg_facfaces->newindex((void **) &parysh); + *parysh = searchsh; + for (i = 0; i < tg_facfaces->objects; i++) { + parysh = (face *) fastlookup(tg_facfaces, i); + for (j = 0; j < 3; j++) { + if (!isshsubseg(*parysh)) { + spivot(*parysh, searchsh); + assert(searchsh.sh != NULL); // SELF_CHECK + if (!smarktested(searchsh)) { + if (!isshtet(searchsh)) { + smarktest(searchsh); + tg_facfaces->newindex((void **) &parysh1); + *parysh1 = searchsh; + } + } + } + senextself(*parysh); + } // j + } // i + // Have found all facet subfaces. Unmark them. + for (i = 0; i < tg_facfaces->objects; i++) { + parysh = (face *) fastlookup(tg_facfaces, i); + sunmarktest(*parysh); + } + + if (b->verbose > 2) { + printf(" Recovering facet #%d: %ld subfaces.\n", facetcount + 1, + tg_facfaces->objects); + } + facetcount++; + + while (tg_facfaces->objects > 0l) { + + tg_facfaces->objects--; + parysh = (face *) fastlookup(tg_facfaces, tg_facfaces->objects); + searchsh = *parysh; + + if (searchsh.sh[3] == NULL) continue; // It is dead. + if (isshtet(searchsh)) continue; // It is recovered. + + searchtet.tet = NULL; + dir = scoutsubface(&searchsh, &searchtet); + if (dir == SHAREFACE) continue; // The subface is inserted. + + // The subface is missing. Form the missing region. + // Re-use 'tg_crosstets' for 'adjtets'. + formregion(&searchsh, tg_missingshs, tg_missingshbds, tg_missingshverts); + + if (scoutcrossedge(searchtet, tg_missingshbds, tg_missingshs)) { + // Save this crossing edge, will be used by fillcavity(). + crossedge = searchtet; + // Form a cavity of crossing tets. + success = formcavity(&searchtet, tg_missingshs, tg_crosstets, + tg_topfaces, tg_botfaces, tg_toppoints, + tg_botpoints); + if (success) { + if (!b->flipinsert) { + // Tetrahedralize the top part. Re-use 'tg_midfaces'. + delaunizecavity(tg_toppoints, tg_topfaces, tg_topshells, + tg_topnewtets, tg_crosstets, tg_midfaces); + // Tetrahedralize the bottom part. Re-use 'tg_midfaces'. + delaunizecavity(tg_botpoints, tg_botfaces, tg_botshells, + tg_botnewtets, tg_crosstets, tg_midfaces); + // Fill the cavity with new tets. + success = fillcavity(tg_topshells, tg_botshells, tg_midfaces, + tg_missingshs, tg_topnewtets, tg_botnewtets, + &crossedge); + if (success) { + // Cavity is remeshed. Delete old tets and outer new tets. + carvecavity(tg_crosstets, tg_topnewtets, tg_botnewtets); + } else { + restorecavity(tg_crosstets, tg_topnewtets, tg_botnewtets, + tg_missingshbds); + } + } else { + // Use the flip algorithm of Shewchuk to recover the subfaces. + flipinsertfacet(tg_crosstets, tg_toppoints, tg_botpoints, + tg_missingshverts); + // Recover the missing region. + success = fillregion(tg_missingshs, tg_missingshbds, tg_topshells); + assert(success); + // Clear working lists. + tg_crosstets->restart(); + tg_topfaces->restart(); + tg_botfaces->restart(); + tg_toppoints->restart(); + tg_botpoints->restart(); + } // b->flipinsert + + if (success) { + // Recover interior subfaces. + for (i = 0; i < caveencshlist->objects; i++) { + parysh = (face *) fastlookup(caveencshlist, i); + dir = scoutsubface(parysh, &searchtet); + if (dir != SHAREFACE) { + // Add this face at the end of the list, so it will be + // processed immediately. + tg_facfaces->newindex((void **) &parysh1); + *parysh1 = *parysh; + } + } + caveencshlist->restart(); + // Recover interior segments. This should always be recovered. + for (i = 0; i < caveencseglist->objects; i++) { + paryseg = (face *) fastlookup(caveencseglist, i); + dir = scoutsegment(sorg(*paryseg),sdest(*paryseg),&searchtet, + NULL, NULL); + assert(dir == SHAREEDGE); + // Insert this segment. + if (!issubseg(searchtet)) { + // Let the segment remember an adjacent tet. + sstbond1(*paryseg, searchtet); + // Bond the segment to all tets containing it. + neightet = searchtet; + do { + tssbond1(neightet, *paryseg); + fnextself(neightet); + } while (neightet.tet != searchtet.tet); + } else { + // Collision! Should not happen. + assert(0); + } + } + caveencseglist->restart(); + } // success - remesh cavity + } // success - form cavity + } else { + // Recover subfaces by retriangulate the surface mesh. + // Re-use tg_topshells for newshs. + success = fillregion(tg_missingshs, tg_missingshbds, tg_topshells); + } + + // Unmarktest all points of the missing region. + for (i = 0; i < tg_missingshverts->objects; i++) { + parypt = (point *) fastlookup(tg_missingshverts, i); + punmarktest(*parypt); + } + tg_missingshverts->restart(); + tg_missingshbds->restart(); + tg_missingshs->restart(); + + if (!success) { + // The missing region can not be recovered. Refine it. + refineregion(recentsh, tg_toppoints, tg_topfaces, tg_topshells, + tg_topnewtets, tg_crosstets, tg_midfaces); + // Clean the current list of facet subfaces. + // tg_facfaces->restart(); + } + } // while (tg_facfaces->objects) + + } // while ((subfacstack->objects) + + // Accumulate the dynamic memory. + totalworkmemory += (tg_crosstets->totalmemory + tg_topnewtets->totalmemory + + tg_botnewtets->totalmemory + tg_topfaces->totalmemory + + tg_botfaces->totalmemory + tg_midfaces->totalmemory + + tg_toppoints->totalmemory + tg_botpoints->totalmemory + + tg_facfaces->totalmemory + tg_topshells->totalmemory + + tg_botshells->totalmemory + tg_missingshs->totalmemory + + tg_missingshbds->totalmemory + + tg_missingshverts->totalmemory + + encseglist->totalmemory); + + // Delete arrays. + delete tg_crosstets; + delete tg_topnewtets; + delete tg_botnewtets; + delete tg_topfaces; + delete tg_botfaces; + delete tg_midfaces; + delete tg_toppoints; + delete tg_botpoints; + delete tg_facfaces; + delete tg_topshells; + delete tg_botshells; + delete tg_missingshs; + delete tg_missingshbds; + delete tg_missingshverts; + delete encseglist; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// constraineddelaunay() Create a constrained Delaunay tetrahedralization.// +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::constraineddelaunay(clock_t& tv) +{ + face searchsh, *parysh; + face searchseg, *paryseg; + int s, i; + + // Statistics. + long bakfillregioncount; + long bakcavitycount, bakcavityexpcount; + long bakseg_ref_count; + + if (!b->quiet) { + printf("Constrained Delaunay...\n"); + } + + makesegmentendpointsmap(); + + if (b->verbose) { + printf(" Delaunizing segments.\n"); + } + + checksubsegflag = 1; + + // Put all segments into the list (in random order). + subsegs->traversalinit(); + for (i = 0; i < subsegs->items; i++) { + s = randomnation(i + 1); + // Move the s-th seg to the i-th. + subsegstack->newindex((void **) &paryseg); + *paryseg = * (face *) fastlookup(subsegstack, s); + // Put i-th seg to be the s-th. + searchseg.sh = shellfacetraverse(subsegs); + //sinfect(searchseg); // Only save it once. + paryseg = (face *) fastlookup(subsegstack, s); + *paryseg = searchseg; + } + + // Recover non-Delaunay segments. + delaunizesegments(); + + if (b->verbose) { + printf(" Inserted %ld Steiner points.\n", st_segref_count); + } + + tv = clock(); + + if (b->verbose) { + printf(" Constraining facets.\n"); + } + + // Subfaces will be introduced. + checksubfaceflag = 1; + + bakfillregioncount = fillregioncount; + bakcavitycount = cavitycount; + bakcavityexpcount = cavityexpcount; + bakseg_ref_count = st_segref_count; + + // Randomly order the subfaces. + subfaces->traversalinit(); + for (i = 0; i < subfaces->items; i++) { + s = randomnation(i + 1); + // Move the s-th subface to the i-th. + subfacstack->newindex((void **) &parysh); + *parysh = * (face *) fastlookup(subfacstack, s); + // Put i-th subface to be the s-th. + searchsh.sh = shellfacetraverse(subfaces); + parysh = (face *) fastlookup(subfacstack, s); + *parysh = searchsh; + } + + // Recover facets. + constrainedfacets(); + + if (b->verbose) { + if (fillregioncount > bakfillregioncount) { + printf(" Remeshed %ld regions.\n", fillregioncount-bakfillregioncount); + } + if (cavitycount > bakcavitycount) { + printf(" Remeshed %ld cavities", cavitycount - bakcavitycount); + if (cavityexpcount - bakcavityexpcount) { + printf(" (%ld enlarged)", cavityexpcount - bakcavityexpcount); + } + printf(".\n"); + } + if (st_segref_count + st_facref_count - bakseg_ref_count > 0) { + printf(" Inserted %ld (%ld, %ld) refine points.\n", + st_segref_count + st_facref_count - bakseg_ref_count, + st_segref_count - bakseg_ref_count, st_facref_count); + } + } +} + +//// //// +//// //// +//// constrained_cxx ////////////////////////////////////////////////////////// + +//// steiner_cxx ////////////////////////////////////////////////////////////// +//// //// +//// //// + +/////////////////////////////////////////////////////////////////////////////// +// // +// checkflipeligibility() A call back function for boundary recovery. // +// // +// 'fliptype' indicates which elementary flip will be performed: 1 : 2-to-3, // +// and 2 : 3-to-2, respectively. // +// // +// 'pa, ..., pe' are the vertices involved in this flip, where [a,b,c] is // +// the flip face, and [d,e] is the flip edge. NOTE: 'pc' may be 'dummypoint',// +// other points must not be 'dummypoint'. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::checkflipeligibility(int fliptype, point pa, point pb, + point pc, point pd, point pe, + int level, int edgepivot, + flipconstraints* fc) +{ + point tmppts[3]; + enum interresult dir; + int types[2], poss[4]; + int intflag; + int rejflag = 0; + int i; + + if (fc->seg[0] != NULL) { + // A constraining edge is given (e.g., for edge recovery). + if (fliptype == 1) { + // A 2-to-3 flip: [a,b,c] => [e,d,a], [e,d,b], [e,d,c]. + tmppts[0] = pa; + tmppts[1] = pb; + tmppts[2] = pc; + for (i = 0; i < 3 && !rejflag; i++) { + if (tmppts[i] != dummypoint) { + // Test if the face [e,d,#] intersects the edge. + intflag = tri_edge_test(pe, pd, tmppts[i], fc->seg[0], fc->seg[1], + NULL, 1, types, poss); + if (intflag == 2) { + // They intersect at a single point. + dir = (enum interresult) types[0]; + if (dir == ACROSSFACE) { + // The interior of [e,d,#] intersect the segment. + rejflag = 1; + } else if (dir == ACROSSEDGE) { + if (poss[0] == 0) { + // The interior of [e,d] intersect the segment. + // Since [e,d] is the newly created edge. Reject this flip. + rejflag = 1; + } + } + } else if (intflag == 4) { + // They may intersect at either a point or a line segment. + dir = (enum interresult) types[0]; + if (dir == ACROSSEDGE) { + if (poss[0] == 0) { + // The interior of [e,d] intersect the segment. + // Since [e,d] is the newly created edge. Reject this flip. + rejflag = 1; + } + } + } + } // if (tmppts[0] != dummypoint) + } // i + } else if (fliptype == 2) { + // A 3-to-2 flip: [e,d,a], [e,d,b], [e,d,c] => [a,b,c] + if (pc != dummypoint) { + // Check if the new face [a,b,c] intersect the edge in its interior. + intflag = tri_edge_test(pa, pb, pc, fc->seg[0], fc->seg[1], NULL, + 1, types, poss); + if (intflag == 2) { + // They intersect at a single point. + dir = (enum interresult) types[0]; + if (dir == ACROSSFACE) { + // The interior of [a,b,c] intersect the segment. + rejflag = 1; // Do not flip. + } + } else if (intflag == 4) { + // [a,b,c] is coplanar with the edge. + dir = (enum interresult) types[0]; + if (dir == ACROSSEDGE) { + // The boundary of [a,b,c] intersect the segment. + rejflag = 1; // Do not flip. + } + } + } // if (pc != dummypoint) + } + } // if (fc->seg[0] != NULL) + + if ((fc->fac[0] != NULL) && !rejflag) { + // A constraining face is given (e.g., for face recovery). + if (fliptype == 1) { + // A 2-to-3 flip. + // Test if the new edge [e,d] intersects the face. + intflag = tri_edge_test(fc->fac[0], fc->fac[1], fc->fac[2], pe, pd, + NULL, 1, types, poss); + if (intflag == 2) { + // They intersect at a single point. + dir = (enum interresult) types[0]; + if (dir == ACROSSFACE) { + rejflag = 1; + } else if (dir == ACROSSEDGE) { + rejflag = 1; + } + } else if (intflag == 4) { + // The edge [e,d] is coplanar with the face. + // There may be two intersections. + for (i = 0; i < 2 && !rejflag; i++) { + dir = (enum interresult) types[i]; + if (dir == ACROSSFACE) { + rejflag = 1; + } else if (dir == ACROSSEDGE) { + rejflag = 1; + } + } + } + } // if (fliptype == 1) + } // if (fc->fac[0] != NULL) + + if ((fc->remvert != NULL) && !rejflag) { + // The vertex is going to be removed. Do not create a new edge which + // contains this vertex. + if (fliptype == 1) { + // A 2-to-3 flip. + if ((pd == fc->remvert) || (pe == fc->remvert)) { + rejflag = 1; + } + } + } + + if (fc->remove_large_angle && !rejflag) { + // Remove a large dihedral angle. Do not create a new small angle. + REAL cosmaxd = 0, diff; + if (fliptype == 1) { + // We assume that neither 'a' nor 'b' is dummypoint. + assert((pa != dummypoint) && (pb != dummypoint)); // SELF_CHECK + // A 2-to-3 flip: [a,b,c] => [e,d,a], [e,d,b], [e,d,c]. + // The new tet [e,d,a,b] will be flipped later. Only two new tets: + // [e,d,b,c] and [e,d,c,a] need to be checked. + if ((pc != dummypoint) && (pe != dummypoint) && (pd != dummypoint)) { + // Get the largest dihedral angle of [e,d,b,c]. + tetalldihedral(pe, pd, pb, pc, NULL, &cosmaxd, NULL); + diff = cosmaxd - fc->cosdihed_in; + if (fabs(diff/fc->cosdihed_in) < b->epsilon) diff = 0.0; // Rounding. + if (diff <= 0) { //if (cosmaxd <= fc->cosdihed_in) { + rejflag = 1; + } else { + // Record the largest new angle. + if (cosmaxd < fc->cosdihed_out) { + fc->cosdihed_out = cosmaxd; + } + // Get the largest dihedral angle of [e,d,c,a]. + tetalldihedral(pe, pd, pc, pa, NULL, &cosmaxd, NULL); + diff = cosmaxd - fc->cosdihed_in; + if (fabs(diff/fc->cosdihed_in) < b->epsilon) diff = 0.0; // Rounding. + if (diff <= 0) { //if (cosmaxd <= fc->cosdihed_in) { + rejflag = 1; + } else { + // Record the largest new angle. + if (cosmaxd < fc->cosdihed_out) { + fc->cosdihed_out = cosmaxd; + } + } + } + } // if (pc != dummypoint && ...) + } else if (fliptype == 2) { + // A 3-to-2 flip: [e,d,a], [e,d,b], [e,d,c] => [a,b,c] + // We assume that neither 'e' nor 'd' is dummypoint. + assert((pe != dummypoint) && (pd != dummypoint)); // SELF_CHECK + if (level == 0) { + // Both new tets [a,b,c,d] and [b,a,c,e] are new tets. + if ((pa != dummypoint) && (pb != dummypoint) && (pc != dummypoint)) { + // Get the largest dihedral angle of [a,b,c,d]. + tetalldihedral(pa, pb, pc, pd, NULL, &cosmaxd, NULL); + diff = cosmaxd - fc->cosdihed_in; + if (fabs(diff/fc->cosdihed_in) < b->epsilon) diff = 0.0; // Rounding + if (diff <= 0) { //if (cosmaxd <= fc->cosdihed_in) { + rejflag = 1; + } else { + // Record the largest new angle. + if (cosmaxd < fc->cosdihed_out) { + fc->cosdihed_out = cosmaxd; + } + // Get the largest dihedral angle of [b,a,c,e]. + tetalldihedral(pb, pa, pc, pe, NULL, &cosmaxd, NULL); + diff = cosmaxd - fc->cosdihed_in; + if (fabs(diff/fc->cosdihed_in) < b->epsilon) diff = 0.0;// Rounding + if (diff <= 0) { //if (cosmaxd <= fc->cosdihed_in) { + rejflag = 1; + } else { + // Record the largest new angle. + if (cosmaxd < fc->cosdihed_out) { + fc->cosdihed_out = cosmaxd; + } + } + } + } + } else { // level > 0 + assert(edgepivot != 0); + if (edgepivot == 1) { + // The new tet [a,b,c,d] will be flipped. Only check [b,a,c,e]. + if ((pa != dummypoint) && (pb != dummypoint) && (pc != dummypoint)) { + // Get the largest dihedral angle of [b,a,c,e]. + tetalldihedral(pb, pa, pc, pe, NULL, &cosmaxd, NULL); + diff = cosmaxd - fc->cosdihed_in; + if (fabs(diff/fc->cosdihed_in) < b->epsilon) diff = 0.0;// Rounding + if (diff <= 0) { //if (cosmaxd <= fc->cosdihed_in) { + rejflag = 1; + } else { + // Record the largest new angle. + if (cosmaxd < fc->cosdihed_out) { + fc->cosdihed_out = cosmaxd; + } + } + } + } else { + assert(edgepivot == 2); + // The new tet [b,a,c,e] will be flipped. Only check [a,b,c,d]. + if ((pa != dummypoint) && (pb != dummypoint) && (pc != dummypoint)) { + // Get the largest dihedral angle of [b,a,c,e]. + tetalldihedral(pa, pb, pc, pd, NULL, &cosmaxd, NULL); + diff = cosmaxd - fc->cosdihed_in; + if (fabs(diff/fc->cosdihed_in) < b->epsilon) diff = 0.0;// Rounding + if (diff <= 0) { //if (cosmaxd <= fc->cosdihed_in) { + rejflag = 1; + } else { + // Record the largest new angle. + if (cosmaxd < fc->cosdihed_out) { + fc->cosdihed_out = cosmaxd; + } + } + } + } // edgepivot + } // level + } + } + + return rejflag; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// removeedgebyflips() Remove an edge by flips. // +// // +// 'flipedge' is a non-convex or flat edge [a,b,#,#] to be removed. // +// // +// The return value is a positive integer, it indicates whether the edge is // +// removed or not. A value "2" means the edge is removed, otherwise, the // +// edge is not removed and the value (must >= 3) is the current number of // +// tets in the edge star. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::removeedgebyflips(triface *flipedge, flipconstraints* fc) +{ + triface *abtets, spintet; + int t1ver; + int n, nn, i; + + + if (checksubsegflag) { + // Do not flip a segment. + if (issubseg(*flipedge)) { + if (fc->collectencsegflag) { + face checkseg, *paryseg; + tsspivot1(*flipedge, checkseg); + if (!sinfected(checkseg)) { + // Queue this segment in list. + sinfect(checkseg); + caveencseglist->newindex((void **) &paryseg); + *paryseg = checkseg; + } + } + return 0; + } + } + + // Count the number of tets at edge [a,b]. + n = 0; + spintet = *flipedge; + while (1) { + n++; + fnextself(spintet); + if (spintet.tet == flipedge->tet) break; + } + assert(n >= 3); + + if ((b->flipstarsize > 0) && (n > b->flipstarsize)) { + // The star size exceeds the limit. + return 0; // Do not flip it. + } + + // Allocate spaces. + abtets = new triface[n]; + // Collect the tets at edge [a,b]. + spintet = *flipedge; + i = 0; + while (1) { + abtets[i] = spintet; + setelemcounter(abtets[i], 1); + i++; + fnextself(spintet); + if (spintet.tet == flipedge->tet) break; + } + + + // Try to flip the edge (level = 0, edgepivot = 0). + nn = flipnm(abtets, n, 0, 0, fc); + + + if (nn > 2) { + // Edge is not flipped. Unmarktest the remaining tets in Star(ab). + for (i = 0; i < nn; i++) { + setelemcounter(abtets[i], 0); + } + // Restore the input edge (needed by Lawson's flip). + *flipedge = abtets[0]; + } + + // Release the temporary allocated spaces. + // NOTE: fc->unflip must be 0. + int bakunflip = fc->unflip; + fc->unflip = 0; + flipnm_post(abtets, n, nn, 0, fc); + fc->unflip = bakunflip; + + delete [] abtets; + + return nn; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// removefacebyflips() Remove a face by flips. // +// // +// Return 1 if the face is removed. Otherwise, return 0. // +// // +// ASSUMPTIONS: // +// - 'flipface' must not be a hull face. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::removefacebyflips(triface *flipface, flipconstraints* fc) +{ + if (checksubfaceflag) { + if (issubface(*flipface)) { + return 0; + } + } + + triface fliptets[3], flipedge; + point pa, pb, pc, pd, pe; + REAL ori; + int reducflag = 0; + + fliptets[0] = *flipface; + fsym(*flipface, fliptets[1]); + pa = org(fliptets[0]); + pb = dest(fliptets[0]); + pc = apex(fliptets[0]); + pd = oppo(fliptets[0]); + pe = oppo(fliptets[1]); + + ori = orient3d(pa, pb, pd, pe); + if (ori > 0) { + ori = orient3d(pb, pc, pd, pe); + if (ori > 0) { + ori = orient3d(pc, pa, pd, pe); + if (ori > 0) { + // Found a 2-to-3 flip. + reducflag = 1; + } else { + eprev(*flipface, flipedge); // [c,a] + } + } else { + enext(*flipface, flipedge); // [b,c] + } + } else { + flipedge = *flipface; // [a,b] + } + + if (reducflag) { + // A 2-to-3 flip is found. + flip23(fliptets, 0, fc); + return 1; + } else { + // Try to flip the selected edge of this face. + if (removeedgebyflips(&flipedge, fc) == 2) { + return 1; + } + } + + // Face is not removed. + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// recoveredge() Recover an edge in current tetrahedralization. // +// // +// If the edge is recovered, 'searchtet' returns a tet containing the edge. // +// // +// This edge may intersect a set of faces and edges in the mesh. All these // +// faces or edges are needed to be removed. // +// // +// If the parameter 'fullsearch' is set, it tries to flip any face or edge // +// that intersects the recovering edge. Otherwise, only the face or edge // +// which is visible by 'startpt' is tried. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::recoveredgebyflips(point startpt, point endpt, + triface* searchtet, int fullsearch) +{ + flipconstraints fc; + enum interresult dir; + + fc.seg[0] = startpt; + fc.seg[1] = endpt; + fc.checkflipeligibility = 1; + + // The mainloop of the edge reocvery. + while (1) { // Loop I + + // Search the edge from 'startpt'. + point2tetorg(startpt, *searchtet); + dir = finddirection(searchtet, endpt); + if (dir == ACROSSVERT) { + if (dest(*searchtet) == endpt) { + return 1; // Edge is recovered. + } else { + terminatetetgen(this, 3); // // It may be a PLC problem. + } + } + + // The edge is missing. + + // Try to flip the first intersecting face/edge. + enextesymself(*searchtet); // Go to the opposite face. + if (dir == ACROSSFACE) { + // A face is intersected with the segment. Try to flip it. + if (removefacebyflips(searchtet, &fc)) { + continue; + } + } else if (dir == ACROSSEDGE) { + // An edge is intersected with the segment. Try to flip it. + if (removeedgebyflips(searchtet, &fc) == 2) { + continue; + } + } else { + terminatetetgen(this, 3); // It may be a PLC problem. + } + + // The edge is missing. + + if (fullsearch) { + // Try to flip one of the faces/edges which intersects the edge. + triface neightet, spintet; + point pa, pb, pc, pd; + badface bakface; + enum interresult dir1; + int types[2], poss[4], pos = 0; + int success = 0; + int t1ver; + int i, j; + + // Loop through the sequence of intersecting faces/edges from + // 'startpt' to 'endpt'. + point2tetorg(startpt, *searchtet); + dir = finddirection(searchtet, endpt); + //assert(dir != ACROSSVERT); + + // Go to the face/edge intersecting the searching edge. + enextesymself(*searchtet); // Go to the opposite face. + // This face/edge has been tried in previous step. + + while (1) { // Loop I-I + + // Find the next intersecting face/edge. + fsymself(*searchtet); + if (dir == ACROSSFACE) { + neightet = *searchtet; + j = (neightet.ver & 3); // j is the current face number. + for (i = j + 1; i < j + 4; i++) { + neightet.ver = (i % 4); + pa = org(neightet); + pb = dest(neightet); + pc = apex(neightet); + pd = oppo(neightet); // The above point. + if (tri_edge_test(pa,pb,pc,startpt,endpt, pd, 1, types, poss)) { + dir = (enum interresult) types[0]; + pos = poss[0]; + break; + } else { + dir = DISJOINT; + pos = 0; + } + } // i + // There must be an intersection face/edge. + assert(dir != DISJOINT); // SELF_CHECK + } else { + assert(dir == ACROSSEDGE); + while (1) { // Loop I-I-I + // Check the two opposite faces (of the edge) in 'searchtet'. + for (i = 0; i < 2; i++) { + if (i == 0) { + enextesym(*searchtet, neightet); + } else { + eprevesym(*searchtet, neightet); + } + pa = org(neightet); + pb = dest(neightet); + pc = apex(neightet); + pd = oppo(neightet); // The above point. + if (tri_edge_test(pa,pb,pc,startpt,endpt,pd,1, types, poss)) { + dir = (enum interresult) types[0]; + pos = poss[0]; + break; // for loop + } else { + dir = DISJOINT; + pos = 0; + } + } // i + if (dir != DISJOINT) { + // Find an intersection face/edge. + break; // Loop I-I-I + } + // No intersection. Rotate to the next tet at the edge. + fnextself(*searchtet); + } // while (1) // Loop I-I-I + } + + // Adjust to the intersecting edge/vertex. + for (i = 0; i < pos; i++) { + enextself(neightet); + } + + if (dir == SHAREVERT) { + // Check if we have reached the 'endpt'. + pd = org(neightet); + if (pd == endpt) { + // Failed to recover the edge. + break; // Loop I-I + } else { + // We need to further check this case. It might be a PLC problem + // or a Steiner point that was added at a bad location. + assert(0); + } + } + + // The next to be flipped face/edge. + *searchtet = neightet; + + // Bakup this face (tetrahedron). + bakface.forg = org(*searchtet); + bakface.fdest = dest(*searchtet); + bakface.fapex = apex(*searchtet); + bakface.foppo = oppo(*searchtet); + + // Try to flip this intersecting face/edge. + if (dir == ACROSSFACE) { + if (removefacebyflips(searchtet, &fc)) { + success = 1; + break; // Loop I-I + } + } else if (dir == ACROSSEDGE) { + if (removeedgebyflips(searchtet, &fc) == 2) { + success = 1; + break; // Loop I-I + } + } else { + assert(0); // A PLC problem. + } + + // The face/edge is not flipped. + if ((searchtet->tet == NULL) || + (org(*searchtet) != bakface.forg) || + (dest(*searchtet) != bakface.fdest) || + (apex(*searchtet) != bakface.fapex) || + (oppo(*searchtet) != bakface.foppo)) { + // 'searchtet' was flipped. We must restore it. + point2tetorg(bakface.forg, *searchtet); + dir1 = finddirection(searchtet, bakface.fdest); + if (dir1 == ACROSSVERT) { + assert(dest(*searchtet) == bakface.fdest); + spintet = *searchtet; + while (1) { + if (apex(spintet) == bakface.fapex) { + // Found the face. + *searchtet = spintet; + break; + } + fnextself(spintet); + if (spintet.tet == searchtet->tet) { + searchtet->tet = NULL; + break; // Not find. + } + } // while (1) + if (searchtet->tet != NULL) { + if (oppo(*searchtet) != bakface.foppo) { + fsymself(*searchtet); + if (oppo(*searchtet) != bakface.foppo) { + assert(0); // Check this case. + searchtet->tet = NULL; + break; // Not find. + } + } + } + } else { + searchtet->tet = NULL; // Not find. + } + if (searchtet->tet == NULL) { + success = 0; // This face/edge has been destroyed. + break; // Loop I-I + } + } + } // while (1) // Loop I-I + + if (success) { + // One of intersecting faces/edges is flipped. + continue; + } + + } // if (fullsearch) + + // The edge is missing. + break; // Loop I + + } // while (1) // Loop I + + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// add_steinerpt_in_schoenhardtpoly() Insert a Steiner point in a Schoen- // +// hardt polyhedron. // +// // +// 'abtets' is an array of n tets which all share at the edge [a,b]. Let the // +// tets are [a,b,p0,p1], [a,b,p1,p2], ..., [a,b,p_(n-2),p_(n-1)]. Moreover, // +// the edge [p0,p_(n-1)] intersects all of the tets in 'abtets'. A special // +// case is that the edge [p0,p_(n-1)] is coplanar with the edge [a,b]. // +// Such set of tets arises when we want to recover an edge from 'p0' to 'p_ // +// (n-1)', and the number of tets at [a,b] can not be reduced by any flip. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::add_steinerpt_in_schoenhardtpoly(triface *abtets, int n, + int chkencflag) +{ + triface worktet, *parytet; + triface faketet1, faketet2; + point pc, pd, steinerpt; + insertvertexflags ivf; + optparameters opm; + REAL vcd[3], sampt[3], smtpt[3]; + REAL maxminvol = 0.0, minvol = 0.0, ori; + int success, maxidx = 0; + int it, i; + + + pc = apex(abtets[0]); // pc = p0 + pd = oppo(abtets[n-1]); // pd = p_(n-1) + + + // Find an optimial point in edge [c,d]. It is visible by all outer faces + // of 'abtets', and it maxmizes the min volume. + + // initialize the list of 2n boundary faces. + for (i = 0; i < n; i++) { + edestoppo(abtets[i], worktet); // [p_i,p_i+1,a] + cavetetlist->newindex((void **) &parytet); + *parytet = worktet; + eorgoppo(abtets[i], worktet); // [p_i+1,p_i,b] + cavetetlist->newindex((void **) &parytet); + *parytet = worktet; + } + + int N = 100; + REAL stepi = 0.01; + + // Search the point along the edge [c,d]. + for (i = 0; i < 3; i++) vcd[i] = pd[i] - pc[i]; + + // Sample N points in edge [c,d]. + for (it = 1; it < N; it++) { + for (i = 0; i < 3; i++) { + sampt[i] = pc[i] + (stepi * (double) it) * vcd[i]; + } + for (i = 0; i < cavetetlist->objects; i++) { + parytet = (triface *) fastlookup(cavetetlist, i); + ori = orient3d(dest(*parytet), org(*parytet), apex(*parytet), sampt); + if (i == 0) { + minvol = ori; + } else { + if (minvol > ori) minvol = ori; + } + } // i + if (it == 1) { + maxminvol = minvol; + maxidx = it; + } else { + if (maxminvol < minvol) { + maxminvol = minvol; + maxidx = it; + } + } + } // it + + if (maxminvol <= 0) { + cavetetlist->restart(); + return 0; + } + + for (i = 0; i < 3; i++) { + smtpt[i] = pc[i] + (stepi * (double) maxidx) * vcd[i]; + } + + // Create two faked tets to hold the two non-existing boundary faces: + // [d,c,a] and [c,d,b]. + maketetrahedron(&faketet1); + setvertices(faketet1, pd, pc, org(abtets[0]), dummypoint); + cavetetlist->newindex((void **) &parytet); + *parytet = faketet1; + maketetrahedron(&faketet2); + setvertices(faketet2, pc, pd, dest(abtets[0]), dummypoint); + cavetetlist->newindex((void **) &parytet); + *parytet = faketet2; + + // Point smooth options. + opm.max_min_volume = 1; + opm.numofsearchdirs = 20; + opm.searchstep = 0.001; + opm.maxiter = 100; // Limit the maximum iterations. + opm.initval = 0.0; // Initial volume is zero. + + // Try to relocate the point into the inside of the polyhedron. + success = smoothpoint(smtpt, cavetetlist, 1, &opm); + + if (success) { + while (opm.smthiter == 100) { + // It was relocated and the prescribed maximum iteration reached. + // Try to increase the search stepsize. + opm.searchstep *= 10.0; + //opm.maxiter = 100; // Limit the maximum iterations. + opm.initval = opm.imprval; + opm.smthiter = 0; // Init. + smoothpoint(smtpt, cavetetlist, 1, &opm); + } + } // if (success) + + // Delete the two faked tets. + tetrahedrondealloc(faketet1.tet); + tetrahedrondealloc(faketet2.tet); + + cavetetlist->restart(); + + if (!success) { + return 0; + } + + + // Insert the Steiner point. + makepoint(&steinerpt, FREEVOLVERTEX); + for (i = 0; i < 3; i++) steinerpt[i] = smtpt[i]; + + // Insert the created Steiner point. + for (i = 0; i < n; i++) { + infect(abtets[i]); + caveoldtetlist->newindex((void **) &parytet); + *parytet = abtets[i]; + } + worktet = abtets[0]; // No need point location. + ivf.iloc = (int) INSTAR; + ivf.chkencflag = chkencflag; + ivf.assignmeshsize = b->metric; + if (ivf.assignmeshsize) { + // Search the tet containing 'steinerpt' for size interpolation. + locate(steinerpt, &(abtets[0])); + worktet = abtets[0]; + } + + // Insert the new point into the tetrahedralization T. + // Note that T is convex (nonconvex = 0). + if (insertpoint(steinerpt, &worktet, NULL, NULL, &ivf)) { + // The vertex has been inserted. + st_volref_count++; + if (steinerleft > 0) steinerleft--; + return 1; + } else { + // Not inserted. + pointdealloc(steinerpt); + return 0; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// add_steinerpt_in_segment() Add a Steiner point inside a segment. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::add_steinerpt_in_segment(face* misseg, int searchlevel) +{ + triface searchtet; + face *paryseg, candseg; + point startpt, endpt, pc, pd; + flipconstraints fc; + enum interresult dir; + REAL P[3], Q[3], tp, tq; + REAL len, smlen = 0, split = 0, split_q = 0; + int success; + int i; + + startpt = sorg(*misseg); + endpt = sdest(*misseg); + + fc.seg[0] = startpt; + fc.seg[1] = endpt; + fc.checkflipeligibility = 1; + fc.collectencsegflag = 1; + + point2tetorg(startpt, searchtet); + dir = finddirection(&searchtet, endpt); + //assert(dir != ACROSSVERT); + + // Try to flip the first intersecting face/edge. + enextesymself(searchtet); // Go to the opposite face. + + int bak_fliplinklevel = b->fliplinklevel; + b->fliplinklevel = searchlevel; + + if (dir == ACROSSFACE) { + // A face is intersected with the segment. Try to flip it. + success = removefacebyflips(&searchtet, &fc); + assert(success == 0); + } else if (dir == ACROSSEDGE) { + // An edge is intersected with the segment. Try to flip it. + success = removeedgebyflips(&searchtet, &fc); + assert(success != 2); + } else { + terminatetetgen(this, 3); // It may be a PLC problem. + } + + split = 0; + for (i = 0; i < caveencseglist->objects; i++) { + paryseg = (face *) fastlookup(caveencseglist, i); + suninfect(*paryseg); + // Calculate the shortest edge between the two lines. + pc = sorg(*paryseg); + pd = sdest(*paryseg); + tp = tq = 0; + if (linelineint(startpt, endpt, pc, pd, P, Q, &tp, &tq)) { + // Does the shortest edge lie between the two segments? + // Round tp and tq. + if ((tp > 0) && (tq < 1)) { + if (tp < 0.5) { + if (tp < (b->epsilon * 1e+3)) tp = 0.0; + } else { + if ((1.0 - tp) < (b->epsilon * 1e+3)) tp = 1.0; + } + } + if ((tp <= 0) || (tp >= 1)) continue; + if ((tq > 0) && (tq < 1)) { + if (tq < 0.5) { + if (tq < (b->epsilon * 1e+3)) tq = 0.0; + } else { + if ((1.0 - tq) < (b->epsilon * 1e+3)) tq = 1.0; + } + } + if ((tq <= 0) || (tq >= 1)) continue; + // It is a valid shortest edge. Calculate its length. + len = distance(P, Q); + if (split == 0) { + smlen = len; + split = tp; + split_q = tq; + candseg = *paryseg; + } else { + if (len < smlen) { + smlen = len; + split = tp; + split_q = tq; + candseg = *paryseg; + } + } + } + } + + caveencseglist->restart(); + b->fliplinklevel = bak_fliplinklevel; + + if (split == 0) { + // Found no crossing segment. + return 0; + } + + face splitsh; + face splitseg; + point steinerpt, *parypt; + insertvertexflags ivf; + + if (b->addsteiner_algo == 1) { + // Split the segment at the closest point to a near segment. + makepoint(&steinerpt, FREESEGVERTEX); + for (i = 0; i < 3; i++) { + steinerpt[i] = startpt[i] + split * (endpt[i] - startpt[i]); + } + } else { // b->addsteiner_algo == 2 + for (i = 0; i < 3; i++) { + P[i] = startpt[i] + split * (endpt[i] - startpt[i]); + } + pc = sorg(candseg); + pd = sdest(candseg); + for (i = 0; i < 3; i++) { + Q[i] = pc[i] + split_q * (pd[i] - pc[i]); + } + makepoint(&steinerpt, FREEVOLVERTEX); + for (i = 0; i < 3; i++) { + steinerpt[i] = 0.5 * (P[i] + Q[i]); + } + } + + // We need to locate the point. Start searching from 'searchtet'. + if (split < 0.5) { + point2tetorg(startpt, searchtet); + } else { + point2tetorg(endpt, searchtet); + } + if (b->addsteiner_algo == 1) { + splitseg = *misseg; + spivot(*misseg, splitsh); + } else { + splitsh.sh = NULL; + splitseg.sh = NULL; + } + ivf.iloc = (int) OUTSIDE; + ivf.bowywat = 1; + ivf.lawson = 0; + ivf.rejflag = 0; + ivf.chkencflag = 0; + ivf.sloc = (int) ONEDGE; + ivf.sbowywat = 1; + ivf.splitbdflag = 0; + ivf.validflag = 1; + ivf.respectbdflag = 1; + ivf.assignmeshsize = b->metric; + + if (!insertpoint(steinerpt, &searchtet, &splitsh, &splitseg, &ivf)) { + pointdealloc(steinerpt); + return 0; + } + + if (b->addsteiner_algo == 1) { + // Save this Steiner point (for removal). + // Re-use the array 'subvertstack'. + subvertstack->newindex((void **) &parypt); + *parypt = steinerpt; + st_segref_count++; + } else { // b->addsteiner_algo == 2 + // Queue the segment for recovery. + subsegstack->newindex((void **) &paryseg); + *paryseg = *misseg; + st_volref_count++; + } + if (steinerleft > 0) steinerleft--; + + return 1; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// addsteiner4recoversegment() Add a Steiner point for recovering a seg. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::addsteiner4recoversegment(face* misseg, int splitsegflag) +{ + triface *abtets, searchtet, spintet; + face splitsh; + face *paryseg; + point startpt, endpt; + point pa, pb, pd, steinerpt, *parypt; + enum interresult dir; + insertvertexflags ivf; + int types[2], poss[4]; + int n, endi, success; + int t1ver; + int i; + + startpt = sorg(*misseg); + if (pointtype(startpt) == FREESEGVERTEX) { + sesymself(*misseg); + startpt = sorg(*misseg); + } + endpt = sdest(*misseg); + + // Try to recover the edge by adding Steiner points. + point2tetorg(startpt, searchtet); + dir = finddirection(&searchtet, endpt); + enextself(searchtet); + //assert(apex(searchtet) == startpt); + + if (dir == ACROSSFACE) { + // The segment is crossing at least 3 faces. Find the common edge of + // the first 3 crossing faces. + esymself(searchtet); + fsym(searchtet, spintet); + pd = oppo(spintet); + for (i = 0; i < 3; i++) { + pa = org(spintet); + pb = dest(spintet); + //pc = apex(neightet); + if (tri_edge_test(pa, pb, pd, startpt, endpt, NULL, 1, types, poss)) { + break; // Found the edge. + } + enextself(spintet); + eprevself(searchtet); + } + assert(i < 3); + esymself(searchtet); + } else { + assert(dir == ACROSSEDGE); + // PLC check. + if (issubseg(searchtet)) { + face checkseg; + tsspivot1(searchtet, checkseg); + printf("Found two segments intersect each other.\n"); + pa = farsorg(*misseg); + pb = farsdest(*misseg); + printf(" 1st: [%d,%d] %d.\n", pointmark(pa), pointmark(pb), + shellmark(*misseg)); + pa = farsorg(checkseg); + pb = farsdest(checkseg); + printf(" 2nd: [%d,%d] %d.\n", pointmark(pa), pointmark(pb), + shellmark(checkseg)); + terminatetetgen(this, 3); + } + } + assert(apex(searchtet) == startpt); + + spintet = searchtet; + n = 0; endi = -1; + while (1) { + // Check if the endpt appears in the star. + if (apex(spintet) == endpt) { + endi = n; // Remember the position of endpt. + } + n++; // Count a tet in the star. + fnextself(spintet); + if (spintet.tet == searchtet.tet) break; + } + assert(n >= 3); + + if (endi > 0) { + // endpt is also in the edge star + // Get all tets in the edge star. + abtets = new triface[n]; + spintet = searchtet; + for (i = 0; i < n; i++) { + abtets[i] = spintet; + fnextself(spintet); + } + + success = 0; + + if (dir == ACROSSFACE) { + // Find a Steiner points inside the polyhedron. + if (add_steinerpt_in_schoenhardtpoly(abtets, endi, 0)) { + success = 1; + } + } else if (dir == ACROSSEDGE) { + if (n > 4) { + // In this case, 'abtets' is separated by the plane (containing the + // two intersecting edges) into two parts, P1 and P2, where P1 + // consists of 'endi' tets: abtets[0], abtets[1], ..., + // abtets[endi-1], and P2 consists of 'n - endi' tets: + // abtets[endi], abtets[endi+1], abtets[n-1]. + if (endi > 2) { // P1 + // There are at least 3 tets in the first part. + if (add_steinerpt_in_schoenhardtpoly(abtets, endi, 0)) { + success++; + } + } + if ((n - endi) > 2) { // P2 + // There are at least 3 tets in the first part. + if (add_steinerpt_in_schoenhardtpoly(&(abtets[endi]), n - endi, 0)) { + success++; + } + } + } else { + // In this case, a 4-to-4 flip should be re-cover the edge [c,d]. + // However, there will be invalid tets (either zero or negtive + // volume). Otherwise, [c,d] should already be recovered by the + // recoveredge() function. + terminatetetgen(this, 2); // Report a bug. + } + } else { + terminatetetgen(this, 10); // A PLC problem. + } + + delete [] abtets; + + if (success) { + // Add the missing segment back to the recovering list. + subsegstack->newindex((void **) &paryseg); + *paryseg = *misseg; + return 1; + } + } // if (endi > 0) + + if (!splitsegflag) { + return 0; + } + + if (b->verbose > 2) { + printf(" Splitting segment (%d, %d)\n", pointmark(startpt), + pointmark(endpt)); + } + steinerpt = NULL; + + if (b->addsteiner_algo > 0) { // -Y/1 or -Y/2 + if (add_steinerpt_in_segment(misseg, 3)) { + return 1; + } + sesymself(*misseg); + if (add_steinerpt_in_segment(misseg, 3)) { + return 1; + } + sesymself(*misseg); + } + + + + + if (steinerpt == NULL) { + // Split the segment at its midpoint. + makepoint(&steinerpt, FREESEGVERTEX); + for (i = 0; i < 3; i++) { + steinerpt[i] = 0.5 * (startpt[i] + endpt[i]); + } + + // We need to locate the point. + assert(searchtet.tet != NULL); // Start searching from 'searchtet'. + spivot(*misseg, splitsh); + ivf.iloc = (int) OUTSIDE; + ivf.bowywat = 1; + ivf.lawson = 0; + ivf.rejflag = 0; + ivf.chkencflag = 0; + ivf.sloc = (int) ONEDGE; + ivf.sbowywat = 1; + ivf.splitbdflag = 0; + ivf.validflag = 1; + ivf.respectbdflag = 1; + ivf.assignmeshsize = b->metric; + if (!insertpoint(steinerpt, &searchtet, &splitsh, misseg, &ivf)) { + assert(0); + } + } // if (endi > 0) + + // Save this Steiner point (for removal). + // Re-use the array 'subvertstack'. + subvertstack->newindex((void **) &parypt); + *parypt = steinerpt; + + st_segref_count++; + if (steinerleft > 0) steinerleft--; + + return 1; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// recoversegments() Recover all segments. // +// // +// All segments need to be recovered are in 'subsegstack'. // +// // +// This routine first tries to recover each segment by only using flips. If // +// no flip is possible, and the flag 'steinerflag' is set, it then tries to // +// insert Steiner points near or in the segment. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::recoversegments(arraypool *misseglist, int fullsearch, + int steinerflag) +{ + triface searchtet, spintet; + face sseg, *paryseg; + point startpt, endpt; + int success; + int t1ver; + long bak_inpoly_count = st_volref_count; + long bak_segref_count = st_segref_count; + + if (b->verbose > 1) { + printf(" Recover segments [%s level = %2d] #: %ld.\n", + (b->fliplinklevel > 0) ? "fixed" : "auto", + (b->fliplinklevel > 0) ? b->fliplinklevel : autofliplinklevel, + subsegstack->objects); + } + + // Loop until 'subsegstack' is empty. + while (subsegstack->objects > 0l) { + // seglist is used as a stack. + subsegstack->objects--; + paryseg = (face *) fastlookup(subsegstack, subsegstack->objects); + sseg = *paryseg; + + // Check if this segment has been recovered. + sstpivot1(sseg, searchtet); + if (searchtet.tet != NULL) { + continue; // Not a missing segment. + } + + startpt = sorg(sseg); + endpt = sdest(sseg); + + if (b->verbose > 2) { + printf(" Recover segment (%d, %d).\n", pointmark(startpt), + pointmark(endpt)); + } + + success = 0; + + if (recoveredgebyflips(startpt, endpt, &searchtet, 0)) { + success = 1; + } else { + // Try to recover it from the other direction. + if (recoveredgebyflips(endpt, startpt, &searchtet, 0)) { + success = 1; + } + } + + if (!success && fullsearch) { + if (recoveredgebyflips(startpt, endpt, &searchtet, fullsearch)) { + success = 1; + } + } + + if (success) { + // Segment is recovered. Insert it. + // Let the segment remember an adjacent tet. + sstbond1(sseg, searchtet); + // Bond the segment to all tets containing it. + spintet = searchtet; + do { + tssbond1(spintet, sseg); + fnextself(spintet); + } while (spintet.tet != searchtet.tet); + } else { + if (steinerflag > 0) { + // Try to recover the segment but do not split it. + if (addsteiner4recoversegment(&sseg, 0)) { + success = 1; + } + if (!success && (steinerflag > 1)) { + // Split the segment. + addsteiner4recoversegment(&sseg, 1); + success = 1; + } + } + if (!success) { + if (misseglist != NULL) { + // Save this segment. + misseglist->newindex((void **) &paryseg); + *paryseg = sseg; + } + } + } + + } // while (subsegstack->objects > 0l) + + if (steinerflag) { + if (b->verbose > 1) { + // Report the number of added Steiner points. + if (st_volref_count > bak_inpoly_count) { + printf(" Add %ld Steiner points in volume.\n", + st_volref_count - bak_inpoly_count); + } + if (st_segref_count > bak_segref_count) { + printf(" Add %ld Steiner points in segments.\n", + st_segref_count - bak_segref_count); + } + } + } + + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// recoverfacebyflips() Recover a face by flips. // +// // +// If 'searchsh' is not NULL, it is a subface to be recovered. It is only // +// used for checking self-intersections. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::recoverfacebyflips(point pa, point pb, point pc, + face *searchsh, triface* searchtet) +{ + triface spintet, flipedge; + point pd, pe; + enum interresult dir; + flipconstraints fc; + int types[2], poss[4], intflag; + int success, success1; + int t1ver; + int i, j; + + + fc.fac[0] = pa; + fc.fac[1] = pb; + fc.fac[2] = pc; + fc.checkflipeligibility = 1; + success = 0; + + for (i = 0; i < 3 && !success; i++) { + while (1) { + // Get a tet containing the edge [a,b]. + point2tetorg(fc.fac[i], *searchtet); + dir = finddirection(searchtet, fc.fac[(i+1)%3]); + //assert(dir == ACROSSVERT); + assert(dest(*searchtet) == fc.fac[(i+1)%3]); + // Search the face [a,b,c] + spintet = *searchtet; + while (1) { + if (apex(spintet) == fc.fac[(i+2)%3]) { + // Found the face. + *searchtet = spintet; + // Return the face [a,b,c]. + for (j = i; j > 0; j--) { + eprevself(*searchtet); + } + success = 1; + break; + } + fnextself(spintet); + if (spintet.tet == searchtet->tet) break; + } // while (1) + if (success) break; + // The face is missing. Try to recover it. + success1 = 0; + // Find a crossing edge of this face. + spintet = *searchtet; + while (1) { + pd = apex(spintet); + pe = oppo(spintet); + if ((pd != dummypoint) && (pe != dummypoint)) { + // Check if [d,e] intersects [a,b,c] + intflag = tri_edge_test(pa, pb, pc, pd, pe, NULL, 1, types, poss); + if (intflag > 0) { + // By our assumptions, they can only intersect at a single point. + if (intflag == 2) { + // Check the intersection type. + dir = (enum interresult) types[0]; + if ((dir == ACROSSFACE) || (dir == ACROSSEDGE)) { + // Go to the edge [d,e]. + edestoppo(spintet, flipedge); // [d,e,a,b] + if (searchsh != NULL) { + // Check if [e,d] is a segment. + if (issubseg(flipedge)) { + if (!b->quiet) { + face checkseg; + tsspivot1(flipedge, checkseg); + printf("Found a segment and a subface intersect.\n"); + pd = farsorg(checkseg); + pe = farsdest(checkseg); + printf(" 1st: [%d, %d] %d.\n", pointmark(pd), + pointmark(pe), shellmark(checkseg)); + printf(" 2nd: [%d,%d,%d] %d\n", pointmark(pa), + pointmark(pb), pointmark(pc), shellmark(*searchsh)); + } + terminatetetgen(this, 3); + } + } + // Try to flip the edge [d,e]. + success1 = (removeedgebyflips(&flipedge, &fc) == 2); + } else { + if (dir == TOUCHFACE) { + point touchpt, *parypt; + if (poss[1] == 0) { + touchpt = pd; // pd is a coplanar vertex. + } else { + touchpt = pe; // pe is a coplanar vertex. + } + if (pointtype(touchpt) == FREEVOLVERTEX) { + // A volume Steiner point was added in this subface. + // Split this subface by this point. + face checksh, *parysh; + int siloc = (int) ONFACE; + int sbowat = 0; // Only split this subface. + setpointtype(touchpt, FREEFACETVERTEX); + sinsertvertex(touchpt, searchsh, NULL, siloc, sbowat, 0); + st_volref_count--; + st_facref_count++; + // Queue this vertex for removal. + subvertstack->newindex((void **) &parypt); + *parypt = touchpt; + // Queue new subfaces for recovery. + // Put all new subfaces into stack for recovery. + for (i = 0; i < caveshbdlist->objects; i++) { + // Get an old subface at edge [a, b]. + parysh = (face *) fastlookup(caveshbdlist, i); + spivot(*parysh, checksh); // The new subface [a, b, p]. + // Do not recover a deleted new face (degenerated). + if (checksh.sh[3] != NULL) { + subfacstack->newindex((void **) &parysh); + *parysh = checksh; + } + } + // Delete the old subfaces in sC(p). + assert(caveshlist->objects == 1); + for (i = 0; i < caveshlist->objects; i++) { + parysh = (face *) fastlookup(caveshlist, i); + shellfacedealloc(subfaces, parysh->sh); + } + // Clear working lists. + caveshlist->restart(); + caveshbdlist->restart(); + cavesegshlist->restart(); + // We can return this function. + searchsh->sh = NULL; // It has been split. + success1 = 0; + success = 1; + } else { + // It should be a PLC problem. + if (pointtype(touchpt) == FREESEGVERTEX) { + // A segment and a subface intersect. + } else if (pointtype(touchpt) == FREEFACETVERTEX) { + // Two facets self-intersect. + } + terminatetetgen(this, 3); + } + } else { + assert(0); // Unknown cases. Debug. + } + } + break; + } else { // intflag == 4. Coplanar case. + // This may be an input PLC error. + assert(0); + } + } // if (intflag > 0) + } + fnextself(spintet); + assert(spintet.tet != searchtet->tet); + } // while (1) + if (!success1) break; + } // while (1) + } // i + + return success; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// recoversubfaces() Recover all subfaces. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::recoversubfaces(arraypool *misshlist, int steinerflag) +{ + triface searchtet, neightet, spintet; + face searchsh, neighsh, neineish, *parysh; + face bdsegs[3]; + point startpt, endpt, apexpt, *parypt; + point steinerpt; + enum interresult dir; + insertvertexflags ivf; + int success; + int t1ver; + int i, j; + + if (b->verbose > 1) { + printf(" Recover subfaces [%s level = %2d] #: %ld.\n", + (b->fliplinklevel > 0) ? "fixed" : "auto", + (b->fliplinklevel > 0) ? b->fliplinklevel : autofliplinklevel, + subfacstack->objects); + } + + // Loop until 'subfacstack' is empty. + while (subfacstack->objects > 0l) { + + subfacstack->objects--; + parysh = (face *) fastlookup(subfacstack, subfacstack->objects); + searchsh = *parysh; + + if (searchsh.sh[3] == NULL) continue; // Skip a dead subface. + + stpivot(searchsh, neightet); + if (neightet.tet != NULL) continue; // Skip a recovered subface. + + + if (b->verbose > 2) { + printf(" Recover subface (%d, %d, %d).\n",pointmark(sorg(searchsh)), + pointmark(sdest(searchsh)), pointmark(sapex(searchsh))); + } + + // The three edges of the face need to be existed first. + for (i = 0; i < 3; i++) { + sspivot(searchsh, bdsegs[i]); + if (bdsegs[i].sh != NULL) { + // The segment must exist. + sstpivot1(bdsegs[i], searchtet); + if (searchtet.tet == NULL) { + assert(0); + } + } else { + // This edge is not a segment (due to a Steiner point). + // Check whether it exists or not. + success = 0; + startpt = sorg(searchsh); + endpt = sdest(searchsh); + point2tetorg(startpt, searchtet); + dir = finddirection(&searchtet, endpt); + if (dir == ACROSSVERT) { + if (dest(searchtet) == endpt) { + success = 1; + } else { + //assert(0); // A PLC problem. + terminatetetgen(this, 3); + } + } else { + // The edge is missing. Try to recover it. + if (recoveredgebyflips(startpt, endpt, &searchtet, 0)) { + success = 1; + } else { + if (recoveredgebyflips(endpt, startpt, &searchtet, 0)) { + success = 1; + } + } + } + if (success) { + // Insert a temporary segment to protect this edge. + makeshellface(subsegs, &(bdsegs[i])); + setshvertices(bdsegs[i], startpt, endpt, NULL); + smarktest2(bdsegs[i]); // It's a temporary segment. + // Insert this segment into surface mesh. + ssbond(searchsh, bdsegs[i]); + spivot(searchsh, neighsh); + if (neighsh.sh != NULL) { + ssbond(neighsh, bdsegs[i]); + } + // Insert this segment into tetrahedralization. + sstbond1(bdsegs[i], searchtet); + // Bond the segment to all tets containing it. + spintet = searchtet; + do { + tssbond1(spintet, bdsegs[i]); + fnextself(spintet); + } while (spintet.tet != searchtet.tet); + } else { + // An edge of this subface is missing. Can't recover this subface. + // Delete any temporary segment that has been created. + for (j = (i - 1); j >= 0; j--) { + if (smarktest2ed(bdsegs[j])) { + spivot(bdsegs[j], neineish); + assert(neineish.sh != NULL); + //if (neineish.sh != NULL) { + ssdissolve(neineish); + spivot(neineish, neighsh); + if (neighsh.sh != NULL) { + ssdissolve(neighsh); + // There should be only two subfaces at this segment. + spivotself(neighsh); // SELF_CHECK + assert(neighsh.sh == neineish.sh); + } + //} + sstpivot1(bdsegs[j], searchtet); + assert(searchtet.tet != NULL); + //if (searchtet.tet != NULL) { + spintet = searchtet; + while (1) { + tssdissolve1(spintet); + fnextself(spintet); + if (spintet.tet == searchtet.tet) break; + } + //} + shellfacedealloc(subsegs, bdsegs[j].sh); + } + } // j + if (steinerflag) { + // Add a Steiner point at the midpoint of this edge. + if (b->verbose > 2) { + printf(" Add a Steiner point in subedge (%d, %d).\n", + pointmark(startpt), pointmark(endpt)); + } + makepoint(&steinerpt, FREEFACETVERTEX); + for (j = 0; j < 3; j++) { + steinerpt[j] = 0.5 * (startpt[j] + endpt[j]); + } + + point2tetorg(startpt, searchtet); // Start from 'searchtet'. + ivf.iloc = (int) OUTSIDE; // Need point location. + ivf.bowywat = 1; + ivf.lawson = 0; + ivf.rejflag = 0; + ivf.chkencflag = 0; + ivf.sloc = (int) ONEDGE; + ivf.sbowywat = 1; // Allow flips in facet. + ivf.splitbdflag = 0; + ivf.validflag = 1; + ivf.respectbdflag = 1; + ivf.assignmeshsize = b->metric; + if (!insertpoint(steinerpt, &searchtet, &searchsh, NULL, &ivf)) { + assert(0); + } + // Save this Steiner point (for removal). + // Re-use the array 'subvertstack'. + subvertstack->newindex((void **) &parypt); + *parypt = steinerpt; + + st_facref_count++; + if (steinerleft > 0) steinerleft--; + } // if (steinerflag) + break; + } + } + senextself(searchsh); + } // i + + if (i == 3) { + // Recover the subface. + startpt = sorg(searchsh); + endpt = sdest(searchsh); + apexpt = sapex(searchsh); + + success = recoverfacebyflips(startpt,endpt,apexpt,&searchsh,&searchtet); + + // Delete any temporary segment that has been created. + for (j = 0; j < 3; j++) { + if (smarktest2ed(bdsegs[j])) { + spivot(bdsegs[j], neineish); + assert(neineish.sh != NULL); + //if (neineish.sh != NULL) { + ssdissolve(neineish); + spivot(neineish, neighsh); + if (neighsh.sh != NULL) { + ssdissolve(neighsh); + // There should be only two subfaces at this segment. + spivotself(neighsh); // SELF_CHECK + assert(neighsh.sh == neineish.sh); + } + //} + sstpivot1(bdsegs[j], neightet); + assert(neightet.tet != NULL); + //if (neightet.tet != NULL) { + spintet = neightet; + while (1) { + tssdissolve1(spintet); + fnextself(spintet); + if (spintet.tet == neightet.tet) break; + } + //} + shellfacedealloc(subsegs, bdsegs[j].sh); + } + } // j + + if (success) { + if (searchsh.sh != NULL) { + // Face is recovered. Insert it. + tsbond(searchtet, searchsh); + fsymself(searchtet); + sesymself(searchsh); + tsbond(searchtet, searchsh); + } + } else { + if (steinerflag) { + // Add a Steiner point at the barycenter of this subface. + if (b->verbose > 2) { + printf(" Add a Steiner point in subface (%d, %d, %d).\n", + pointmark(startpt), pointmark(endpt), pointmark(apexpt)); + } + makepoint(&steinerpt, FREEFACETVERTEX); + for (j = 0; j < 3; j++) { + steinerpt[j] = (startpt[j] + endpt[j] + apexpt[j]) / 3.0; + } + + point2tetorg(startpt, searchtet); // Start from 'searchtet'. + ivf.iloc = (int) OUTSIDE; // Need point location. + ivf.bowywat = 1; + ivf.lawson = 0; + ivf.rejflag = 0; + ivf.chkencflag = 0; + ivf.sloc = (int) ONFACE; + ivf.sbowywat = 1; // Allow flips in facet. + ivf.splitbdflag = 0; + ivf.validflag = 1; + ivf.respectbdflag = 1; + ivf.assignmeshsize = b->metric; + if (!insertpoint(steinerpt, &searchtet, &searchsh, NULL, &ivf)) { + assert(0); + } + // Save this Steiner point (for removal). + // Re-use the array 'subvertstack'. + subvertstack->newindex((void **) &parypt); + *parypt = steinerpt; + + st_facref_count++; + if (steinerleft > 0) steinerleft--; + } // if (steinerflag) + } + } else { + success = 0; + } + + if (!success) { + if (misshlist != NULL) { + // Save this subface. + misshlist->newindex((void **) &parysh); + *parysh = searchsh; + } + } + + } // while (subfacstack->objects > 0l) + + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// getvertexstar() Return the star of a vertex. // +// // +// If the flag 'fullstar' is set, return the complete star of this vertex. // +// Otherwise, only a part of the star which is bounded by facets is returned.// +// // +// 'tetlist' returns the list of tets in the star of the vertex 'searchpt'. // +// Every tet in 'tetlist' is at the face opposing to 'searchpt'. // +// // +// 'vertlist' returns the list of vertices in the star (exclude 'searchpt'). // +// // +// 'shlist' returns the list of subfaces in the star. Each subface must face // +// to the interior of this star. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::getvertexstar(int fullstar, point searchpt, arraypool* tetlist, + arraypool* vertlist, arraypool* shlist) +{ + triface searchtet, neightet, *parytet; + face checksh, *parysh; + point pt, *parypt; + int collectflag; + int t1ver; + int i, j; + + point2tetorg(searchpt, searchtet); + + // Go to the opposite face (the link face) of the vertex. + enextesymself(searchtet); + //assert(oppo(searchtet) == searchpt); + infect(searchtet); // Collect this tet (link face). + tetlist->newindex((void **) &parytet); + *parytet = searchtet; + if (vertlist != NULL) { + // Collect three (link) vertices. + j = (searchtet.ver & 3); // The current vertex index. + for (i = 1; i < 4; i++) { + pt = (point) searchtet.tet[4 + ((j + i) % 4)]; + pinfect(pt); + vertlist->newindex((void **) &parypt); + *parypt = pt; + } + } + + collectflag = 1; + esym(searchtet, neightet); + if (issubface(neightet)) { + if (shlist != NULL) { + tspivot(neightet, checksh); + if (!sinfected(checksh)) { + // Collect this subface (link edge). + sinfected(checksh); + shlist->newindex((void **) &parysh); + *parysh = checksh; + } + } + if (!fullstar) { + collectflag = 0; + } + } + if (collectflag) { + fsymself(neightet); // Goto the adj tet of this face. + esymself(neightet); // Goto the oppo face of this vertex. + // assert(oppo(neightet) == searchpt); + infect(neightet); // Collect this tet (link face). + tetlist->newindex((void **) &parytet); + *parytet = neightet; + if (vertlist != NULL) { + // Collect its apex. + pt = apex(neightet); + pinfect(pt); + vertlist->newindex((void **) &parypt); + *parypt = pt; + } + } // if (collectflag) + + // Continue to collect all tets in the star. + for (i = 0; i < tetlist->objects; i++) { + searchtet = * (triface *) fastlookup(tetlist, i); + // Note that 'searchtet' is a face opposite to 'searchpt', and the neighbor + // tet at the current edge is already collected. + // Check the neighbors at the other two edges of this face. + for (j = 0; j < 2; j++) { + collectflag = 1; + enextself(searchtet); + esym(searchtet, neightet); + if (issubface(neightet)) { + if (shlist != NULL) { + tspivot(neightet, checksh); + if (!sinfected(checksh)) { + // Collect this subface (link edge). + sinfected(checksh); + shlist->newindex((void **) &parysh); + *parysh = checksh; + } + } + if (!fullstar) { + collectflag = 0; + } + } + if (collectflag) { + fsymself(neightet); + if (!infected(neightet)) { + esymself(neightet); // Go to the face opposite to 'searchpt'. + infect(neightet); + tetlist->newindex((void **) &parytet); + *parytet = neightet; + if (vertlist != NULL) { + // Check if a vertex is collected. + pt = apex(neightet); + if (!pinfected(pt)) { + pinfect(pt); + vertlist->newindex((void **) &parypt); + *parypt = pt; + } + } + } // if (!infected(neightet)) + } // if (collectflag) + } // j + } // i + + + // Uninfect the list of tets and vertices. + for (i = 0; i < tetlist->objects; i++) { + parytet = (triface *) fastlookup(tetlist, i); + uninfect(*parytet); + } + + if (vertlist != NULL) { + for (i = 0; i < vertlist->objects; i++) { + parypt = (point *) fastlookup(vertlist, i); + puninfect(*parypt); + } + } + + if (shlist != NULL) { + for (i = 0; i < shlist->objects; i++) { + parysh = (face *) fastlookup(shlist, i); + suninfect(*parysh); + } + } + + return (int) tetlist->objects; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// getedge() Get a tetrahedron having the two endpoints. // +// // +// The method here is to search the second vertex in the link faces of the // +// first vertex. The global array 'cavetetlist' is re-used for searching. // +// // +// This function is used for the case when the mesh is non-convex. Otherwise,// +// the function finddirection() should be faster than this. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::getedge(point e1, point e2, triface *tedge) +{ + triface searchtet, neightet, *parytet; + point pt; + int done; + int i, j; + + if (b->verbose > 2) { + printf(" Get edge from %d to %d.\n", pointmark(e1), pointmark(e2)); + } + + // Quickly check if 'tedge' is just this edge. + if (!isdeadtet(*tedge)) { + if (org(*tedge) == e1) { + if (dest(*tedge) == e2) { + return 1; + } + } else if (org(*tedge) == e2) { + if (dest(*tedge) == e1) { + esymself(*tedge); + return 1; + } + } + } + + // Search for the edge [e1, e2]. + point2tetorg(e1, *tedge); + finddirection(tedge, e2); + if (dest(*tedge) == e2) { + return 1; + } else { + // Search for the edge [e2, e1]. + point2tetorg(e2, *tedge); + finddirection(tedge, e1); + if (dest(*tedge) == e1) { + esymself(*tedge); + return 1; + } + } + + + // Go to the link face of e1. + point2tetorg(e1, searchtet); + enextesymself(searchtet); + //assert(oppo(searchtet) == e1); + + assert(cavebdrylist->objects == 0l); // It will re-use this list. + arraypool *tetlist = cavebdrylist; + + // Search e2. + for (i = 0; i < 3; i++) { + pt = apex(searchtet); + if (pt == e2) { + // Found. 'searchtet' is [#,#,e2,e1]. + eorgoppo(searchtet, *tedge); // [e1,e2,#,#]. + return 1; + } + enextself(searchtet); + } + + // Get the adjacent link face at 'searchtet'. + fnext(searchtet, neightet); + esymself(neightet); + // assert(oppo(neightet) == e1); + pt = apex(neightet); + if (pt == e2) { + // Found. 'neightet' is [#,#,e2,e1]. + eorgoppo(neightet, *tedge); // [e1,e2,#,#]. + return 1; + } + + // Continue searching in the link face of e1. + infect(searchtet); + tetlist->newindex((void **) &parytet); + *parytet = searchtet; + infect(neightet); + tetlist->newindex((void **) &parytet); + *parytet = neightet; + + done = 0; + + for (i = 0; (i < tetlist->objects) && !done; i++) { + parytet = (triface *) fastlookup(tetlist, i); + searchtet = *parytet; + for (j = 0; (j < 2) && !done; j++) { + enextself(searchtet); + fnext(searchtet, neightet); + if (!infected(neightet)) { + esymself(neightet); + pt = apex(neightet); + if (pt == e2) { + // Found. 'neightet' is [#,#,e2,e1]. + eorgoppo(neightet, *tedge); + done = 1; + } else { + infect(neightet); + tetlist->newindex((void **) &parytet); + *parytet = neightet; + } + } + } // j + } // i + + // Uninfect the list of visited tets. + for (i = 0; i < tetlist->objects; i++) { + parytet = (triface *) fastlookup(tetlist, i); + uninfect(*parytet); + } + tetlist->restart(); + + return done; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// reduceedgesatvertex() Reduce the number of edges at a given vertex. // +// // +// 'endptlist' contains the endpoints of edges connecting at the vertex. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::reduceedgesatvertex(point startpt, arraypool* endptlist) +{ + triface searchtet; + point *pendpt, *parypt; + enum interresult dir; + flipconstraints fc; + int reduceflag; + int count; + int n, i, j; + + + fc.remvert = startpt; + fc.checkflipeligibility = 1; + + while (1) { + + count = 0; + + for (i = 0; i < endptlist->objects; i++) { + pendpt = (point *) fastlookup(endptlist, i); + if (*pendpt == dummypoint) { + continue; // Do not reduce a virtual edge. + } + reduceflag = 0; + // Find the edge. + if (nonconvex) { + if (getedge(startpt, *pendpt, &searchtet)) { + dir = ACROSSVERT; + } else { + // The edge does not exist (was flipped). + dir = INTERSECT; + } + } else { + point2tetorg(startpt, searchtet); + dir = finddirection(&searchtet, *pendpt); + } + if (dir == ACROSSVERT) { + if (dest(searchtet) == *pendpt) { + // Do not flip a segment. + if (!issubseg(searchtet)) { + n = removeedgebyflips(&searchtet, &fc); + if (n == 2) { + reduceflag = 1; + } + } + } else { + assert(0); // A plc problem. + } + } else { + // The edge has been flipped. + reduceflag = 1; + } + if (reduceflag) { + count++; + // Move the last vertex into this slot. + j = endptlist->objects - 1; + parypt = (point *) fastlookup(endptlist, j); + *pendpt = *parypt; + endptlist->objects--; + i--; + } + } // i + + if (count == 0) { + // No edge is reduced. + break; + } + + } // while (1) + + return (int) endptlist->objects; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// removevertexbyflips() Remove a vertex by flips. // +// // +// This routine attempts to remove the given vertex 'rempt' (p) from the // +// tetrahedralization (T) by a sequence of flips. // +// // +// The algorithm used here is a simple edge reduce method. Suppose there are // +// n edges connected at p. We try to reduce the number of edges by flipping // +// any edge (not a segment) that is connecting at p. // +// // +// Unless T is a Delaunay tetrahedralization, there is no guarantee that 'p' // +// can be successfully removed. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::removevertexbyflips(point steinerpt) +{ + triface *fliptets = NULL, wrktets[4]; + triface searchtet, spintet, neightet; + face parentsh, spinsh, checksh; + face leftseg, rightseg, checkseg; + point lpt = NULL, rpt = NULL, apexpt; //, *parypt; + flipconstraints fc; + enum verttype vt; + enum locateresult loc; + int valence, removeflag; + int slawson; + int t1ver; + int n, i; + + vt = pointtype(steinerpt); + + if (vt == FREESEGVERTEX) { + sdecode(point2sh(steinerpt), leftseg); + assert(leftseg.sh != NULL); + leftseg.shver = 0; + if (sdest(leftseg) == steinerpt) { + senext(leftseg, rightseg); + spivotself(rightseg); + assert(rightseg.sh != NULL); + rightseg.shver = 0; + assert(sorg(rightseg) == steinerpt); + } else { + assert(sorg(leftseg) == steinerpt); + rightseg = leftseg; + senext2(rightseg, leftseg); + spivotself(leftseg); + assert(leftseg.sh != NULL); + leftseg.shver = 0; + assert(sdest(leftseg) == steinerpt); + } + lpt = sorg(leftseg); + rpt = sdest(rightseg); + if (b->verbose > 2) { + printf(" Removing Steiner point %d in segment (%d, %d).\n", + pointmark(steinerpt), pointmark(lpt), pointmark(rpt)); + + } + } else if (vt == FREEFACETVERTEX) { + if (b->verbose > 2) { + printf(" Removing Steiner point %d in facet.\n", + pointmark(steinerpt)); + } + } else if (vt == FREEVOLVERTEX) { + if (b->verbose > 2) { + printf(" Removing Steiner point %d in volume.\n", + pointmark(steinerpt)); + } + } else if (vt == VOLVERTEX) { + if (b->verbose > 2) { + printf(" Removing a point %d in volume.\n", + pointmark(steinerpt)); + } + } else { + // It is not a Steiner point. + return 0; + } + + // Try to reduce the number of edges at 'p' by flips. + getvertexstar(1, steinerpt, cavetetlist, cavetetvertlist, NULL); + cavetetlist->restart(); // This list may be re-used. + if (cavetetvertlist->objects > 3l) { + valence = reduceedgesatvertex(steinerpt, cavetetvertlist); + } else { + valence = cavetetvertlist->objects; + } + assert(cavetetlist->objects == 0l); + cavetetvertlist->restart(); + + removeflag = 0; + + if (valence == 4) { + // Only 4 vertices (4 tets) left! 'p' is inside the convex hull of the 4 + // vertices. This case is due to that 'p' is not exactly on the segment. + point2tetorg(steinerpt, searchtet); + loc = INTETRAHEDRON; + removeflag = 1; + } else if (valence == 5) { + // There are 5 edges. + if (vt == FREESEGVERTEX) { + sstpivot1(leftseg, searchtet); + if (org(searchtet) != steinerpt) { + esymself(searchtet); + } + assert(org(searchtet) == steinerpt); + assert(dest(searchtet) == lpt); + i = 0; // Count the numbe of tet at the edge [p,lpt]. + neightet.tet = NULL; // Init the face. + spintet = searchtet; + while (1) { + i++; + if (apex(spintet) == rpt) { + // Remember the face containing the edge [lpt, rpt]. + neightet = spintet; + } + fnextself(spintet); + if (spintet.tet == searchtet.tet) break; + } + if (i == 3) { + // This case has been checked below. + } else if (i == 4) { + // There are 4 tets sharing at [p,lpt]. There must be 4 tets sharing + // at [p,rpt]. There must be a face [p, lpt, rpt]. + if (apex(neightet) == rpt) { + // The edge (segment) has been already recovered! + // Check if a 6-to-2 flip is possible (to remove 'p'). + // Let 'searchtet' be [p,d,a,b] + esym(neightet, searchtet); + enextself(searchtet); + // Check if there are exactly three tets at edge [p,d]. + wrktets[0] = searchtet; // [p,d,a,b] + for (i = 0; i < 2; i++) { + fnext(wrktets[i], wrktets[i+1]); // [p,d,b,c], [p,d,c,a] + } + if (apex(wrktets[0]) == oppo(wrktets[2])) { + loc = ONFACE; + removeflag = 1; + } + } + } + } else if (vt == FREEFACETVERTEX) { + // It is possible to do a 6-to-2 flip to remove the vertex. + point2tetorg(steinerpt, searchtet); + // Get the three faces of 'searchtet' which share at p. + // All faces has p as origin. + wrktets[0] = searchtet; + wrktets[1] = searchtet; + esymself(wrktets[1]); + enextself(wrktets[1]); + wrktets[2] = searchtet; + eprevself(wrktets[2]); + esymself(wrktets[2]); + // All internal edges of the six tets have valance either 3 or 4. + // Get one edge which has valance 3. + searchtet.tet = NULL; + for (i = 0; i < 3; i++) { + spintet = wrktets[i]; + valence = 0; + while (1) { + valence++; + fnextself(spintet); + if (spintet.tet == wrktets[i].tet) break; + } + if (valence == 3) { + // Found the edge. + searchtet = wrktets[i]; + break; + } else { + assert(valence == 4); + } + } + assert(searchtet.tet != NULL); + // Note, we do not detach the three subfaces at p. + // They will be removed within a 4-to-1 flip. + loc = ONFACE; + removeflag = 1; + } else { + // assert(0); DEBUG IT + } + //removeflag = 1; + } + + if (!removeflag) { + if (vt == FREESEGVERTEX) { + // Check is it possible to recover the edge [lpt,rpt]. + // The condition to check is: Whether each tet containing 'leftseg' is + // adjacent to a tet containing 'rightseg'. + sstpivot1(leftseg, searchtet); + if (org(searchtet) != steinerpt) { + esymself(searchtet); + } + assert(org(searchtet) == steinerpt); + assert(dest(searchtet) == lpt); + spintet = searchtet; + while (1) { + // Go to the bottom face of this tet. + eprev(spintet, neightet); + esymself(neightet); // [steinerpt, p1, p2, lpt] + // Get the adjacent tet. + fsymself(neightet); // [p1, steinerpt, p2, rpt] + if (oppo(neightet) != rpt) { + // Found a non-matching adjacent tet. + break; + } + fnextself(spintet); + if (spintet.tet == searchtet.tet) { + // 'searchtet' is [p,d,p1,p2]. + loc = ONEDGE; + removeflag = 1; + break; + } + } + } // if (vt == FREESEGVERTEX) + } + + if (!removeflag) { + if (vt == FREESEGVERTEX) { + // Check if the edge [lpt, rpt] exists. + if (getedge(lpt, rpt, &searchtet)) { + // We have recovered this edge. Shift the vertex into the volume. + // We can recover this edge if the subfaces are not recovered yet. + if (!checksubfaceflag) { + // Remove the vertex from the surface mesh. + // This will re-create the segment [lpt, rpt] and re-triangulate + // all the facets at the segment. + // Detach the subsegments from their surrounding tets. + for (i = 0; i < 2; i++) { + checkseg = (i == 0) ? leftseg : rightseg; + sstpivot1(checkseg, neightet); + spintet = neightet; + while (1) { + tssdissolve1(spintet); + fnextself(spintet); + if (spintet.tet == neightet.tet) break; + } + sstdissolve1(checkseg); + } // i + slawson = 1; // Do lawson flip after removal. + spivot(rightseg, parentsh); // 'rightseg' has p as its origin. + sremovevertex(steinerpt, &parentsh, &rightseg, slawson); + // Clear the list for new subfaces. + caveshbdlist->restart(); + // Insert the new segment. + assert(org(searchtet) == lpt); + assert(dest(searchtet) == rpt); + sstbond1(rightseg, searchtet); + spintet = searchtet; + while (1) { + tsspivot1(spintet, checkseg); // FOR DEBUG ONLY + assert(checkseg.sh == NULL); // FOR DEBUG ONLY + tssbond1(spintet, rightseg); + fnextself(spintet); + if (spintet.tet == searchtet.tet) break; + } + // The Steiner point has been shifted into the volume. + setpointtype(steinerpt, FREEVOLVERTEX); + st_segref_count--; + st_volref_count++; + return 1; + } // if (!checksubfaceflag) + } // if (getedge(...)) + } // if (vt == FREESEGVERTEX) + } // if (!removeflag) + + if (!removeflag) { + return 0; + } + + assert(org(searchtet) == steinerpt); + + if (vt == FREESEGVERTEX) { + // Detach the subsegments from their surronding tets. + for (i = 0; i < 2; i++) { + checkseg = (i == 0) ? leftseg : rightseg; + sstpivot1(checkseg, neightet); + spintet = neightet; + while (1) { + tssdissolve1(spintet); + fnextself(spintet); + if (spintet.tet == neightet.tet) break; + } + sstdissolve1(checkseg); + } // i + if (checksubfaceflag) { + // Detach the subfaces at the subsegments from their attached tets. + for (i = 0; i < 2; i++) { + checkseg = (i == 0) ? leftseg : rightseg; + spivot(checkseg, parentsh); + if (parentsh.sh != NULL) { + spinsh = parentsh; + while (1) { + stpivot(spinsh, neightet); + if (neightet.tet != NULL) { + tsdissolve(neightet); + } + sesymself(spinsh); + stpivot(spinsh, neightet); + if (neightet.tet != NULL) { + tsdissolve(neightet); + } + stdissolve(spinsh); + spivotself(spinsh); // Go to the next subface. + if (spinsh.sh == parentsh.sh) break; + } + } + } // i + } // if (checksubfaceflag) + } + + if (loc == INTETRAHEDRON) { + // Collect the four tets containing 'p'. + fliptets = new triface[4]; + fliptets[0] = searchtet; // [p,d,a,b] + for (i = 0; i < 2; i++) { + fnext(fliptets[i], fliptets[i+1]); // [p,d,b,c], [p,d,c,a] + } + eprev(fliptets[0], fliptets[3]); + fnextself(fliptets[3]); // it is [a,p,b,c] + eprevself(fliptets[3]); + esymself(fliptets[3]); // [a,b,c,p]. + // Remove p by a 4-to-1 flip. + //flip41(fliptets, 1, 0, 0); + flip41(fliptets, 1, &fc); + //recenttet = fliptets[0]; + } else if (loc == ONFACE) { + // Let the original two tets be [a,b,c,d] and [b,a,c,e]. And p is in + // face [a,b,c]. Let 'searchtet' be the tet [p,d,a,b]. + // Collect the six tets containing 'p'. + fliptets = new triface[6]; + fliptets[0] = searchtet; // [p,d,a,b] + for (i = 0; i < 2; i++) { + fnext(fliptets[i], fliptets[i+1]); // [p,d,b,c], [p,d,c,a] + } + eprev(fliptets[0], fliptets[3]); + fnextself(fliptets[3]); // [a,p,b,e] + esymself(fliptets[3]); // [p,a,e,b] + eprevself(fliptets[3]); // [e,p,a,b] + for (i = 3; i < 5; i++) { + fnext(fliptets[i], fliptets[i+1]); // [e,p,b,c], [e,p,c,a] + } + if (vt == FREEFACETVERTEX) { + // We need to determine the location of three subfaces at p. + valence = 0; // Re-use it. + // Check if subfaces are all located in the lower three tets. + // i.e., [e,p,a,b], [e,p,b,c], and [e,p,c,a]. + for (i = 3; i < 6; i++) { + if (issubface(fliptets[i])) valence++; + } + if (valence > 0) { + assert(valence == 2); + // We must do 3-to-2 flip in the upper part. We simply re-arrange + // the six tets. + for (i = 0; i < 3; i++) { + esym(fliptets[i+3], wrktets[i]); + esym(fliptets[i], fliptets[i+3]); + fliptets[i] = wrktets[i]; + } + // Swap the last two pairs, i.e., [1]<->[[2], and [4]<->[5] + wrktets[1] = fliptets[1]; + fliptets[1] = fliptets[2]; + fliptets[2] = wrktets[1]; + wrktets[1] = fliptets[4]; + fliptets[4] = fliptets[5]; + fliptets[5] = wrktets[1]; + } + } + // Remove p by a 6-to-2 flip, which is a combination of two flips: + // a 3-to-2 (deletes the edge [e,p]), and + // a 4-to-1 (deletes the vertex p). + // First do a 3-to-2 flip on [e,p,a,b],[e,p,b,c],[e,p,c,a]. It creates + // two new tets: [a,b,c,p] and [b,a,c,e]. The new tet [a,b,c,p] is + // degenerate (has zero volume). It will be deleted in the followed + // 4-to-1 flip. + //flip32(&(fliptets[3]), 1, 0, 0); + flip32(&(fliptets[3]), 1, &fc); + // Second do a 4-to-1 flip on [p,d,a,b],[p,d,b,c],[p,d,c,a],[a,b,c,p]. + // This creates a new tet [a,b,c,d]. + //flip41(fliptets, 1, 0, 0); + flip41(fliptets, 1, &fc); + //recenttet = fliptets[0]; + } else if (loc == ONEDGE) { + // Let the original edge be [e,d] and p is in [e,d]. Assume there are n + // tets sharing at edge [e,d] originally. We number the link vertices + // of [e,d]: p_0, p_1, ..., p_n-1. 'searchtet' is [p,d,p_0,p_1]. + // Count the number of tets at edge [e,p] and [p,d] (this is n). + n = 0; + spintet = searchtet; + while (1) { + n++; + fnextself(spintet); + if (spintet.tet == searchtet.tet) break; + } + assert(n >= 3); + // Collect the 2n tets containing 'p'. + fliptets = new triface[2 * n]; + fliptets[0] = searchtet; // [p,b,p_0,p_1] + for (i = 0; i < (n - 1); i++) { + fnext(fliptets[i], fliptets[i+1]); // [p,d,p_i,p_i+1]. + } + eprev(fliptets[0], fliptets[n]); + fnextself(fliptets[n]); // [p_0,p,p_1,e] + esymself(fliptets[n]); // [p,p_0,e,p_1] + eprevself(fliptets[n]); // [e,p,p_0,p_1] + for (i = n; i < (2 * n - 1); i++) { + fnext(fliptets[i], fliptets[i+1]); // [e,p,p_i,p_i+1]. + } + // Remove p by a 2n-to-n flip, it is a sequence of n flips: + // - Do a 2-to-3 flip on + // [p_0,p_1,p,d] and + // [p,p_1,p_0,e]. + // This produces: + // [e,d,p_0,p_1], + // [e,d,p_1,p] (degenerated), and + // [e,d,p,p_0] (degenerated). + wrktets[0] = fliptets[0]; // [p,d,p_0,p_1] + eprevself(wrktets[0]); // [p_0,p,d,p_1] + esymself(wrktets[0]); // [p,p_0,p_1,d] + enextself(wrktets[0]); // [p_0,p_1,p,d] [0] + wrktets[1] = fliptets[n]; // [e,p,p_0,p_1] + enextself(wrktets[1]); // [p,p_0,e,p_1] + esymself(wrktets[1]); // [p_0,p,p_1,e] + eprevself(wrktets[1]); // [p_1,p_0,p,e] [1] + //flip23(wrktets, 1, 0, 0); + flip23(wrktets, 1, &fc); + // Save the new tet [e,d,p,p_0] (degenerated). + fliptets[n] = wrktets[2]; + // Save the new tet [e,d,p_0,p_1]. + fliptets[0] = wrktets[0]; + // - Repeat from i = 1 to n-2: (n - 2) flips + // - Do a 3-to-2 flip on + // [p,p_i,d,e], + // [p,p_i,e,p_i+1], and + // [p,p_i,p_i+1,d]. + // This produces: + // [d,e,p_i+1,p_i], and + // [e,d,p_i+1,p] (degenerated). + for (i = 1; i < (n - 1); i++) { + wrktets[0] = wrktets[1]; // [e,d,p_i,p] (degenerated). + enextself(wrktets[0]); // [d,p_i,e,p] (...) + esymself(wrktets[0]); // [p_i,d,p,e] (...) + eprevself(wrktets[0]); // [p,p_i,d,e] (degenerated) [0]. + wrktets[1] = fliptets[n+i]; // [e,p,p_i,p_i+1] + enextself(wrktets[1]); // [p,p_i,e,p_i+1] [1] + wrktets[2] = fliptets[i]; // [p,d,p_i,p_i+1] + eprevself(wrktets[2]); // [p_i,p,d,p_i+1] + esymself(wrktets[2]); // [p,p_i,p_i+1,d] [2] + //flip32(wrktets, 1, 0, 0); + flip32(wrktets, 1, &fc); + // Save the new tet [e,d,p_i,p_i+1]. // FOR DEBUG ONLY + fliptets[i] = wrktets[0]; // [d,e,p_i+1,p_i] // FOR DEBUG ONLY + esymself(fliptets[i]); // [e,d,p_i,p_i+1] // FOR DEBUG ONLY + } + // - Do a 4-to-1 flip on + // [p,p_0,e,d], [d,e,p_0,p], + // [p,p_0,d,p_n-1], [e,p_n-1,p_0,p], + // [p,p_0,p_n-1,e], [p_0,p_n-1,d,p], and + // [e,d,p_n-1,p]. + // This produces + // [e,d,p_n-1,p_0] and + // deletes p. + wrktets[3] = wrktets[1]; // [e,d,p_n-1,p] (degenerated) [3] + wrktets[0] = fliptets[n]; // [e,d,p,p_0] (degenerated) + eprevself(wrktets[0]); // [p,e,d,p_0] (...) + esymself(wrktets[0]); // [e,p,p_0,d] (...) + enextself(wrktets[0]); // [p,p_0,e,d] (degenerated) [0] + wrktets[1] = fliptets[n-1]; // [p,d,p_n-1,p_0] + esymself(wrktets[1]); // [d,p,p_0,p_n-1] + enextself(wrktets[1]); // [p,p_0,d,p_n-1] [1] + wrktets[2] = fliptets[2*n-1]; // [e,p,p_n-1,p_0] + enextself(wrktets[2]); // [p_p_n-1,e,p_0] + esymself(wrktets[2]); // [p_n-1,p,p_0,e] + enextself(wrktets[2]); // [p,p_0,p_n-1,e] [2] + //flip41(wrktets, 1, 0, 0); + flip41(wrktets, 1, &fc); + // Save the new tet [e,d,p_n-1,p_0] // FOR DEBUG ONLY + fliptets[n-1] = wrktets[0]; // [e,d,p_n-1,p_0] // FOR DEBUG ONLY + //recenttet = fliptets[0]; + } else { + assert(0); // Unknown location. + } // if (iloc == ...) + + delete [] fliptets; + + if (vt == FREESEGVERTEX) { + // Remove the vertex from the surface mesh. + // This will re-create the segment [lpt, rpt] and re-triangulate + // all the facets at the segment. + // Only do lawson flip when subfaces are not recovery yet. + slawson = (checksubfaceflag ? 0 : 1); + spivot(rightseg, parentsh); // 'rightseg' has p as its origin. + sremovevertex(steinerpt, &parentsh, &rightseg, slawson); + + // The original segment is returned in 'rightseg'. + rightseg.shver = 0; + assert(sorg(rightseg) == lpt); + assert(sdest(rightseg) == rpt); + + // Insert the new segment. + point2tetorg(lpt, searchtet); + finddirection(&searchtet, rpt); + assert(dest(searchtet) == rpt); + sstbond1(rightseg, searchtet); + spintet = searchtet; + while (1) { + tsspivot1(spintet, checkseg); // FOR DEBUG ONLY + assert(checkseg.sh == NULL); // FOR DEBUG ONLY + tssbond1(spintet, rightseg); + fnextself(spintet); + if (spintet.tet == searchtet.tet) break; + } + + if (checksubfaceflag) { + // Insert subfaces at segment [lpt,rpt] into the tetrahedralization. + spivot(rightseg, parentsh); + if (parentsh.sh != NULL) { + spinsh = parentsh; + while (1) { + if (sorg(spinsh) != lpt) { + sesymself(spinsh); + assert(sorg(spinsh) == lpt); + } + assert(sdest(spinsh) == rpt); + apexpt = sapex(spinsh); + // Find the adjacent tet of [lpt,rpt,apexpt]; + spintet = searchtet; + while (1) { + if (apex(spintet) == apexpt) { + tsbond(spintet, spinsh); + sesymself(spinsh); // Get to another side of this face. + fsym(spintet, neightet); + tsbond(neightet, spinsh); + sesymself(spinsh); // Get back to the original side. + break; + } + fnextself(spintet); + assert(spintet.tet != searchtet.tet); + //if (spintet.tet == searchtet.tet) break; + } + spivotself(spinsh); + if (spinsh.sh == parentsh.sh) break; + } + } + } // if (checksubfaceflag) + + // Clear the set of new subfaces. + caveshbdlist->restart(); + } // if (vt == FREESEGVERTEX) + + // The point has been removed. + if (pointtype(steinerpt) != UNUSEDVERTEX) { + setpointtype(steinerpt, UNUSEDVERTEX); + unuverts++; + } + if (vt != VOLVERTEX) { + // Update the correspinding counters. + if (vt == FREESEGVERTEX) { + st_segref_count--; + } else if (vt == FREEFACETVERTEX) { + st_facref_count--; + } else if (vt == FREEVOLVERTEX) { + st_volref_count--; + } + if (steinerleft > 0) steinerleft++; + } + + return 1; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// suppressbdrysteinerpoint() Suppress a boundary Steiner point // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::suppressbdrysteinerpoint(point steinerpt) +{ + face parentsh, spinsh, *parysh; + face leftseg, rightseg; + point lpt = NULL, rpt = NULL; + int i; + + verttype vt = pointtype(steinerpt); + + if (vt == FREESEGVERTEX) { + sdecode(point2sh(steinerpt), leftseg); + leftseg.shver = 0; + if (sdest(leftseg) == steinerpt) { + senext(leftseg, rightseg); + spivotself(rightseg); + assert(rightseg.sh != NULL); + rightseg.shver = 0; + assert(sorg(rightseg) == steinerpt); + } else { + assert(sorg(leftseg) == steinerpt); + rightseg = leftseg; + senext2(rightseg, leftseg); + spivotself(leftseg); + assert(leftseg.sh != NULL); + leftseg.shver = 0; + assert(sdest(leftseg) == steinerpt); + } + lpt = sorg(leftseg); + rpt = sdest(rightseg); + if (b->verbose > 2) { + printf(" Suppressing Steiner point %d in segment (%d, %d).\n", + pointmark(steinerpt), pointmark(lpt), pointmark(rpt)); + } + // Get all subfaces at the left segment [lpt, steinerpt]. + spivot(leftseg, parentsh); + spinsh = parentsh; + while (1) { + cavesegshlist->newindex((void **) &parysh); + *parysh = spinsh; + // Orient the face consistently. + if (sorg(*parysh)!= sorg(parentsh)) sesymself(*parysh); + spivotself(spinsh); + if (spinsh.sh == NULL) break; + if (spinsh.sh == parentsh.sh) break; + } + if (cavesegshlist->objects < 2) { + // It is a single segment. Not handle it yet. + cavesegshlist->restart(); + return 0; + } + } else if (vt == FREEFACETVERTEX) { + if (b->verbose > 2) { + printf(" Suppressing Steiner point %d from facet.\n", + pointmark(steinerpt)); + } + sdecode(point2sh(steinerpt), parentsh); + // A facet Steiner point. There are exactly two sectors. + for (i = 0; i < 2; i++) { + cavesegshlist->newindex((void **) &parysh); + *parysh = parentsh; + sesymself(parentsh); + } + } else { + return 0; + } + + triface searchtet, neightet, *parytet; + point pa, pb, pc, pd; + REAL v1[3], v2[3], len, u; + + REAL startpt[3] = {0,}, samplept[3] = {0,}, candpt[3] = {0,}; + REAL ori, minvol, smallvol; + int samplesize; + int it, j, k; + + int n = (int) cavesegshlist->objects; + point *newsteiners = new point[n]; + for (i = 0; i < n; i++) newsteiners[i] = NULL; + + // Search for each sector an interior vertex. + for (i = 0; i < cavesegshlist->objects; i++) { + parysh = (face *) fastlookup(cavesegshlist, i); + stpivot(*parysh, searchtet); + // Skip it if it is outside. + if (ishulltet(searchtet)) continue; + // Get the "half-ball". Tets in 'cavetetlist' all contain 'steinerpt' as + // opposite. Subfaces in 'caveshlist' all contain 'steinerpt' as apex. + // Moreover, subfaces are oriented towards the interior of the ball. + setpoint2tet(steinerpt, encode(searchtet)); + getvertexstar(0, steinerpt, cavetetlist, NULL, caveshlist); + // Calculate the searching vector. + pa = sorg(*parysh); + pb = sdest(*parysh); + pc = sapex(*parysh); + facenormal(pa, pb, pc, v1, 1, NULL); + len = sqrt(dot(v1, v1)); + assert(len > 0.0); + v1[0] /= len; + v1[1] /= len; + v1[2] /= len; + if (vt == FREESEGVERTEX) { + parysh = (face *) fastlookup(cavesegshlist, (i + 1) % n); + pd = sapex(*parysh); + facenormal(pb, pa, pd, v2, 1, NULL); + len = sqrt(dot(v2, v2)); + assert(len > 0.0); + v2[0] /= len; + v2[1] /= len; + v2[2] /= len; + // Average the two vectors. + v1[0] = 0.5 * (v1[0] + v2[0]); + v1[1] = 0.5 * (v1[1] + v2[1]); + v1[2] = 0.5 * (v1[2] + v2[2]); + } + // Search the intersection of the ray starting from 'steinerpt' to + // the search direction 'v1' and the shell of the half-ball. + // - Construct an endpoint. + len = distance(pa, pb); + v2[0] = steinerpt[0] + len * v1[0]; + v2[1] = steinerpt[1] + len * v1[1]; + v2[2] = steinerpt[2] + len * v1[2]; + for (j = 0; j < cavetetlist->objects; j++) { + parytet = (triface *) fastlookup(cavetetlist, j); + pa = org(*parytet); + pb = dest(*parytet); + pc = apex(*parytet); + // Test if the ray startpt->v2 lies in the cone: where 'steinerpt' + // is the apex, and three sides are defined by the triangle + // [pa, pb, pc]. + ori = orient3d(steinerpt, pa, pb, v2); + if (ori >= 0) { + ori = orient3d(steinerpt, pb, pc, v2); + if (ori >= 0) { + ori = orient3d(steinerpt, pc, pa, v2); + if (ori >= 0) { + // Found! Calculate the intersection. + planelineint(pa, pb, pc, steinerpt, v2, startpt, &u); + assert(u != 0.0); + break; + } + } + } + } // j + assert(j < cavetetlist->objects); // There must be an intersection. + // Close the ball by adding the subfaces. + for (j = 0; j < caveshlist->objects; j++) { + parysh = (face *) fastlookup(caveshlist, j); + stpivot(*parysh, neightet); + cavetetlist->newindex((void **) &parytet); + *parytet = neightet; + } + // Search a best point inside the segment [startpt, steinerpt]. + it = 0; + samplesize = 100; + v1[0] = steinerpt[0] - startpt[0]; + v1[1] = steinerpt[1] - startpt[1]; + v1[2] = steinerpt[2] - startpt[2]; + minvol = -1.0; + while (it < 3) { + for (j = 1; j < samplesize - 1; j++) { + samplept[0] = startpt[0] + ((REAL) j / (REAL) samplesize) * v1[0]; + samplept[1] = startpt[1] + ((REAL) j / (REAL) samplesize) * v1[1]; + samplept[2] = startpt[2] + ((REAL) j / (REAL) samplesize) * v1[2]; + // Find the minimum volume for 'samplept'. + smallvol = -1; + for (k = 0; k < cavetetlist->objects; k++) { + parytet = (triface *) fastlookup(cavetetlist, k); + pa = org(*parytet); + pb = dest(*parytet); + pc = apex(*parytet); + ori = orient3d(pb, pa, pc, samplept); + if (ori <= 0) { + break; // An invalid tet. + } + if (smallvol == -1) { + smallvol = ori; + } else { + if (ori < smallvol) smallvol = ori; + } + } // k + if (k == cavetetlist->objects) { + // Found a valid point. Remember it. + if (minvol == -1.0) { + candpt[0] = samplept[0]; + candpt[1] = samplept[1]; + candpt[2] = samplept[2]; + minvol = smallvol; + } else { + if (minvol < smallvol) { + // It is a better location. Remember it. + candpt[0] = samplept[0]; + candpt[1] = samplept[1]; + candpt[2] = samplept[2]; + minvol = smallvol; + } else { + // No improvement of smallest volume. + // Since we are searching along the line [startpt, steinerpy], + // The smallest volume can only be decreased later. + break; + } + } + } + } // j + if (minvol > 0) break; + samplesize *= 10; + it++; + } // while (it < 3) + if (minvol == -1.0) { + // Failed to find a valid point. + cavetetlist->restart(); + caveshlist->restart(); + break; + } + // Create a new Steiner point inside this section. + makepoint(&(newsteiners[i]), FREEVOLVERTEX); + newsteiners[i][0] = candpt[0]; + newsteiners[i][1] = candpt[1]; + newsteiners[i][2] = candpt[2]; + cavetetlist->restart(); + caveshlist->restart(); + } // i + + if (i < cavesegshlist->objects) { + // Failed to suppress the vertex. + for (; i > 0; i--) { + if (newsteiners[i - 1] != NULL) { + pointdealloc(newsteiners[i - 1]); + } + } + delete [] newsteiners; + cavesegshlist->restart(); + return 0; + } + + // Remove p from the segment or the facet. + triface newtet, newface, spintet; + face newsh, neighsh; + face *splitseg, checkseg; + int slawson = 0; // Do not do flip afterword. + int t1ver; + + if (vt == FREESEGVERTEX) { + // Detach 'leftseg' and 'rightseg' from their adjacent tets. + // These two subsegments will be deleted. + sstpivot1(leftseg, neightet); + spintet = neightet; + while (1) { + tssdissolve1(spintet); + fnextself(spintet); + if (spintet.tet == neightet.tet) break; + } + sstpivot1(rightseg, neightet); + spintet = neightet; + while (1) { + tssdissolve1(spintet); + fnextself(spintet); + if (spintet.tet == neightet.tet) break; + } + } + + // Loop through all sectors bounded by facets at this segment. + // Within each sector, create a new Steiner point 'np', and replace 'p' + // by 'np' for all tets in this sector. + for (i = 0; i < cavesegshlist->objects; i++) { + parysh = (face *) fastlookup(cavesegshlist, i); + // 'parysh' is the face [lpt, steinerpt, #]. + stpivot(*parysh, neightet); + // Get all tets in this sector. + setpoint2tet(steinerpt, encode(neightet)); + getvertexstar(0, steinerpt, cavetetlist, NULL, caveshlist); + if (!ishulltet(neightet)) { + // Within each tet in the ball, replace 'p' by 'np'. + for (j = 0; j < cavetetlist->objects; j++) { + parytet = (triface *) fastlookup(cavetetlist, j); + setoppo(*parytet, newsteiners[i]); + } // j + // Point to a parent tet. + parytet = (triface *) fastlookup(cavetetlist, 0); + setpoint2tet(newsteiners[i], (tetrahedron) (parytet->tet)); + st_volref_count++; + if (steinerleft > 0) steinerleft--; + } + // Disconnect the set of boundary faces. They're temporarily open faces. + // They will be connected to the new tets after 'p' is removed. + for (j = 0; j < caveshlist->objects; j++) { + // Get a boundary face. + parysh = (face *) fastlookup(caveshlist, j); + stpivot(*parysh, neightet); + //assert(apex(neightet) == newpt); + // Clear the connection at this face. + dissolve(neightet); + tsdissolve(neightet); + } + // Clear the working lists. + cavetetlist->restart(); + caveshlist->restart(); + } // i + cavesegshlist->restart(); + + if (vt == FREESEGVERTEX) { + spivot(rightseg, parentsh); // 'rightseg' has p as its origin. + splitseg = &rightseg; + } else { + if (sdest(parentsh) == steinerpt) { + senextself(parentsh); + } else if (sapex(parentsh) == steinerpt) { + senext2self(parentsh); + } + assert(sorg(parentsh) == steinerpt); + splitseg = NULL; + } + sremovevertex(steinerpt, &parentsh, splitseg, slawson); + + if (vt == FREESEGVERTEX) { + // The original segment is returned in 'rightseg'. + rightseg.shver = 0; + } + + // For each new subface, create two new tets at each side of it. + // Both of the two new tets have its opposite be dummypoint. + for (i = 0; i < caveshbdlist->objects; i++) { + parysh = (face *) fastlookup(caveshbdlist, i); + sinfect(*parysh); // Mark it for connecting new tets. + newsh = *parysh; + pa = sorg(newsh); + pb = sdest(newsh); + pc = sapex(newsh); + maketetrahedron(&newtet); + maketetrahedron(&neightet); + setvertices(newtet, pa, pb, pc, dummypoint); + setvertices(neightet, pb, pa, pc, dummypoint); + bond(newtet, neightet); + tsbond(newtet, newsh); + sesymself(newsh); + tsbond(neightet, newsh); + } + // Temporarily increase the hullsize. + hullsize += (caveshbdlist->objects * 2l); + + if (vt == FREESEGVERTEX) { + // Connecting new tets at the recovered segment. + spivot(rightseg, parentsh); + assert(parentsh.sh != NULL); + spinsh = parentsh; + while (1) { + if (sorg(spinsh) != lpt) sesymself(spinsh); + // Get the new tet at this subface. + stpivot(spinsh, newtet); + tssbond1(newtet, rightseg); + // Go to the other face at this segment. + spivot(spinsh, neighsh); + if (sorg(neighsh) != lpt) sesymself(neighsh); + sesymself(neighsh); + stpivot(neighsh, neightet); + tssbond1(neightet, rightseg); + sstbond1(rightseg, neightet); + // Connecting two adjacent tets at this segment. + esymself(newtet); + esymself(neightet); + // Connect the two tets (at rightseg) together. + bond(newtet, neightet); + // Go to the next subface. + spivotself(spinsh); + if (spinsh.sh == parentsh.sh) break; + } + } + + // Connecting new tets at new subfaces together. + for (i = 0; i < caveshbdlist->objects; i++) { + parysh = (face *) fastlookup(caveshbdlist, i); + newsh = *parysh; + //assert(sinfected(newsh)); + // Each new subface contains two new tets. + for (k = 0; k < 2; k++) { + stpivot(newsh, newtet); + for (j = 0; j < 3; j++) { + // Check if this side is open. + esym(newtet, newface); + if (newface.tet[newface.ver & 3] == NULL) { + // An open face. Connect it to its adjacent tet. + sspivot(newsh, checkseg); + if (checkseg.sh != NULL) { + // A segment. It must not be the recovered segment. + tssbond1(newtet, checkseg); + sstbond1(checkseg, newtet); + } + spivot(newsh, neighsh); + if (neighsh.sh != NULL) { + // The adjacent subface exists. It's not a dangling segment. + if (sorg(neighsh) != sdest(newsh)) sesymself(neighsh); + stpivot(neighsh, neightet); + if (sinfected(neighsh)) { + esymself(neightet); + assert(neightet.tet[neightet.ver & 3] == NULL); + } else { + // Search for an open face at this edge. + spintet = neightet; + while (1) { + esym(spintet, searchtet); + fsym(searchtet, spintet); + if (spintet.tet == NULL) break; + assert(spintet.tet != neightet.tet); + } + // Found an open face at 'searchtet'. + neightet = searchtet; + } + } else { + // The edge (at 'newsh') is a dangling segment. + assert(checkseg.sh != NULL); + // Get an adjacent tet at this segment. + sstpivot1(checkseg, neightet); + assert(!isdeadtet(neightet)); + if (org(neightet) != sdest(newsh)) esymself(neightet); + assert((org(neightet) == sdest(newsh)) && + (dest(neightet) == sorg(newsh))); + // Search for an open face at this edge. + spintet = neightet; + while (1) { + esym(spintet, searchtet); + fsym(searchtet, spintet); + if (spintet.tet == NULL) break; + assert(spintet.tet != neightet.tet); + } + // Found an open face at 'searchtet'. + neightet = searchtet; + } + pc = apex(newface); + if (apex(neightet) == steinerpt) { + // Exterior case. The 'neightet' is a hull tet which contain + // 'steinerpt'. It will be deleted after 'steinerpt' is removed. + assert(pc == dummypoint); + caveoldtetlist->newindex((void **) &parytet); + *parytet = neightet; + // Connect newface to the adjacent hull tet of 'neightet', which + // has the same edge as 'newface', and does not has 'steinerpt'. + fnextself(neightet); + } else { + if (pc == dummypoint) { + if (apex(neightet) != dummypoint) { + setapex(newface, apex(neightet)); + // A hull tet has turned into an interior tet. + hullsize--; // Must update the hullsize. + } + } + } + bond(newface, neightet); + } // if (newface.tet[newface.ver & 3] == NULL) + enextself(newtet); + senextself(newsh); + } // j + sesymself(newsh); + } // k + } // i + + // Unmark all new subfaces. + for (i = 0; i < caveshbdlist->objects; i++) { + parysh = (face *) fastlookup(caveshbdlist, i); + suninfect(*parysh); + } + caveshbdlist->restart(); + + if (caveoldtetlist->objects > 0l) { + // Delete hull tets which contain 'steinerpt'. + for (i = 0; i < caveoldtetlist->objects; i++) { + parytet = (triface *) fastlookup(caveoldtetlist, i); + tetrahedrondealloc(parytet->tet); + } + // Must update the hullsize. + hullsize -= caveoldtetlist->objects; + caveoldtetlist->restart(); + } + + setpointtype(steinerpt, UNUSEDVERTEX); + unuverts++; + if (vt == FREESEGVERTEX) { + st_segref_count--; + } else { // vt == FREEFACETVERTEX + st_facref_count--; + } + if (steinerleft > 0) steinerleft++; // We've removed a Steiner points. + + + point *parypt; + int steinercount = 0; + + int bak_fliplinklevel = b->fliplinklevel; + b->fliplinklevel = 100000; // Unlimited flip level. + + // Try to remove newly added Steiner points. + for (i = 0; i < n; i++) { + if (newsteiners[i] != NULL) { + if (!removevertexbyflips(newsteiners[i])) { + if (b->nobisect_param > 0) { // Not -Y0 + // Save it in subvertstack for removal. + subvertstack->newindex((void **) &parypt); + *parypt = newsteiners[i]; + } + steinercount++; + } + } + } + + b->fliplinklevel = bak_fliplinklevel; + + if (steinercount > 0) { + if (b->verbose > 2) { + printf(" Added %d interior Steiner points.\n", steinercount); + } + } + + delete [] newsteiners; + + return 1; +} + + +/////////////////////////////////////////////////////////////////////////////// +// // +// suppresssteinerpoints() Suppress Steiner points. // +// // +// All Steiner points have been saved in 'subvertstack' in the routines // +// carveholes() and suppresssteinerpoint(). // +// Each Steiner point is either removed or shifted into the interior. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::suppresssteinerpoints() +{ + + if (!b->quiet) { + printf("Suppressing Steiner points ...\n"); + } + + point rempt, *parypt; + + int bak_fliplinklevel = b->fliplinklevel; + b->fliplinklevel = 100000; // Unlimited flip level. + int suppcount = 0, remcount = 0; + int i; + + // Try to suppress boundary Steiner points. + for (i = 0; i < subvertstack->objects; i++) { + parypt = (point *) fastlookup(subvertstack, i); + rempt = *parypt; + if (pointtype(rempt) != UNUSEDVERTEX) { + if ((pointtype(rempt) == FREESEGVERTEX) || + (pointtype(rempt) == FREEFACETVERTEX)) { + if (suppressbdrysteinerpoint(rempt)) { + suppcount++; + } + } + } + } // i + + if (suppcount > 0) { + if (b->verbose) { + printf(" Suppressed %d boundary Steiner points.\n", suppcount); + } + } + + if (b->nobisect_param > 0) { // -Y1 + for (i = 0; i < subvertstack->objects; i++) { + parypt = (point *) fastlookup(subvertstack, i); + rempt = *parypt; + if (pointtype(rempt) != UNUSEDVERTEX) { + if (pointtype(rempt) == FREEVOLVERTEX) { + if (removevertexbyflips(rempt)) { + remcount++; + } + } + } + } + } + + if (remcount > 0) { + if (b->verbose) { + printf(" Removed %d interior Steiner points.\n", remcount); + } + } + + b->fliplinklevel = bak_fliplinklevel; + + if (b->nobisect_param > 1) { // -Y2 + // Smooth interior Steiner points. + optparameters opm; + triface *parytet; + point *ppt; + REAL ori; + int smtcount, count, ivcount; + int nt, j; + + // Point smooth options. + opm.max_min_volume = 1; + opm.numofsearchdirs = 20; + opm.searchstep = 0.001; + opm.maxiter = 30; // Limit the maximum iterations. + + smtcount = 0; + + do { + + nt = 0; + + while (1) { + count = 0; + ivcount = 0; // Clear the inverted count. + + for (i = 0; i < subvertstack->objects; i++) { + parypt = (point *) fastlookup(subvertstack, i); + rempt = *parypt; + if (pointtype(rempt) == FREEVOLVERTEX) { + getvertexstar(1, rempt, cavetetlist, NULL, NULL); + // Calculate the initial smallest volume (maybe zero or negative). + for (j = 0; j < cavetetlist->objects; j++) { + parytet = (triface *) fastlookup(cavetetlist, j); + ppt = (point *) &(parytet->tet[4]); + ori = orient3dfast(ppt[1], ppt[0], ppt[2], ppt[3]); + if (j == 0) { + opm.initval = ori; + } else { + if (opm.initval > ori) opm.initval = ori; + } + } + if (smoothpoint(rempt, cavetetlist, 1, &opm)) { + count++; + } + if (opm.imprval <= 0.0) { + ivcount++; // The mesh contains inverted elements. + } + cavetetlist->restart(); + } + } // i + + smtcount += count; + + if (count == 0) { + // No point has been smoothed. + break; + } + + nt++; + if (nt > 2) { + break; // Already three iterations. + } + } // while + + if (ivcount > 0) { + // There are inverted elements! + if (opm.maxiter > 0) { + // Set unlimited smoothing steps. Try again. + opm.numofsearchdirs = 30; + opm.searchstep = 0.0001; + opm.maxiter = -1; + continue; + } + } + + break; + } while (1); // Additional loop for (ivcount > 0) + + if (ivcount > 0) { + printf("BUG Report! The mesh contain inverted elements.\n"); + } + + if (b->verbose) { + if (smtcount > 0) { + printf(" Smoothed %d Steiner points.\n", smtcount); + } + } + } // -Y2 + + subvertstack->restart(); + + return 1; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// recoverboundary() Recover segments and facets. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::recoverboundary(clock_t& tv) +{ + arraypool *misseglist, *misshlist; + arraypool *bdrysteinerptlist; + face searchsh, *parysh; + face searchseg, *paryseg; + point rempt, *parypt; + long ms; // The number of missing segments/subfaces. + int nit; // The number of iterations. + int s, i; + + // Counters. + long bak_segref_count, bak_facref_count, bak_volref_count; + + if (!b->quiet) { + printf("Recovering boundaries...\n"); + } + + + if (b->verbose) { + printf(" Recovering segments.\n"); + } + + // Segments will be introduced. + checksubsegflag = 1; + + misseglist = new arraypool(sizeof(face), 8); + bdrysteinerptlist = new arraypool(sizeof(point), 8); + + // In random order. + subsegs->traversalinit(); + for (i = 0; i < subsegs->items; i++) { + s = randomnation(i + 1); + // Move the s-th seg to the i-th. + subsegstack->newindex((void **) &paryseg); + *paryseg = * (face *) fastlookup(subsegstack, s); + // Put i-th seg to be the s-th. + searchseg.sh = shellfacetraverse(subsegs); + paryseg = (face *) fastlookup(subsegstack, s); + *paryseg = searchseg; + } + + // The init number of missing segments. + ms = subsegs->items; + nit = 0; + if (b->fliplinklevel < 0) { + autofliplinklevel = 1; // Init value. + } + + // First, trying to recover segments by only doing flips. + while (1) { + recoversegments(misseglist, 0, 0); + + if (misseglist->objects > 0) { + if (b->fliplinklevel >= 0) { + break; + } else { + if (misseglist->objects >= ms) { + nit++; + if (nit >= 3) { + //break; + // Do the last round with unbounded flip link level. + b->fliplinklevel = 100000; + } + } else { + ms = misseglist->objects; + if (nit > 0) { + nit--; + } + } + for (i = 0; i < misseglist->objects; i++) { + subsegstack->newindex((void **) &paryseg); + *paryseg = * (face *) fastlookup(misseglist, i); + } + misseglist->restart(); + autofliplinklevel+=b->fliplinklevelinc; + } + } else { + // All segments are recovered. + break; + } + } // while (1) + + if (b->verbose) { + printf(" %ld (%ld) segments are recovered (missing).\n", + subsegs->items - misseglist->objects, misseglist->objects); + } + + if (misseglist->objects > 0) { + // Second, trying to recover segments by doing more flips (fullsearch). + while (misseglist->objects > 0) { + ms = misseglist->objects; + for (i = 0; i < misseglist->objects; i++) { + subsegstack->newindex((void **) &paryseg); + *paryseg = * (face *) fastlookup(misseglist, i); + } + misseglist->restart(); + + recoversegments(misseglist, 1, 0); + + if (misseglist->objects < ms) { + // The number of missing segments is reduced. + continue; + } else { + break; + } + } + if (b->verbose) { + printf(" %ld (%ld) segments are recovered (missing).\n", + subsegs->items - misseglist->objects, misseglist->objects); + } + } + + if (misseglist->objects > 0) { + // Third, trying to recover segments by doing more flips (fullsearch) + // and adding Steiner points in the volume. + while (misseglist->objects > 0) { + ms = misseglist->objects; + for (i = 0; i < misseglist->objects; i++) { + subsegstack->newindex((void **) &paryseg); + *paryseg = * (face *) fastlookup(misseglist, i); + } + misseglist->restart(); + + recoversegments(misseglist, 1, 1); + + if (misseglist->objects < ms) { + // The number of missing segments is reduced. + continue; + } else { + break; + } + } + if (b->verbose) { + printf(" Added %ld Steiner points in volume.\n", st_volref_count); + } + } + + if (misseglist->objects > 0) { + // Last, trying to recover segments by doing more flips (fullsearch), + // and adding Steiner points in the volume, and splitting segments. + long bak_inpoly_count = st_volref_count; //st_inpoly_count; + for (i = 0; i < misseglist->objects; i++) { + subsegstack->newindex((void **) &paryseg); + *paryseg = * (face *) fastlookup(misseglist, i); + } + misseglist->restart(); + + recoversegments(misseglist, 1, 2); + + if (b->verbose) { + printf(" Added %ld Steiner points in segments.\n", st_segref_count); + if (st_volref_count > bak_inpoly_count) { + printf(" Added another %ld Steiner points in volume.\n", + st_volref_count - bak_inpoly_count); + } + } + assert(misseglist->objects == 0l); + } + + + if (st_segref_count > 0) { + // Try to remove the Steiner points added in segments. + bak_segref_count = st_segref_count; + bak_volref_count = st_volref_count; + for (i = 0; i < subvertstack->objects; i++) { + // Get the Steiner point. + parypt = (point *) fastlookup(subvertstack, i); + rempt = *parypt; + if (!removevertexbyflips(rempt)) { + // Save it in list. + bdrysteinerptlist->newindex((void **) &parypt); + *parypt = rempt; + } + } + if (b->verbose) { + if (st_segref_count < bak_segref_count) { + if (bak_volref_count < st_volref_count) { + printf(" Suppressed %ld Steiner points in segments.\n", + st_volref_count - bak_volref_count); + } + if ((st_segref_count + (st_volref_count - bak_volref_count)) < + bak_segref_count) { + printf(" Removed %ld Steiner points in segments.\n", + bak_segref_count - + (st_segref_count + (st_volref_count - bak_volref_count))); + } + } + } + subvertstack->restart(); + } + + + tv = clock(); + + if (b->verbose) { + printf(" Recovering facets.\n"); + } + + // Subfaces will be introduced. + checksubfaceflag = 1; + + misshlist = new arraypool(sizeof(face), 8); + + // Randomly order the subfaces. + subfaces->traversalinit(); + for (i = 0; i < subfaces->items; i++) { + s = randomnation(i + 1); + // Move the s-th subface to the i-th. + subfacstack->newindex((void **) &parysh); + *parysh = * (face *) fastlookup(subfacstack, s); + // Put i-th subface to be the s-th. + searchsh.sh = shellfacetraverse(subfaces); + parysh = (face *) fastlookup(subfacstack, s); + *parysh = searchsh; + } + + ms = subfaces->items; + nit = 0; + b->fliplinklevel = -1; // Init. + if (b->fliplinklevel < 0) { + autofliplinklevel = 1; // Init value. + } + + while (1) { + recoversubfaces(misshlist, 0); + + if (misshlist->objects > 0) { + if (b->fliplinklevel >= 0) { + break; + } else { + if (misshlist->objects >= ms) { + nit++; + if (nit >= 3) { + //break; + // Do the last round with unbounded flip link level. + b->fliplinklevel = 100000; + } + } else { + ms = misshlist->objects; + if (nit > 0) { + nit--; + } + } + for (i = 0; i < misshlist->objects; i++) { + subfacstack->newindex((void **) &parysh); + *parysh = * (face *) fastlookup(misshlist, i); + } + misshlist->restart(); + autofliplinklevel+=b->fliplinklevelinc; + } + } else { + // All subfaces are recovered. + break; + } + } // while (1) + + if (b->verbose) { + printf(" %ld (%ld) subfaces are recovered (missing).\n", + subfaces->items - misshlist->objects, misshlist->objects); + } + + if (misshlist->objects > 0) { + // There are missing subfaces. Add Steiner points. + for (i = 0; i < misshlist->objects; i++) { + subfacstack->newindex((void **) &parysh); + *parysh = * (face *) fastlookup(misshlist, i); + } + misshlist->restart(); + + recoversubfaces(NULL, 1); + + if (b->verbose) { + printf(" Added %ld Steiner points in facets.\n", st_facref_count); + } + } + + + if (st_facref_count > 0) { + // Try to remove the Steiner points added in facets. + bak_facref_count = st_facref_count; + for (i = 0; i < subvertstack->objects; i++) { + // Get the Steiner point. + parypt = (point *) fastlookup(subvertstack, i); + rempt = *parypt; + if (!removevertexbyflips(*parypt)) { + // Save it in list. + bdrysteinerptlist->newindex((void **) &parypt); + *parypt = rempt; + } + } + if (b->verbose) { + if (st_facref_count < bak_facref_count) { + printf(" Removed %ld Steiner points in facets.\n", + bak_facref_count - st_facref_count); + } + } + subvertstack->restart(); + } + + + if (bdrysteinerptlist->objects > 0) { + if (b->verbose) { + printf(" %ld Steiner points remained in boundary.\n", + bdrysteinerptlist->objects); + } + } // if + + + // Accumulate the dynamic memory. + totalworkmemory += (misseglist->totalmemory + misshlist->totalmemory + + bdrysteinerptlist->totalmemory); + + delete bdrysteinerptlist; + delete misseglist; + delete misshlist; +} + +//// //// +//// //// +//// steiner_cxx ////////////////////////////////////////////////////////////// + + +//// reconstruct_cxx ////////////////////////////////////////////////////////// +//// //// +//// //// + +/////////////////////////////////////////////////////////////////////////////// +// // +// carveholes() Remove tetrahedra not in the mesh domain. // +// // +/////////////////////////////////////////////////////////////////////////////// + + +void tetgenmesh::carveholes() +{ + arraypool *tetarray, *hullarray; + triface tetloop, neightet, *parytet, *parytet1; + triface *regiontets = NULL; + face checksh, *parysh; + face checkseg; + point ptloop, *parypt; + int t1ver; + int i, j, k; + + if (!b->quiet) { + if (b->convex) { + printf("Marking exterior tetrahedra ...\n"); + } else { + printf("Removing exterior tetrahedra ...\n"); + } + } + + // Initialize the pool of exterior tets. + tetarray = new arraypool(sizeof(triface), 10); + hullarray = new arraypool(sizeof(triface), 10); + + // Collect unprotected tets and hull tets. + tetrahedrons->traversalinit(); + tetloop.ver = 11; // The face opposite to dummypoint. + tetloop.tet = alltetrahedrontraverse(); + while (tetloop.tet != (tetrahedron *) NULL) { + if (ishulltet(tetloop)) { + // Is this side protected by a subface? + if (!issubface(tetloop)) { + // Collect an unprotected hull tet and tet. + infect(tetloop); + hullarray->newindex((void **) &parytet); + *parytet = tetloop; + // tetloop's face number is 11 & 3 = 3. + decode(tetloop.tet[3], neightet); + if (!infected(neightet)) { + infect(neightet); + tetarray->newindex((void **) &parytet); + *parytet = neightet; + } + } + } + tetloop.tet = alltetrahedrontraverse(); + } + + if (in->numberofholes > 0) { + // Mark as infected any tets inside volume holes. + for (i = 0; i < 3 * in->numberofholes; i += 3) { + // Search a tet containing the i-th hole point. + neightet.tet = NULL; + randomsample(&(in->holelist[i]), &neightet); + if (locate(&(in->holelist[i]), &neightet) != OUTSIDE) { + // The tet 'neightet' contain this point. + if (!infected(neightet)) { + infect(neightet); + tetarray->newindex((void **) &parytet); + *parytet = neightet; + // Add its adjacent tet if it is not protected. + if (!issubface(neightet)) { + decode(neightet.tet[neightet.ver & 3], tetloop); + if (!infected(tetloop)) { + infect(tetloop); + if (ishulltet(tetloop)) { + hullarray->newindex((void **) &parytet); + } else { + tetarray->newindex((void **) &parytet); + } + *parytet = tetloop; + } + } + else { + // It is protected. Check if its adjacent tet is a hull tet. + decode(neightet.tet[neightet.ver & 3], tetloop); + if (ishulltet(tetloop)) { + // It is hull tet, add it into the list. Moreover, the subface + // is dead, i.e., both sides are in exterior. + if (!infected(tetloop)) { + infect(tetloop); + hullarray->newindex((void **) &parytet); + *parytet = tetloop; + } + } + if (infected(tetloop)) { + // Both sides of this subface are in exterior. + tspivot(neightet, checksh); + sinfect(checksh); // Only queue it once. + subfacstack->newindex((void **) &parysh); + *parysh = checksh; + } + } + } // if (!infected(neightet)) + } else { + // A hole point locates outside of the convex hull. + if (!b->quiet) { + printf("Warning: The %d-th hole point ", i/3 + 1); + printf("lies outside the convex hull.\n"); + } + } + } // i + } // if (in->numberofholes > 0) + + if (b->regionattrib && (in->numberofregions > 0)) { // -A option. + // Record the tetrahedra that contains the region points for assigning + // region attributes after the holes have been carved. + regiontets = new triface[in->numberofregions]; + // Mark as marktested any tetrahedra inside volume regions. + for (i = 0; i < 5 * in->numberofregions; i += 5) { + // Search a tet containing the i-th region point. + neightet.tet = NULL; + randomsample(&(in->regionlist[i]), &neightet); + if (locate(&(in->regionlist[i]), &neightet) != OUTSIDE) { + regiontets[i/5] = neightet; + } else { + if (!b->quiet) { + printf("Warning: The %d-th region point ", i/5+1); + printf("lies outside the convex hull.\n"); + } + regiontets[i/5].tet = NULL; + } + } + } + + // Collect all exterior tets (in concave place and in holes). + for (i = 0; i < tetarray->objects; i++) { + parytet = (triface *) fastlookup(tetarray, i); + j = (parytet->ver & 3); // j is the current face number. + // Check the other three adjacent tets. + for (k = 1; k < 4; k++) { + decode(parytet->tet[(j + k) % 4], neightet); + // neightet may be a hull tet. + if (!infected(neightet)) { + // Is neightet protected by a subface. + if (!issubface(neightet)) { + // Not proected. Collect it. (It must not be a hull tet). + infect(neightet); + tetarray->newindex((void **) &parytet1); + *parytet1 = neightet; + } else { + // Protected. Check if it is a hull tet. + if (ishulltet(neightet)) { + // A hull tet. Collect it. + infect(neightet); + hullarray->newindex((void **) &parytet1); + *parytet1 = neightet; + // Both sides of this subface are exterior. + tspivot(neightet, checksh); + // Queue this subface (to be deleted later). + assert(!sinfected(checksh)); + sinfect(checksh); // Only queue it once. + subfacstack->newindex((void **) &parysh); + *parysh = checksh; + } + } + } else { + // Both sides of this face are in exterior. + // If there is a subface. It should be collected. + if (issubface(neightet)) { + tspivot(neightet, checksh); + if (!sinfected(checksh)) { + sinfect(checksh); + subfacstack->newindex((void **) &parysh); + *parysh = checksh; + } + } + } + } // j, k + } // i + + if (b->regionattrib && (in->numberofregions > 0)) { + // Re-check saved region tets to see if they lie outside. + for (i = 0; i < in->numberofregions; i++) { + if (infected(regiontets[i])) { + if (b->verbose) { + printf("Warning: The %d-th region point ", i+1); + printf("lies in the exterior of the domain.\n"); + } + regiontets[i].tet = NULL; + } + } + } + + // Collect vertices which point to infected tets. These vertices + // may get deleted after the removal of exterior tets. + // If -Y1 option is used, collect all Steiner points for removal. + // The lists 'cavetetvertlist' and 'subvertstack' are re-used. + points->traversalinit(); + ptloop = pointtraverse(); + while (ptloop != NULL) { + if ((pointtype(ptloop) != UNUSEDVERTEX) && + (pointtype(ptloop) != DUPLICATEDVERTEX)) { + decode(point2tet(ptloop), neightet); + if (infected(neightet)) { + cavetetvertlist->newindex((void **) &parypt); + *parypt = ptloop; + } + if (b->nobisect && (b->nobisect_param > 0)) { // -Y1 + // Queue it if it is a Steiner point. + if (pointmark(ptloop) > + (in->numberofpoints - (in->firstnumber ? 0 : 1))) { + subvertstack->newindex((void **) &parypt); + *parypt = ptloop; + } + } + } + ptloop = pointtraverse(); + } + + if (!b->convex && (tetarray->objects > 0l)) { // No -c option. + // Remove exterior tets. Hull tets are updated. + arraypool *newhullfacearray; + triface hulltet, casface; + point pa, pb, pc; + + newhullfacearray = new arraypool(sizeof(triface), 10); + + // Create and save new hull tets. + for (i = 0; i < tetarray->objects; i++) { + parytet = (triface *) fastlookup(tetarray, i); + for (j = 0; j < 4; j++) { + decode(parytet->tet[j], tetloop); + if (!infected(tetloop)) { + // Found a new hull face (must be a subface). + tspivot(tetloop, checksh); + maketetrahedron(&hulltet); + pa = org(tetloop); + pb = dest(tetloop); + pc = apex(tetloop); + setvertices(hulltet, pb, pa, pc, dummypoint); + bond(tetloop, hulltet); + // Update the subface-to-tet map. + sesymself(checksh); + tsbond(hulltet, checksh); + // Update the segment-to-tet map. + for (k = 0; k < 3; k++) { + if (issubseg(tetloop)) { + tsspivot1(tetloop, checkseg); + tssbond1(hulltet, checkseg); + sstbond1(checkseg, hulltet); + } + enextself(tetloop); + eprevself(hulltet); + } + // Update the point-to-tet map. + setpoint2tet(pa, (tetrahedron) tetloop.tet); + setpoint2tet(pb, (tetrahedron) tetloop.tet); + setpoint2tet(pc, (tetrahedron) tetloop.tet); + // Save the exterior tet at this hull face. It still holds pointer + // to the adjacent interior tet. Use it to connect new hull tets. + newhullfacearray->newindex((void **) &parytet1); + parytet1->tet = parytet->tet; + parytet1->ver = j; + } // if (!infected(tetloop)) + } // j + } // i + + // Connect new hull tets. + for (i = 0; i < newhullfacearray->objects; i++) { + parytet = (triface *) fastlookup(newhullfacearray, i); + fsym(*parytet, neightet); + // Get the new hull tet. + fsym(neightet, hulltet); + for (j = 0; j < 3; j++) { + esym(hulltet, casface); + if (casface.tet[casface.ver & 3] == NULL) { + // Since the boundary of the domain may not be a manifold, we + // find the adjacent hull face by traversing the tets in the + // exterior (which are all infected tets). + neightet = *parytet; + while (1) { + fnextself(neightet); + if (!infected(neightet)) break; + } + if (!ishulltet(neightet)) { + // An interior tet. Get the new hull tet. + fsymself(neightet); + esymself(neightet); + } + // Bond them together. + bond(casface, neightet); + } + enextself(hulltet); + enextself(*parytet); + } // j + } // i + + if (subfacstack->objects > 0l) { + // Remove all subfaces which do not attach to any tetrahedron. + // Segments which are not attached to any subfaces and tets + // are deleted too. + face casingout, casingin; + long delsegcount = 0l; + + for (i = 0; i < subfacstack->objects; i++) { + parysh = (face *) fastlookup(subfacstack, i); + if (i == 0) { + if (b->verbose) { + printf("Warning: Removing an open face (%d, %d, %d)\n", + pointmark(sorg(*parysh)), pointmark(sdest(*parysh)), + pointmark(sapex(*parysh))); + } + } + // Dissolve this subface from face links. + for (j = 0; j < 3; j++) { + spivot(*parysh, casingout); + sspivot(*parysh, checkseg); + if (casingout.sh != NULL) { + casingin = casingout; + while (1) { + spivot(casingin, checksh); + if (checksh.sh == parysh->sh) break; + casingin = checksh; + } + if (casingin.sh != casingout.sh) { + // Update the link: ... -> casingin -> casingout ->... + sbond1(casingin, casingout); + } else { + // Only one subface at this edge is left. + sdissolve(casingout); + } + if (checkseg.sh != NULL) { + // Make sure the segment does not connect to a dead one. + ssbond(casingout, checkseg); + } + } else { + if (checkseg.sh != NULL) { + // The segment is also dead. + if (delsegcount == 0) { + if (b->verbose) { + printf("Warning: Removing a dangling segment (%d, %d)\n", + pointmark(sorg(checkseg)), pointmark(sdest(checkseg))); + } + } + shellfacedealloc(subsegs, checkseg.sh); + delsegcount++; + } + } + senextself(*parysh); + } // j + // Delete this subface. + shellfacedealloc(subfaces, parysh->sh); + } // i + if (b->verbose) { + printf(" Deleted %ld subfaces.\n", subfacstack->objects); + if (delsegcount > 0) { + printf(" Deleted %ld segments.\n", delsegcount); + } + } + subfacstack->restart(); + } // if (subfacstack->objects > 0l) + + if (cavetetvertlist->objects > 0l) { + // Some vertices may lie in exterior. Marke them as UNUSEDVERTEX. + long delvertcount = unuverts; + long delsteinercount = 0l; + + for (i = 0; i < cavetetvertlist->objects; i++) { + parypt = (point *) fastlookup(cavetetvertlist, i); + decode(point2tet(*parypt), neightet); + if (infected(neightet)) { + // Found an exterior vertex. + if (pointmark(*parypt) > + (in->numberofpoints - (in->firstnumber ? 0 : 1))) { + // A Steiner point. + if (pointtype(*parypt) == FREESEGVERTEX) { + st_segref_count--; + } else if (pointtype(*parypt) == FREEFACETVERTEX) { + st_facref_count--; + } else { + assert(pointtype(*parypt) == FREEVOLVERTEX); + st_volref_count--; + } + delsteinercount++; + if (steinerleft > 0) steinerleft++; + } + setpointtype(*parypt, UNUSEDVERTEX); + unuverts++; + } + } + + if (b->verbose) { + if (unuverts > delvertcount) { + if (delsteinercount > 0l) { + if (unuverts > (delvertcount + delsteinercount)) { + printf(" Removed %ld exterior input vertices.\n", + unuverts - delvertcount - delsteinercount); + } + printf(" Removed %ld exterior Steiner vertices.\n", + delsteinercount); + } else { + printf(" Removed %ld exterior input vertices.\n", + unuverts - delvertcount); + } + } + } + cavetetvertlist->restart(); + // Comment: 'subvertstack' will be cleaned in routine + // suppresssteinerpoints(). + } // if (cavetetvertlist->objects > 0l) + + // Update the hull size. + hullsize += (newhullfacearray->objects - hullarray->objects); + + // Delete all exterior tets and old hull tets. + for (i = 0; i < tetarray->objects; i++) { + parytet = (triface *) fastlookup(tetarray, i); + tetrahedrondealloc(parytet->tet); + } + tetarray->restart(); + + for (i = 0; i < hullarray->objects; i++) { + parytet = (triface *) fastlookup(hullarray, i); + tetrahedrondealloc(parytet->tet); + } + hullarray->restart(); + + delete newhullfacearray; + } // if (!b->convex && (tetarray->objects > 0l)) + + if (b->convex && (tetarray->objects > 0l)) { // With -c option + // In this case, all exterior tets get a region marker '-1'. + assert(b->regionattrib > 0); // -A option must be enabled. + int attrnum = numelemattrib - 1; + + for (i = 0; i < tetarray->objects; i++) { + parytet = (triface *) fastlookup(tetarray, i); + setelemattribute(parytet->tet, attrnum, -1); + } + tetarray->restart(); + + for (i = 0; i < hullarray->objects; i++) { + parytet = (triface *) fastlookup(hullarray, i); + uninfect(*parytet); + } + hullarray->restart(); + + if (subfacstack->objects > 0l) { + for (i = 0; i < subfacstack->objects; i++) { + parysh = (face *) fastlookup(subfacstack, i); + suninfect(*parysh); + } + subfacstack->restart(); + } + + if (cavetetvertlist->objects > 0l) { + cavetetvertlist->restart(); + } + } // if (b->convex && (tetarray->objects > 0l)) + + if (b->regionattrib) { // With -A option. + if (!b->quiet) { + printf("Spreading region attributes.\n"); + } + REAL volume; + int attr, maxattr = 0; // Choose a small number here. + int attrnum = numelemattrib - 1; + // Comment: The element region marker is at the end of the list of + // the element attributes. + int regioncount = 0; + + // If has user-defined region attributes. + if (in->numberofregions > 0) { + // Spread region attributes. + for (i = 0; i < 5 * in->numberofregions; i += 5) { + if (regiontets[i/5].tet != NULL) { + attr = (int) in->regionlist[i + 3]; + if (attr > maxattr) { + maxattr = attr; + } + volume = in->regionlist[i + 4]; + tetarray->restart(); // Re-use this array. + infect(regiontets[i/5]); + tetarray->newindex((void **) &parytet); + *parytet = regiontets[i/5]; + // Collect and set attrs for all tets of this region. + for (j = 0; j < tetarray->objects; j++) { + parytet = (triface *) fastlookup(tetarray, j); + tetloop = *parytet; + setelemattribute(tetloop.tet, attrnum, attr); + if (b->varvolume) { // If has -a option. + setvolumebound(tetloop.tet, volume); + } + for (k = 0; k < 4; k++) { + decode(tetloop.tet[k], neightet); + // Is the adjacent already checked? + if (!infected(neightet)) { + // Is this side protected by a subface? + if (!issubface(neightet)) { + infect(neightet); + tetarray->newindex((void **) &parytet); + *parytet = neightet; + } + } + } // k + } // j + regioncount++; + } // if (regiontets[i/5].tet != NULL) + } // i + } + + // Set attributes for all tetrahedra. + attr = maxattr + 1; + tetrahedrons->traversalinit(); + tetloop.tet = tetrahedrontraverse(); + while (tetloop.tet != (tetrahedron *) NULL) { + if (!infected(tetloop)) { + // An unmarked region. + tetarray->restart(); // Re-use this array. + infect(tetloop); + tetarray->newindex((void **) &parytet); + *parytet = tetloop; + // Find and mark all tets. + for (j = 0; j < tetarray->objects; j++) { + parytet = (triface *) fastlookup(tetarray, j); + tetloop = *parytet; + setelemattribute(tetloop.tet, attrnum, attr); + for (k = 0; k < 4; k++) { + decode(tetloop.tet[k], neightet); + // Is the adjacent tet already checked? + if (!infected(neightet)) { + // Is this side protected by a subface? + if (!issubface(neightet)) { + infect(neightet); + tetarray->newindex((void **) &parytet); + *parytet = neightet; + } + } + } // k + } // j + attr++; // Increase the attribute. + regioncount++; + } + tetloop.tet = tetrahedrontraverse(); + } + // Until here, every tet has a region attribute. + + // Uninfect processed tets. + tetrahedrons->traversalinit(); + tetloop.tet = tetrahedrontraverse(); + while (tetloop.tet != (tetrahedron *) NULL) { + uninfect(tetloop); + tetloop.tet = tetrahedrontraverse(); + } + + if (b->verbose) { + //assert(regioncount > 0); + if (regioncount > 1) { + printf(" Found %d subdomains.\n", regioncount); + } else { + printf(" Found %d domain.\n", regioncount); + } + } + } // if (b->regionattrib) + + if (regiontets != NULL) { + delete [] regiontets; + } + delete tetarray; + delete hullarray; + + if (!b->convex) { // No -c option + // The mesh is non-convex now. + nonconvex = 1; + + // Push all hull tets into 'flipstack'. + tetrahedrons->traversalinit(); + tetloop.ver = 11; // The face opposite to dummypoint. + tetloop.tet = alltetrahedrontraverse(); + while (tetloop.tet != (tetrahedron *) NULL) { + if ((point) tetloop.tet[7] == dummypoint) { + fsym(tetloop, neightet); + flippush(flipstack, &neightet); + } + tetloop.tet = alltetrahedrontraverse(); + } + + flipconstraints fc; + fc.enqflag = 2; + long sliver_peel_count = lawsonflip3d(&fc); + + if (sliver_peel_count > 0l) { + if (b->verbose) { + printf(" Removed %ld hull slivers.\n", sliver_peel_count); + } + } + unflipqueue->restart(); + } // if (!b->convex) +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// reconstructmesh() Reconstruct a tetrahedral mesh. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::reconstructmesh() +{ + tetrahedron *ver2tetarray; + point *idx2verlist; + triface tetloop, checktet, prevchktet; + triface hulltet, face1, face2; + tetrahedron tptr; + face subloop, neighsh, nextsh; + face segloop; + shellface sptr; + point p[4], q[3]; + REAL ori, attrib, volume; + REAL angtol, ang; + int eextras, marker = 0; + int bondflag; + int t1ver; + int idx, i, j, k; + + if (!b->quiet) { + printf("Reconstructing mesh ...\n"); + } + + if (b->convex) { // -c option. + // Assume the mesh is convex. Exterior tets have region attribute -1. + assert(in->numberoftetrahedronattributes > 0); + } else { + // Assume the mesh is non-convex. + nonconvex = 1; + } + + // Create a map from indices to vertices. + makeindex2pointmap(idx2verlist); + // 'idx2verlist' has length 'in->numberofpoints + 1'. + if (in->firstnumber == 1) { + idx2verlist[0] = dummypoint; // Let 0th-entry be dummypoint. + } + + // Allocate an array that maps each vertex to its adjacent tets. + ver2tetarray = new tetrahedron[in->numberofpoints + 1]; + //for (i = 0; i < in->numberofpoints + 1; i++) { + for (i = in->firstnumber; i < in->numberofpoints + in->firstnumber; i++) { + setpointtype(idx2verlist[i], VOLVERTEX); // initial type. + ver2tetarray[i] = NULL; + } + + // Create the tetrahedra and connect those that share a common face. + for (i = 0; i < in->numberoftetrahedra; i++) { + // Get the four vertices. + idx = i * in->numberofcorners; + for (j = 0; j < 4; j++) { + p[j] = idx2verlist[in->tetrahedronlist[idx++]]; + } + // Check the orientation. + ori = orient3d(p[0], p[1], p[2], p[3]); + if (ori > 0.0) { + // Swap the first two vertices. + q[0] = p[0]; p[0] = p[1]; p[1] = q[0]; + } else if (ori == 0.0) { + if (!b->quiet) { + printf("Warning: Tet #%d is degenerate.\n", i + in->firstnumber); + } + } + // Create a new tetrahedron. + maketetrahedron(&tetloop); // tetloop.ver = 11. + setvertices(tetloop, p[0], p[1], p[2], p[3]); + // Set element attributes if they exist. + for (j = 0; j < in->numberoftetrahedronattributes; j++) { + idx = i * in->numberoftetrahedronattributes; + attrib = in->tetrahedronattributelist[idx + j]; + setelemattribute(tetloop.tet, j, attrib); + } + // If -a switch is used (with no number follows) Set a volume + // constraint if it exists. + if (b->varvolume) { + if (in->tetrahedronvolumelist != (REAL *) NULL) { + volume = in->tetrahedronvolumelist[i]; + } else { + volume = -1.0; + } + setvolumebound(tetloop.tet, volume); + } + // Try connecting this tet to others that share the common faces. + for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) { + p[3] = oppo(tetloop); + // Look for other tets having this vertex. + idx = pointmark(p[3]); + tptr = ver2tetarray[idx]; + // Link the current tet to the next one in the stack. + tetloop.tet[8 + tetloop.ver] = tptr; + // Push the current tet onto the stack. + ver2tetarray[idx] = encode(tetloop); + decode(tptr, checktet); + if (checktet.tet != NULL) { + p[0] = org(tetloop); // a + p[1] = dest(tetloop); // b + p[2] = apex(tetloop); // c + prevchktet = tetloop; + do { + q[0] = org(checktet); // a' + q[1] = dest(checktet); // b' + q[2] = apex(checktet); // c' + // Check the three faces at 'd' in 'checktet'. + bondflag = 0; + for (j = 0; j < 3; j++) { + // Go to the face [b',a',d], or [c',b',d], or [a',c',d]. + esym(checktet, face2); + if (face2.tet[face2.ver & 3] == NULL) { + k = ((j + 1) % 3); + if (q[k] == p[0]) { // b', c', a' = a + if (q[j] == p[1]) { // a', b', c' = b + // [#,#,d] is matched to [b,a,d]. + esym(tetloop, face1); + bond(face1, face2); + bondflag++; + } + } + if (q[k] == p[1]) { // b',c',a' = b + if (q[j] == p[2]) { // a',b',c' = c + // [#,#,d] is matched to [c,b,d]. + enext(tetloop, face1); + esymself(face1); + bond(face1, face2); + bondflag++; + } + } + if (q[k] == p[2]) { // b',c',a' = c + if (q[j] == p[0]) { // a',b',c' = a + // [#,#,d] is matched to [a,c,d]. + eprev(tetloop, face1); + esymself(face1); + bond(face1, face2); + bondflag++; + } + } + } else { + bondflag++; + } + enextself(checktet); + } // j + // Go to the next tet in the link. + tptr = checktet.tet[8 + checktet.ver]; + if (bondflag == 3) { + // All three faces at d in 'checktet' have been connected. + // It can be removed from the link. + prevchktet.tet[8 + prevchktet.ver] = tptr; + } else { + // Bakup the previous tet in the link. + prevchktet = checktet; + } + decode(tptr, checktet); + } while (checktet.tet != NULL); + } // if (checktet.tet != NULL) + } // for (tetloop.ver = 0; ... + } // i + + // Remember a tet of the mesh. + recenttet = tetloop; + + // Create hull tets, create the point-to-tet map, and clean up the + // temporary spaces used in each tet. + hullsize = tetrahedrons->items; + + tetrahedrons->traversalinit(); + tetloop.tet = tetrahedrontraverse(); + while (tetloop.tet != (tetrahedron *) NULL) { + tptr = encode(tetloop); + for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) { + if (tetloop.tet[tetloop.ver] == NULL) { + // Create a hull tet. + maketetrahedron(&hulltet); + p[0] = org(tetloop); + p[1] = dest(tetloop); + p[2] = apex(tetloop); + setvertices(hulltet, p[1], p[0], p[2], dummypoint); + bond(tetloop, hulltet); + // Try connecting this to others that share common hull edges. + for (j = 0; j < 3; j++) { + fsym(hulltet, face2); + while (1) { + if (face2.tet == NULL) break; + esymself(face2); + if (apex(face2) == dummypoint) break; + fsymself(face2); + } + if (face2.tet != NULL) { + // Found an adjacent hull tet. + assert(face2.tet[face2.ver & 3] == NULL); + esym(hulltet, face1); + bond(face1, face2); + } + enextself(hulltet); + } + //hullsize++; + } + // Create the point-to-tet map. + setpoint2tet((point) (tetloop.tet[4 + tetloop.ver]), tptr); + // Clean the temporary used space. + tetloop.tet[8 + tetloop.ver] = NULL; + } + tetloop.tet = tetrahedrontraverse(); + } + + hullsize = tetrahedrons->items - hullsize; + + // Subfaces will be inserted into the mesh. + if (in->trifacelist != NULL) { + // A .face file is given. It may contain boundary faces. Insert them. + for (i = 0; i < in->numberoftrifaces; i++) { + // Is it a subface? + if (in->trifacemarkerlist != NULL) { + marker = in->trifacemarkerlist[i]; + } else { + // Face markers are not available. Assume all of them are subfaces. + marker = 1; + } + if (marker > 0) { + idx = i * 3; + for (j = 0; j < 3; j++) { + p[j] = idx2verlist[in->trifacelist[idx++]]; + } + // Search the subface. + bondflag = 0; + // Make sure all vertices are in the mesh. Avoid crash. + for (j = 0; j < 3; j++) { + decode(point2tet(p[j]), checktet); + if (checktet.tet == NULL) break; + } + if ((j == 3) && getedge(p[0], p[1], &checktet)) { + tetloop = checktet; + q[2] = apex(checktet); + while (1) { + if (apex(tetloop) == p[2]) { + // Found the face. + // Check if there exist a subface already? + tspivot(tetloop, neighsh); + if (neighsh.sh != NULL) { + // Found a duplicated subface. + // This happens when the mesh was generated by other mesher. + bondflag = 0; + } else { + bondflag = 1; + } + break; + } + fnextself(tetloop); + if (apex(tetloop) == q[2]) break; + } + } + if (bondflag) { + // Create a new subface. + makeshellface(subfaces, &subloop); + setshvertices(subloop, p[0], p[1], p[2]); + // Create the point-to-subface map. + sptr = sencode(subloop); + for (j = 0; j < 3; j++) { + setpointtype(p[j], FACETVERTEX); // initial type. + setpoint2sh(p[j], sptr); + } + if (in->trifacemarkerlist != NULL) { + setshellmark(subloop, in->trifacemarkerlist[i]); + } + // Insert the subface into the mesh. + tsbond(tetloop, subloop); + fsymself(tetloop); + sesymself(subloop); + tsbond(tetloop, subloop); + } else { + if (!b->quiet) { + if (neighsh.sh == NULL) { + printf("Warning: Subface #%d [%d,%d,%d] is missing.\n", + i + in->firstnumber, pointmark(p[0]), pointmark(p[1]), + pointmark(p[2])); + } else { + printf("Warning: Ignore a dunplicated subface #%d [%d,%d,%d].\n", + i + in->firstnumber, pointmark(p[0]), pointmark(p[1]), + pointmark(p[2])); + } + } + } // if (bondflag) + } // if (marker > 0) + } // i + } // if (in->trifacelist) + + // Indentify subfaces from the mesh. + // Create subfaces for hull faces (if they're not subface yet) and + // interior faces which separate two different materials. + eextras = in->numberoftetrahedronattributes; + tetrahedrons->traversalinit(); + tetloop.tet = tetrahedrontraverse(); + while (tetloop.tet != (tetrahedron *) NULL) { + for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) { + tspivot(tetloop, neighsh); + if (neighsh.sh == NULL) { + bondflag = 0; + fsym(tetloop, checktet); + if (ishulltet(checktet)) { + // A hull face. + if (!b->convex) { + bondflag = 1; // Insert a hull subface. + } + } else { + if (eextras > 0) { + if (elemattribute(tetloop.tet, eextras - 1) != + elemattribute(checktet.tet, eextras - 1)) { + bondflag = 1; // Insert an interior interface. + } + } + } + if (bondflag) { + // Create a new subface. + makeshellface(subfaces, &subloop); + p[0] = org(tetloop); + p[1] = dest(tetloop); + p[2] = apex(tetloop); + setshvertices(subloop, p[0], p[1], p[2]); + // Create the point-to-subface map. + sptr = sencode(subloop); + for (j = 0; j < 3; j++) { + setpointtype(p[j], FACETVERTEX); // initial type. + setpoint2sh(p[j], sptr); + } + setshellmark(subloop, 0); // Default marker. + // Insert the subface into the mesh. + tsbond(tetloop, subloop); + sesymself(subloop); + tsbond(checktet, subloop); + } // if (bondflag) + } // if (neighsh.sh == NULL) + } + tetloop.tet = tetrahedrontraverse(); + } + + // Connect subfaces together. + subfaces->traversalinit(); + subloop.shver = 0; + subloop.sh = shellfacetraverse(subfaces); + while (subloop.sh != (shellface *) NULL) { + for (i = 0; i < 3; i++) { + spivot(subloop, neighsh); + if (neighsh.sh == NULL) { + // Form a subface ring by linking all subfaces at this edge. + // Traversing all faces of the tets at this edge. + stpivot(subloop, tetloop); + q[2] = apex(tetloop); + neighsh = subloop; + while (1) { + fnextself(tetloop); + tspivot(tetloop, nextsh); + if (nextsh.sh != NULL) { + // Link neighsh <= nextsh. + sbond1(neighsh, nextsh); + neighsh = nextsh; + } + if (apex(tetloop) == q[2]) { + assert(nextsh.sh == subloop.sh); // It's a ring. + break; + } + } // while (1) + } // if (neighsh.sh == NULL) + senextself(subloop); + } + subloop.sh = shellfacetraverse(subfaces); + } + + + // Segments will be introduced. + if (in->edgelist != NULL) { + // A .edge file is given. It may contain boundary edges. Insert them. + for (i = 0; i < in->numberofedges; i++) { + // Is it a segment? + if (in->edgemarkerlist != NULL) { + marker = in->edgemarkerlist[i]; + } else { + // Edge markers are not available. Assume all of them are segments. + marker = 1; + } + if (marker != 0) { + // Insert a segment. + idx = i * 2; + for (j = 0; j < 2; j++) { + p[j] = idx2verlist[in->edgelist[idx++]]; + } + // Make sure all vertices are in the mesh. Avoid crash. + for (j = 0; j < 2; j++) { + decode(point2tet(p[j]), checktet); + if (checktet.tet == NULL) break; + } + // Search the segment. + if ((j == 2) && getedge(p[0], p[1], &checktet)) { + // Create a new subface. + makeshellface(subsegs, &segloop); + setshvertices(segloop, p[0], p[1], NULL); + // Create the point-to-segment map. + sptr = sencode(segloop); + for (j = 0; j < 2; j++) { + setpointtype(p[j], RIDGEVERTEX); // initial type. + setpoint2sh(p[j], sptr); + } + if (in->edgemarkerlist != NULL) { + setshellmark(segloop, marker); + } + // Insert the segment into the mesh. + tetloop = checktet; + q[2] = apex(checktet); + subloop.sh = NULL; + while (1) { + tssbond1(tetloop, segloop); + tspivot(tetloop, subloop); + if (subloop.sh != NULL) { + ssbond1(subloop, segloop); + sbond1(segloop, subloop); + } + fnextself(tetloop); + if (apex(tetloop) == q[2]) break; + } // while (1) + // Remember an adjacent tet for this segment. + sstbond1(segloop, tetloop); + } else { + if (!b->quiet) { + printf("Warning: Segment #%d [%d,%d] is missing.\n", + i + in->firstnumber, pointmark(p[0]), pointmark(p[1])); + } + } + } // if (marker != 0) + } // i + } // if (in->edgelist) + + // Identify segments from the mesh. + // Create segments for non-manifold edges (which are shared by more + // than two subfaces), and for non-coplanar edges, i.e., two subfaces + // form an dihedral angle > 'b->facet_ang_tol' (degree). + angtol = b->facet_ang_tol / 180.0 * PI; + subfaces->traversalinit(); + subloop.shver = 0; + subloop.sh = shellfacetraverse(subfaces); + while (subloop.sh != (shellface *) NULL) { + for (i = 0; i < 3; i++) { + sspivot(subloop, segloop); + if (segloop.sh == NULL) { + // Check if this edge is a segment. + bondflag = 0; + // Counter the number of subfaces at this edge. + idx = 0; + nextsh = subloop; + while (1) { + idx++; + spivotself(nextsh); + if (nextsh.sh == subloop.sh) break; + } + if (idx != 2) { + // It's a non-manifold edge. Insert a segment. + p[0] = sorg(subloop); + p[1] = sdest(subloop); + bondflag = 1; + } else { + spivot(subloop, neighsh); + if (shellmark(subloop) != shellmark(neighsh)) { + // It's an interior interface. Insert a segment. + p[0] = sorg(subloop); + p[1] = sdest(subloop); + bondflag = 1; + } else { + if (!b->convex) { + // Check the dihedral angle formed by the two subfaces. + p[0] = sorg(subloop); + p[1] = sdest(subloop); + p[2] = sapex(subloop); + p[3] = sapex(neighsh); + ang = facedihedral(p[0], p[1], p[2], p[3]); + if (ang > PI) ang = 2 * PI - ang; + if (ang < angtol) { + bondflag = 1; + } + } + } + } + if (bondflag) { + // Create a new segment. + makeshellface(subsegs, &segloop); + setshvertices(segloop, p[0], p[1], NULL); + // Create the point-to-segment map. + sptr = sencode(segloop); + for (j = 0; j < 2; j++) { + setpointtype(p[j], RIDGEVERTEX); // initial type. + setpoint2sh(p[j], sptr); + } + setshellmark(segloop, 0); // Initially has no marker. + // Insert the subface into the mesh. + stpivot(subloop, tetloop); + q[2] = apex(tetloop); + while (1) { + tssbond1(tetloop, segloop); + tspivot(tetloop, neighsh); + if (neighsh.sh != NULL) { + ssbond1(neighsh, segloop); + } + fnextself(tetloop); + if (apex(tetloop) == q[2]) break; + } // while (1) + // Remember an adjacent tet for this segment. + sstbond1(segloop, tetloop); + sbond1(segloop, subloop); + } // if (bondflag) + } // if (neighsh.sh == NULL) + senextself(subloop); + } // i + subloop.sh = shellfacetraverse(subfaces); + } + + // Remember the number of input segments. + insegments = subsegs->items; + + if (!b->nobisect || checkconstraints) { + // Mark Steiner points on segments and facets. + // - all vertices which remaining type FEACTVERTEX become + // Steiner points in facets (= FREEFACERVERTEX). + // - vertices on segment need to be checked. + face* segperverlist; + int* idx2seglist; + face parentseg, nextseg; + verttype vt; + REAL area, len, l1, l2; + int fmarker; + + makepoint2submap(subsegs, idx2seglist, segperverlist); + + points->traversalinit(); + point ptloop = pointtraverse(); + while (ptloop != NULL) { + vt = pointtype(ptloop); + if (vt == VOLVERTEX) { + setpointtype(ptloop, FREEVOLVERTEX); + st_volref_count++; + } else if (vt == FACETVERTEX) { + setpointtype(ptloop, FREEFACETVERTEX); + st_facref_count++; + } else if (vt == RIDGEVERTEX) { + idx = pointmark(ptloop) - in->firstnumber; + if ((idx2seglist[idx + 1] - idx2seglist[idx]) == 2) { + i = idx2seglist[idx]; + parentseg = segperverlist[i]; + nextseg = segperverlist[i + 1]; + sesymself(nextseg); + p[0] = sorg(nextseg); + p[1] = sdest(parentseg); + // Check if three points p[0], ptloop, p[2] are (nearly) collinear. + len = distance(p[0], p[1]); + l1 = distance(p[0], ptloop); + l2 = distance(ptloop, p[1]); + if (((l1 + l2 - len) / len) < b->epsilon) { + // They are (nearly) collinear. + setpointtype(ptloop, FREESEGVERTEX); + // Connect nextseg and parentseg together at ptloop. + senextself(nextseg); + senext2self(parentseg); + sbond(nextseg, parentseg); + st_segref_count++; + } + } + } + ptloop = pointtraverse(); + } + + // Are there area constraints? + if (b->quality && (in->facetconstraintlist != (REAL *) NULL)) { + // Set maximum area constraints on facets. + for (i = 0; i < in->numberoffacetconstraints; i++) { + fmarker = (int) in->facetconstraintlist[i * 2]; + area = in->facetconstraintlist[i * 2 + 1]; + subfaces->traversalinit(); + subloop.sh = shellfacetraverse(subfaces); + while (subloop.sh != NULL) { + if (shellmark(subloop) == fmarker) { + setareabound(subloop, area); + } + subloop.sh = shellfacetraverse(subfaces); + } + } + } + + // Are there length constraints? + if (b->quality && (in->segmentconstraintlist != (REAL *) NULL)) { + // Set maximum length constraints on segments. + int e1, e2; + for (i = 0; i < in->numberofsegmentconstraints; i++) { + e1 = (int) in->segmentconstraintlist[i * 3]; + e2 = (int) in->segmentconstraintlist[i * 3 + 1]; + len = in->segmentconstraintlist[i * 3 + 2]; + // Search for edge [e1, e2]. + idx = e1 - in->firstnumber; + for (j = idx2seglist[idx]; j < idx2seglist[idx + 1]; j++) { + parentseg = segperverlist[j]; + if (pointmark(sdest(parentseg)) == e2) { + setareabound(parentseg, len); + break; + } + } + } + } + + delete [] idx2seglist; + delete [] segperverlist; + } + + + // Set global flags. + checksubsegflag = 1; + checksubfaceflag = 1; + + delete [] idx2verlist; + delete [] ver2tetarray; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// scoutpoint() Search a point in mesh. // +// // +// This function searches the point in a mesh whose domain may be not convex.// +// In case of a convex domain, the locate() function is sufficient. // +// // +// If 'randflag' is used, randomly select a start searching tet. Otherwise, // +// start searching directly from 'searchtet'. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::scoutpoint(point searchpt, triface *searchtet, int randflag) +{ + point pa, pb, pc, pd; + enum locateresult loc = OUTSIDE; + REAL vol, ori1, ori2 = 0, ori3 = 0, ori4 = 0; + int t1ver; + + + // Randomly select a good starting tet. + if (randflag) { + randomsample(searchpt, searchtet); + } else { + if (searchtet->tet == NULL) { + *searchtet = recenttet; + } + } + loc = locate(searchpt, searchtet); + + if (loc == OUTSIDE) { + if (b->convex) { // -c option + // The point lies outside of the convex hull. + return (int) loc; + } + // Test if it lies nearly on the hull face. + // Reuse vol, ori1. + pa = org(*searchtet); + pb = dest(*searchtet); + pc = apex(*searchtet); + vol = triarea(pa, pb, pc); + ori1 = orient3dfast(pa, pb, pc, searchpt); + if (fabs(ori1 / vol) < b->epsilon) { + loc = ONFACE; // On face (or on edge, or on vertex). + fsymself(*searchtet); + } + } + + if (loc != OUTSIDE) { + // Round the result of location. + pa = org(*searchtet); + pb = dest(*searchtet); + pc = apex(*searchtet); + pd = oppo(*searchtet); + vol = orient3dfast(pa, pb, pc, pd); + ori1 = orient3dfast(pa, pb, pc, searchpt); + ori2 = orient3dfast(pb, pa, pd, searchpt); + ori3 = orient3dfast(pc, pb, pd, searchpt); + ori4 = orient3dfast(pa, pc, pd, searchpt); + if (fabs(ori1 / vol) < b->epsilon) ori1 = 0; + if (fabs(ori2 / vol) < b->epsilon) ori2 = 0; + if (fabs(ori3 / vol) < b->epsilon) ori3 = 0; + if (fabs(ori4 / vol) < b->epsilon) ori4 = 0; + } else { // if (loc == OUTSIDE) { + // Do a brute force search for the point (with rounding). + tetrahedrons->traversalinit(); + searchtet->tet = tetrahedrontraverse(); + while (searchtet->tet != NULL) { + pa = org(*searchtet); + pb = dest(*searchtet); + pc = apex(*searchtet); + pd = oppo(*searchtet); + + vol = orient3dfast(pa, pb, pc, pd); + if (vol < 0) { + ori1 = orient3dfast(pa, pb, pc, searchpt); + if (fabs(ori1 / vol) < b->epsilon) ori1 = 0; // Rounding. + if (ori1 <= 0) { + ori2 = orient3dfast(pb, pa, pd, searchpt); + if (fabs(ori2 / vol) < b->epsilon) ori2 = 0; + if (ori2 <= 0) { + ori3 = orient3dfast(pc, pb, pd, searchpt); + if (fabs(ori3 / vol) < b->epsilon) ori3 = 0; + if (ori3 <= 0) { + ori4 = orient3dfast(pa, pc, pd, searchpt); + if (fabs(ori4 / vol) < b->epsilon) ori4 = 0; + if (ori4 <= 0) { + // Found the tet. Return its location. + break; + } // ori4 + } // ori3 + } // ori2 + } // ori1 + } + + searchtet->tet = tetrahedrontraverse(); + } // while (searchtet->tet != NULL) + nonregularcount++; // Re-use this counter. + } + + if (searchtet->tet != NULL) { + // Return the point location. + if (ori1 == 0) { // on face [a,b,c] + if (ori2 == 0) { // on edge [a,b]. + if (ori3 == 0) { // on vertex [b]. + assert(ori4 != 0); + enextself(*searchtet); // [b,c,a,d] + loc = ONVERTEX; + } else { + if (ori4 == 0) { // on vertex [a] + loc = ONVERTEX; // [a,b,c,d] + } else { + loc = ONEDGE; // [a,b,c,d] + } + } + } else { // ori2 != 0 + if (ori3 == 0) { // on edge [b,c] + if (ori4 == 0) { // on vertex [c] + eprevself(*searchtet); // [c,a,b,d] + loc = ONVERTEX; + } else { + enextself(*searchtet); // [b,c,a,d] + loc = ONEDGE; + } + } else { // ori3 != 0 + if (ori4 == 0) { // on edge [c,a] + eprevself(*searchtet); // [c,a,b,d] + loc = ONEDGE; + } else { + loc = ONFACE; + } + } + } + } else { // ori1 != 0 + if (ori2 == 0) { // on face [b,a,d] + esymself(*searchtet); // [b,a,d,c] + if (ori3 == 0) { // on edge [b,d] + eprevself(*searchtet); // [d,b,a,c] + if (ori4 == 0) { // on vertex [d] + loc = ONVERTEX; + } else { + loc = ONEDGE; + } + } else { // ori3 != 0 + if (ori4 == 0) { // on edge [a,d] + enextself(*searchtet); // [a,d,b,c] + loc = ONEDGE; + } else { + loc = ONFACE; + } + } + } else { // ori2 != 0 + if (ori3 == 0) { // on face [c,b,d] + enextself(*searchtet); + esymself(*searchtet); + if (ori4 == 0) { // on edge [c,d] + eprevself(*searchtet); + loc = ONEDGE; + } else { + loc = ONFACE; + } + } else { + if (ori4 == 0) { // on face [a,c,d] + eprevself(*searchtet); + esymself(*searchtet); + loc = ONFACE; + } else { // inside tet [a,b,c,d] + loc = INTETRAHEDRON; + } // ori4 + } // ori3 + } // ori2 + } // ori1 + } else { + loc = OUTSIDE; + } + + return (int) loc; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// getpointmeshsize() Interpolate the mesh size at given point. // +// // +// 'iloc' indicates the location of the point w.r.t. 'searchtet'. The size // +// is obtained by linear interpolation on the vertices of the tet. // +// // +/////////////////////////////////////////////////////////////////////////////// + +REAL tetgenmesh::getpointmeshsize(point searchpt, triface *searchtet, int iloc) +{ + point *pts, pa, pb, pc; + REAL volume, vol[4], wei[4]; + REAL size; + int i; + + size = 0; + + if (iloc == (int) INTETRAHEDRON) { + pts = (point *) &(searchtet->tet[4]); + assert(pts[3] != dummypoint); + // Only do interpolation if all vertices have non-zero sizes. + if ((pts[0][pointmtrindex] > 0) && (pts[1][pointmtrindex] > 0) && + (pts[2][pointmtrindex] > 0) && (pts[3][pointmtrindex] > 0)) { + // P1 interpolation. + volume = orient3dfast(pts[0], pts[1], pts[2], pts[3]); + vol[0] = orient3dfast(searchpt, pts[1], pts[2], pts[3]); + vol[1] = orient3dfast(pts[0], searchpt, pts[2], pts[3]); + vol[2] = orient3dfast(pts[0], pts[1], searchpt, pts[3]); + vol[3] = orient3dfast(pts[0], pts[1], pts[2], searchpt); + for (i = 0; i < 4; i++) { + wei[i] = fabs(vol[i] / volume); + size += (wei[i] * pts[i][pointmtrindex]); + } + } + } else if (iloc == (int) ONFACE) { + pa = org(*searchtet); + pb = dest(*searchtet); + pc = apex(*searchtet); + if ((pa[pointmtrindex] > 0) && (pb[pointmtrindex] > 0) && + (pc[pointmtrindex] > 0)) { + volume = triarea(pa, pb, pc); + vol[0] = triarea(searchpt, pb, pc); + vol[1] = triarea(pa, searchpt, pc); + vol[2] = triarea(pa, pb, searchpt); + size = (vol[0] / volume) * pa[pointmtrindex] + + (vol[1] / volume) * pb[pointmtrindex] + + (vol[2] / volume) * pc[pointmtrindex]; + } + } else if (iloc == (int) ONEDGE) { + pa = org(*searchtet); + pb = dest(*searchtet); + if ((pa[pointmtrindex] > 0) && (pb[pointmtrindex] > 0)) { + volume = distance(pa, pb); + vol[0] = distance(searchpt, pb); + vol[1] = distance(pa, searchpt); + size = (vol[0] / volume) * pa[pointmtrindex] + + (vol[1] / volume) * pb[pointmtrindex]; + } + } else if (iloc == (int) ONVERTEX) { + pa = org(*searchtet); + if (pa[pointmtrindex] > 0) { + size = pa[pointmtrindex]; + } + } + + return size; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// interpolatemeshsize() Interpolate the mesh size from a background mesh // +// (source) to the current mesh (destination). // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::interpolatemeshsize() +{ + triface searchtet; + point ploop; + REAL minval = 0.0, maxval = 0.0; + int iloc; + int count; + + if (!b->quiet) { + printf("Interpolating mesh size ...\n"); + } + + long bak_nonregularcount = nonregularcount; + nonregularcount = 0l; // Count the number of (slow) global searches. + long baksmaples = bgm->samples; + bgm->samples = 3l; + count = 0; // Count the number of interpolated points. + + // Interpolate sizes for all points in the current mesh. + points->traversalinit(); + ploop = pointtraverse(); + while (ploop != NULL) { + // Search a tet in bgm which containing this point. + searchtet.tet = NULL; + iloc = bgm->scoutpoint(ploop, &searchtet, 1); // randflag = 1 + if (iloc != (int) OUTSIDE) { + // Interpolate the mesh size. + ploop[pointmtrindex] = bgm->getpointmeshsize(ploop, &searchtet, iloc); + setpoint2bgmtet(ploop, bgm->encode(searchtet)); + if (count == 0) { + // This is the first interpolated point. + minval = maxval = ploop[pointmtrindex]; + } else { + if (ploop[pointmtrindex] < minval) { + minval = ploop[pointmtrindex]; + } + if (ploop[pointmtrindex] > maxval) { + maxval = ploop[pointmtrindex]; + } + } + count++; + } else { + if (!b->quiet) { + printf("Warnning: Failed to locate point %d in source mesh.\n", + pointmark(ploop)); + } + } + ploop = pointtraverse(); + } + + if (b->verbose) { + printf(" Interoplated %d points.\n", count); + if (nonregularcount > 0l) { + printf(" Performed %ld brute-force searches.\n", nonregularcount); + } + printf(" Size rangle [%.17g, %.17g].\n", minval, maxval); + } + + bgm->samples = baksmaples; + nonregularcount = bak_nonregularcount; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// insertconstrainedpoints() Insert a list of points into the mesh. // +// // +// Assumption: The bounding box of the insert point set should be no larger // +// than the bounding box of the mesh. (Required by point sorting). // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::insertconstrainedpoints(point *insertarray, int arylen, + int rejflag) +{ + triface searchtet, spintet; + face splitsh; + face splitseg; + insertvertexflags ivf; + flipconstraints fc; + int randflag = 0; + int t1ver; + int i; + + if (b->verbose) { + printf(" Inserting %d constrained points\n", arylen); + } + + if (b->no_sort) { // -b/1 option. + if (b->verbose) { + printf(" Using the input order.\n"); + } + } else { + if (b->verbose) { + printf(" Permuting vertices.\n"); + } + point swappoint; + int randindex; + srand(arylen); + for (i = 0; i < arylen; i++) { + randindex = rand() % (i + 1); + swappoint = insertarray[i]; + insertarray[i] = insertarray[randindex]; + insertarray[randindex] = swappoint; + } + if (b->brio_hilbert) { // -b1 option + if (b->verbose) { + printf(" Sorting vertices.\n"); + } + hilbert_init(in->mesh_dim); + int ngroup = 0; + brio_multiscale_sort(insertarray, arylen, b->brio_threshold, + b->brio_ratio, &ngroup); + } else { // -b0 option. + randflag = 1; + } // if (!b->brio_hilbert) + } // if (!b->no_sort) + + long bak_nonregularcount = nonregularcount; + nonregularcount = 0l; + long baksmaples = samples; + samples = 3l; // Use at least 3 samples. Updated in randomsample(). + + long bak_seg_count = st_segref_count; + long bak_fac_count = st_facref_count; + long bak_vol_count = st_volref_count; + + // Initialize the insertion parameters. + if (b->incrflip) { // -l option + // Use incremental flip algorithm. + ivf.bowywat = 0; + ivf.lawson = 1; + ivf.validflag = 0; // No need to validate the cavity. + fc.enqflag = 2; + } else { + // Use Bowyer-Watson algorithm. + ivf.bowywat = 1; + ivf.lawson = 0; + ivf.validflag = 1; // Validate the B-W cavity. + } + ivf.rejflag = rejflag; + ivf.chkencflag = 0; + ivf.sloc = (int) INSTAR; + ivf.sbowywat = 3; + ivf.splitbdflag = 1; + ivf.respectbdflag = 1; + ivf.assignmeshsize = b->metric; + + encseglist = new arraypool(sizeof(face), 8); + encshlist = new arraypool(sizeof(badface), 8); + + // Insert the points. + for (i = 0; i < arylen; i++) { + // Find the location of the inserted point. + // Do not use 'recenttet', since the mesh may be non-convex. + searchtet.tet = NULL; + ivf.iloc = scoutpoint(insertarray[i], &searchtet, randflag); + + // Decide the right type for this point. + setpointtype(insertarray[i], FREEVOLVERTEX); // Default. + splitsh.sh = NULL; + splitseg.sh = NULL; + if (ivf.iloc == (int) ONEDGE) { + if (issubseg(searchtet)) { + tsspivot1(searchtet, splitseg); + setpointtype(insertarray[i], FREESEGVERTEX); + //ivf.rejflag = 0; + } else { + // Check if it is a subface edge. + spintet = searchtet; + while (1) { + if (issubface(spintet)) { + tspivot(spintet, splitsh); + setpointtype(insertarray[i], FREEFACETVERTEX); + //ivf.rejflag |= 1; + break; + } + fnextself(spintet); + if (spintet.tet == searchtet.tet) break; + } + } + } else if (ivf.iloc == (int) ONFACE) { + if (issubface(searchtet)) { + tspivot(searchtet, splitsh); + setpointtype(insertarray[i], FREEFACETVERTEX); + //ivf.rejflag |= 1; + } + } + + // Now insert the point. + if (insertpoint(insertarray[i], &searchtet, &splitsh, &splitseg, &ivf)) { + if (flipstack != NULL) { + // There are queued faces. Use flips to recover Delaunayness. + lawsonflip3d(&fc); + // There may be unflippable edges. Ignore them. + unflipqueue->restart(); + } + // Update the Steiner counters. + if (pointtype(insertarray[i]) == FREESEGVERTEX) { + st_segref_count++; + } else if (pointtype(insertarray[i]) == FREEFACETVERTEX) { + st_facref_count++; + } else { + st_volref_count++; + } + } else { + // Point is not inserted. + //pointdealloc(insertarray[i]); + setpointtype(insertarray[i], UNUSEDVERTEX); + unuverts++; + encseglist->restart(); + encshlist->restart(); + } + } // i + + delete encseglist; + delete encshlist; + + if (b->verbose) { + printf(" Inserted %ld (%ld, %ld, %ld) vertices.\n", + st_segref_count + st_facref_count + st_volref_count - + (bak_seg_count + bak_fac_count + bak_vol_count), + st_segref_count - bak_seg_count, st_facref_count - bak_fac_count, + st_volref_count - bak_vol_count); + if (nonregularcount > 0l) { + printf(" Performed %ld brute-force searches.\n", nonregularcount); + } + } + + nonregularcount = bak_nonregularcount; + samples = baksmaples; +} + +void tetgenmesh::insertconstrainedpoints(tetgenio *addio) +{ + point *insertarray, newpt; + REAL x, y, z, w; + int index, attribindex, mtrindex; + int arylen, i, j; + + if (!b->quiet) { + printf("Inserting constrained points ...\n"); + } + + insertarray = new point[addio->numberofpoints]; + arylen = 0; + index = 0; + attribindex = 0; + mtrindex = 0; + + for (i = 0; i < addio->numberofpoints; i++) { + x = addio->pointlist[index++]; + y = addio->pointlist[index++]; + z = addio->pointlist[index++]; + // Test if this point lies inside the bounding box. + if ((x < xmin) || (x > xmax) || (y < ymin) || (y > ymax) || + (z < zmin) || (z > zmax)) { + if (b->verbose) { + printf("Warning: Point #%d lies outside the bounding box. Ignored\n", + i + in->firstnumber); + } + continue; + } + makepoint(&newpt, UNUSEDVERTEX); + newpt[0] = x; + newpt[1] = y; + newpt[2] = z; + // Read the point attributes. (Including point weights.) + for (j = 0; j < addio->numberofpointattributes; j++) { + newpt[3 + j] = addio->pointattributelist[attribindex++]; + } + // Read the point metric tensor. + for (j = 0; j < addio->numberofpointmtrs; j++) { + newpt[pointmtrindex + j] = addio->pointmtrlist[mtrindex++]; + } + if (b->weighted) { // -w option + if (addio->numberofpointattributes > 0) { + // The first point attribute is its weight. + w = newpt[3]; + } else { + // No given weight available. Default choose the maximum + // absolute value among its coordinates. + w = fabs(x); + if (w < fabs(y)) w = fabs(y); + if (w < fabs(z)) w = fabs(z); + } + if (b->weighted_param == 0) { + newpt[3] = x * x + y * y + z * z - w; // Weighted DT. + } else { // -w1 option + newpt[3] = w; // Regular tetrahedralization. + } + } + insertarray[arylen] = newpt; + arylen++; + } // i + + // Insert the points. + int rejflag = 0; // Do not check encroachment. + if (b->metric) { // -m option. + rejflag |= 4; // Reject it if it lies in some protecting balls. + } + + insertconstrainedpoints(insertarray, arylen, rejflag); + + delete [] insertarray; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// meshcoarsening() Deleting (selected) vertices. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::collectremovepoints(arraypool *remptlist) +{ + point ptloop, *parypt; + verttype vt; + + // If a mesh sizing function is given. Collect vertices whose mesh size + // is greater than its smallest edge length. + if (b->metric) { // -m option + REAL len, smlen; + int i; + points->traversalinit(); + ptloop = pointtraverse(); + while (ptloop != NULL) { + if (ptloop[pointmtrindex] > 0) { + // Get the smallest edge length at this vertex. + getvertexstar(1, ptloop, cavetetlist, cavetetvertlist, NULL); + parypt = (point *) fastlookup(cavetetvertlist, 0); + smlen = distance(ptloop, *parypt); + for (i = 1; i < cavetetvertlist->objects; i++) { + parypt = (point *) fastlookup(cavetetvertlist, i); + len = distance(ptloop, *parypt); + if (len < smlen) { + smlen = len; + } + } + cavetetvertlist->restart(); + cavetetlist->restart(); + if (smlen < ptloop[pointmtrindex]) { + pinfect(ptloop); + remptlist->newindex((void **) &parypt); + *parypt = ptloop; + } + } + ptloop = pointtraverse(); + } + if (b->verbose > 1) { + printf(" Coarsen %ld oversized points.\n", remptlist->objects); + } + } + + // If 'in->pointmarkerlist' exists, Collect vertices with markers '-1'. + if (in->pointmarkerlist != NULL) { + long bak_count = remptlist->objects; + points->traversalinit(); + ptloop = pointtraverse(); + int index = 0; + while (ptloop != NULL) { + if (index < in->numberofpoints) { + if (in->pointmarkerlist[index] == -1) { + pinfect(ptloop); + remptlist->newindex((void **) &parypt); + *parypt = ptloop; + } + } else { + // Remaining are not input points. Stop here. + break; + } + index++; + ptloop = pointtraverse(); + } + if (b->verbose > 1) { + printf(" Coarsen %ld marked points.\n", remptlist->objects - bak_count); + } + } // if (in->pointmarkerlist != NULL) + + if (b->coarsen_param > 0) { // -R1/# + // Remove a coarsen_percent number of interior points. + assert((b->coarsen_percent > 0) && (b->coarsen_percent <= 1.0)); + if (b->verbose > 1) { + printf(" Coarsen %g percent of interior points.\n", + b->coarsen_percent * 100.0); + } + arraypool *intptlist = new arraypool(sizeof(point *), 10); + // Count the total number of interior points. + points->traversalinit(); + ptloop = pointtraverse(); + while (ptloop != NULL) { + vt = pointtype(ptloop); + if ((vt == VOLVERTEX) || (vt == FREEVOLVERTEX) || + (vt == FREEFACETVERTEX) || (vt == FREESEGVERTEX)) { + intptlist->newindex((void **) &parypt); + *parypt = ptloop; + } + ptloop = pointtraverse(); + } + if (intptlist->objects > 0l) { + // Sort the list of points randomly. + point *parypt_i, swappt; + int randindex, i; + srand(intptlist->objects); + for (i = 0; i < intptlist->objects; i++) { + randindex = rand() % (i + 1); // randomnation(i + 1); + parypt_i = (point *) fastlookup(intptlist, i); + parypt = (point *) fastlookup(intptlist, randindex); + // Swap this two points. + swappt = *parypt_i; + *parypt_i = *parypt; + *parypt = swappt; + } + int remcount = (int) ((REAL) intptlist->objects * b->coarsen_percent); + // Return the first remcount points. + for (i = 0; i < remcount; i++) { + parypt_i = (point *) fastlookup(intptlist, i); + if (!pinfected(*parypt_i)) { + pinfected(*parypt_i); + remptlist->newindex((void **) &parypt); + *parypt = *parypt_i; + } + } + } + delete intptlist; + } + + // Unmark all collected vertices. + for (int i = 0; i < remptlist->objects; i++) { + parypt = (point *) fastlookup(remptlist, i); + puninfect(*parypt); + } +} + +void tetgenmesh::meshcoarsening() +{ + arraypool *remptlist; + + if (!b->quiet) { + printf("Mesh coarsening ...\n"); + } + + // Collect the set of points to be removed + remptlist = new arraypool(sizeof(point *), 10); + collectremovepoints(remptlist); + + if (remptlist->objects == 0l) { + delete remptlist; + return; + } + + if (b->verbose) { + if (remptlist->objects > 0l) { + printf(" Removing %ld points...\n", remptlist->objects); + } + } + + point *parypt, *plastpt; + long ms = remptlist->objects; + int nit = 0; + int bak_fliplinklevel = b->fliplinklevel; + b->fliplinklevel = -1; + autofliplinklevel = 1; // Init value. + int i; + + while (1) { + + if (b->verbose > 1) { + printf(" Removing points [%s level = %2d] #: %ld.\n", + (b->fliplinklevel > 0) ? "fixed" : "auto", + (b->fliplinklevel > 0) ? b->fliplinklevel : autofliplinklevel, + remptlist->objects); + } + + // Remove the list of points. + for (i = 0; i < remptlist->objects; i++) { + parypt = (point *) fastlookup(remptlist, i); + assert(pointtype(*parypt) != UNUSEDVERTEX); + if (removevertexbyflips(*parypt)) { + // Move the last entry to the current place. + plastpt = (point *) fastlookup(remptlist, remptlist->objects - 1); + *parypt = *plastpt; + remptlist->objects--; + i--; + } + } + + if (remptlist->objects > 0l) { + if (b->fliplinklevel >= 0) { + break; // We have tried all levels. + } + if (remptlist->objects == ms) { + nit++; + if (nit >= 3) { + // Do the last round with unbounded flip link level. + b->fliplinklevel = 100000; + } + } else { + ms = remptlist->objects; + if (nit > 0) { + nit--; + } + } + autofliplinklevel+=b->fliplinklevelinc; + } else { + // All points are removed. + break; + } + } // while (1) + + if (remptlist->objects > 0l) { + if (b->verbose) { + printf(" %ld points are not removed !\n", remptlist->objects); + } + } + + b->fliplinklevel = bak_fliplinklevel; + delete remptlist; +} + +//// //// +//// //// +//// reconstruct_cxx ////////////////////////////////////////////////////////// + +//// refine_cxx /////////////////////////////////////////////////////////////// +//// //// +//// //// + +/////////////////////////////////////////////////////////////////////////////// +// // +// makefacetverticesmap() Create a map from facet to its vertices. // +// // +// All facets will be indexed (starting from 0). The map is saved in two // +// global arrays: 'idx2facetlist' and 'facetverticeslist'. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::makefacetverticesmap() +{ + arraypool *facetvertexlist, *vertlist, **paryvertlist; + face subloop, neighsh, *parysh, *parysh1; + point pa, *ppt, *parypt; + verttype vt; + int facetindex, totalvertices; + int i, j, k; + + if (b->verbose) { + printf(" Creating the facet vertices map.\n"); + } + + facetvertexlist = new arraypool(sizeof(arraypool *), 10); + facetindex = totalvertices = 0; + + subfaces->traversalinit(); + subloop.sh = shellfacetraverse(subfaces); + while (subloop.sh != NULL) { + if (!sinfected(subloop)) { + // A new facet. Create its vertices list. + vertlist = new arraypool(sizeof(point *), 8); + ppt = (point *) &(subloop.sh[3]); + for (k = 0; k < 3; k++) { + vt = pointtype(ppt[k]); + if ((vt != FREESEGVERTEX) && (vt != FREEFACETVERTEX)) { + pinfect(ppt[k]); + vertlist->newindex((void **) &parypt); + *parypt = ppt[k]; + } + } + sinfect(subloop); + caveshlist->newindex((void **) &parysh); + *parysh = subloop; + for (i = 0; i < caveshlist->objects; i++) { + parysh = (face *) fastlookup(caveshlist, i); + setfacetindex(*parysh, facetindex); + for (j = 0; j < 3; j++) { + if (!isshsubseg(*parysh)) { + spivot(*parysh, neighsh); + assert(neighsh.sh != NULL); + if (!sinfected(neighsh)) { + pa = sapex(neighsh); + if (!pinfected(pa)) { + vt = pointtype(pa); + if ((vt != FREESEGVERTEX) && (vt != FREEFACETVERTEX)) { + pinfect(pa); + vertlist->newindex((void **) &parypt); + *parypt = pa; + } + } + sinfect(neighsh); + caveshlist->newindex((void **) &parysh1); + *parysh1 = neighsh; + } + } + senextself(*parysh); + } + } // i + totalvertices += (int) vertlist->objects; + // Uninfect facet vertices. + for (k = 0; k < vertlist->objects; k++) { + parypt = (point *) fastlookup(vertlist, k); + puninfect(*parypt); + } + caveshlist->restart(); + // Save this vertex list. + facetvertexlist->newindex((void **) &paryvertlist); + *paryvertlist = vertlist; + facetindex++; + } + subloop.sh = shellfacetraverse(subfaces); + } + + // All subfaces are infected. Uninfect them. + subfaces->traversalinit(); + subloop.sh = shellfacetraverse(subfaces); + while (subloop.sh != NULL) { + assert(sinfected(subloop)); + suninfect(subloop); + subloop.sh = shellfacetraverse(subfaces); + } + + if (b->verbose) { + printf(" Found %ld facets.\n", facetvertexlist->objects); + } + + idx2facetlist = new int[facetindex + 1]; + facetverticeslist = new point[totalvertices]; + + totalworkmemory += ((facetindex + 1) * sizeof(int) + + totalvertices * sizeof(point *)); + + idx2facetlist[0] = 0; + for (i = 0, k = 0; i < facetindex; i++) { + paryvertlist = (arraypool **) fastlookup(facetvertexlist, i); + vertlist = *paryvertlist; + idx2facetlist[i + 1] = (idx2facetlist[i] + (int) vertlist->objects); + for (j = 0; j < vertlist->objects; j++) { + parypt = (point *) fastlookup(vertlist, j); + facetverticeslist[k] = *parypt; + k++; + } + } + assert(k == totalvertices); + + // Free the lists. + for (i = 0; i < facetvertexlist->objects; i++) { + paryvertlist = (arraypool **) fastlookup(facetvertexlist, i); + vertlist = *paryvertlist; + delete vertlist; + } + delete facetvertexlist; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// Check whether two segments, or a segment and a facet, or two facets are // +// adjacent to each other. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::segsegadjacent(face *seg1, face *seg2) +{ + int segidx1 = getfacetindex(*seg1); + int segidx2 = getfacetindex(*seg2); + + if (segidx1 == segidx2) return 0; + + point pa1 = segmentendpointslist[segidx1 * 2]; + point pb1 = segmentendpointslist[segidx1 * 2 + 1]; + point pa2 = segmentendpointslist[segidx2 * 2]; + point pb2 = segmentendpointslist[segidx2 * 2 + 1]; + + if ((pa1 == pa2) || (pa1 == pb2) || (pb1 == pa2) || (pb1 == pb2)) { + return 1; + } + return 0; +} + +int tetgenmesh::segfacetadjacent(face *subseg, face *subsh) +{ + int segidx = getfacetindex(*subseg); + point pa = segmentendpointslist[segidx * 2]; + point pb = segmentendpointslist[segidx * 2 + 1]; + + pinfect(pa); + pinfect(pb); + + int fidx = getfacetindex(*subsh); + int count = 0, i; + + for (i = idx2facetlist[fidx]; i < idx2facetlist[fidx+1]; i++) { + if (pinfected(facetverticeslist[i])) count++; + } + + puninfect(pa); + puninfect(pb); + + return count == 1; +} + +int tetgenmesh::facetfacetadjacent(face *subsh1, face *subsh2) +{ + int count = 0, i; + + int fidx1 = getfacetindex(*subsh1); + int fidx2 = getfacetindex(*subsh2); + + if (fidx1 == fidx2) return 0; + + for (i = idx2facetlist[fidx1]; i < idx2facetlist[fidx1+1]; i++) { + pinfect(facetverticeslist[i]); + } + + for (i = idx2facetlist[fidx2]; i < idx2facetlist[fidx2+1]; i++) { + if (pinfected(facetverticeslist[i])) count++; + } + + // Uninfect the vertices. + for (i = idx2facetlist[fidx1]; i < idx2facetlist[fidx1+1]; i++) { + puninfect(facetverticeslist[i]); + } + + return count > 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// checkseg4encroach() Check if an edge is encroached upon by a point. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::checkseg4encroach(point pa, point pb, point checkpt) +{ + // Check if the point lies inside the diametrical sphere of this seg. + REAL v1[3], v2[3]; + + v1[0] = pa[0] - checkpt[0]; + v1[1] = pa[1] - checkpt[1]; + v1[2] = pa[2] - checkpt[2]; + v2[0] = pb[0] - checkpt[0]; + v2[1] = pb[1] - checkpt[1]; + v2[2] = pb[2] - checkpt[2]; + + if (dot(v1, v2) < 0) { + // Inside. + if (b->metric) { // -m option. + if ((pa[pointmtrindex] > 0) && (pb[pointmtrindex] > 0)) { + // The projection of 'checkpt' lies inside the segment [a,b]. + REAL prjpt[3], u, v, t; + projpt2edge(checkpt, pa, pb, prjpt); + // Interoplate the mesh size at the location 'prjpt'. + u = distance(pa, pb); + v = distance(pa, prjpt); + t = v / u; + // 'u' is the mesh size at 'prjpt' + u = pa[pointmtrindex] + t * (pb[pointmtrindex] - pa[pointmtrindex]); + v = distance(checkpt, prjpt); + if (v < u) { + return 1; // Encroached prot-ball! + } + } else { + return 1; // NO protecting ball. Encroached. + } + } else { + return 1; // Inside! Encroached. + } + } + + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// checkseg4split() Check if we need to split a segment. // +// // +// A segment needs to be split if it is in the following case: // +// (1) It is encroached by an existing vertex. // +// (2) It has bad quality (too long). // +// (3) Its length is larger than the mesh sizes at its endpoints. // +// // +// Return 1 if it needs to be split, otherwise, return 0. 'pencpt' returns // +// an encroaching point if there exists. 'qflag' returns '1' if the segment // +// has a length larger than the desired edge length. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::checkseg4split(face *chkseg, point& encpt, int& qflag) +{ + REAL ccent[3], len, r; + int i; + + point forg = sorg(*chkseg); + point fdest = sdest(*chkseg); + + // Initialize the return values. + encpt = NULL; + qflag = 0; + + len = distance(forg, fdest); + r = 0.5 * len; + for (i = 0; i < 3; i++) { + ccent[i] = 0.5 * (forg[i] + fdest[i]); + } + + // First check its quality. + if (checkconstraints && (areabound(*chkseg) > 0.0)) { + if (len > areabound(*chkseg)) { + qflag = 1; + return 1; + } + } + + if (b->fixedvolume) { + if ((len * len * len) > b->maxvolume) { + qflag = 1; + return 1; + } + } + + if (b->metric) { // -m option. Check mesh size. + // Check if the ccent lies outside one of the prot.balls at vertices. + if (((forg[pointmtrindex] > 0) && (r > forg[pointmtrindex])) || + ((fdest[pointmtrindex]) > 0 && (r > fdest[pointmtrindex]))) { + qflag = 1; // Enforce mesh size. + return 1; + } + } + + + // Second check if it is encroached. + // Comment: There may exist more than one encroaching points of this segment. + // The 'encpt' returns the one which is closet to it. + triface searchtet, spintet; + point eapex; + REAL d, diff, smdist = 0; + int t1ver; + + sstpivot1(*chkseg, searchtet); + spintet = searchtet; + while (1) { + eapex = apex(spintet); + if (eapex != dummypoint) { + d = distance(ccent, eapex); + diff = d - r; + if (fabs(diff) / r < b->epsilon) diff = 0.0; // Rounding. + if (diff < 0) { + // This segment is encroached by eapex. + if (useinsertradius) { + if (encpt == NULL) { + encpt = eapex; + smdist = d; + } else { + // Choose the closet encroaching point. + if (d < smdist) { + encpt = eapex; + smdist = d; + } + } + } else { + encpt = eapex; + break; + } + } + } + fnextself(spintet); + if (spintet.tet == searchtet.tet) break; + } // while (1) + + if (encpt != NULL) { + return 1; + } + + return 0; // No need to split it. +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// splitsegment() Split a segment. // +// // +// The segment 'splitseg' is intended to be split. It will be split if it // +// is in one of the following cases: // +// (1) It is encroached by an existing vertex 'encpt != NULL'; or // +// (2) It is in bad quality 'qflag == 1'; or // +// (3) Its length is larger than the mesh sizes at its endpoints. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::splitsegment(face *splitseg, point encpt, REAL rrp, + point encpt1, point encpt2, int qflag, + int chkencflag) +{ + point pa = sorg(*splitseg); + point pb = sdest(*splitseg); + + + + if ((encpt == NULL) && (qflag == 0)) { + if (useinsertradius) { + // Do not split this segment if the length is smaller than the smaller + // insertion radius at its endpoints. + REAL len = distance(pa, pb); + REAL smrrv = getpointinsradius(pa); + REAL rrv = getpointinsradius(pb); + if (rrv > 0) { + if (smrrv > 0) { + if (rrv < smrrv) { + smrrv = rrv; + } + } else { + smrrv = rrv; + } + } + if (smrrv > 0) { + if ((fabs(smrrv - len) / len) < b->epsilon) smrrv = len; + if (len < smrrv) { + return 0; + } + } + } + } + + if (b->nobisect) { // With -Y option. + // Only split this segment if it is allowed to be split. + if (checkconstraints) { + // Check if it has a non-zero length bound. + if (areabound(*splitseg) == 0) { + // It is not allowed. However, if all of facets containing this seg + // is allowed to be split, we still split it. + face parentsh, spinsh; + //splitseg.shver = 0; + spivot(*splitseg, parentsh); + if (parentsh.sh == NULL) { + return 0; // A dangling segment. Do not split it. + } + spinsh = parentsh; + while (1) { + if (areabound(spinsh) == 0) break; + spivotself(spinsh); + if (spinsh.sh == parentsh.sh) break; + } + if (areabound(spinsh) == 0) { + // All facets at this seg are not allowed to be split. + return 0; // Do not split it. + } + } + } else { + return 0; // Do not split this segment. + } + } // if (b->nobisect) + + triface searchtet; + face searchsh; + point newpt; + insertvertexflags ivf; + + makepoint(&newpt, FREESEGVERTEX); + getsteinerptonsegment(splitseg, encpt, newpt); + + // Split the segment by the Bowyer-Watson algorithm. + sstpivot1(*splitseg, searchtet); + ivf.iloc = (int) ONEDGE; + // Use Bowyer-Watson algorithm. Preserve subsegments and subfaces; + ivf.bowywat = 3; + ivf.validflag = 1; // Validate the B-W cavity. + ivf.lawson = 2; // Do flips to recover Delaunayness. + ivf.rejflag = 0; // Do not check encroachment of new segments/facets. + if (b->metric) { + ivf.rejflag |= 4; // Do check encroachment of protecting balls. + } + ivf.chkencflag = chkencflag; + ivf.sloc = (int) INSTAR; // ivf.iloc; + ivf.sbowywat = 3; // ivf.bowywat; // Surface mesh options. + ivf.splitbdflag = 1; + ivf.respectbdflag = 1; + ivf.assignmeshsize = b->metric; + ivf.smlenflag = useinsertradius; + + + if (insertpoint(newpt, &searchtet, &searchsh, splitseg, &ivf)) { + st_segref_count++; + if (steinerleft > 0) steinerleft--; + if (useinsertradius) { + // Update 'rv' (to be the shortest distance). + REAL rv = ivf.smlen, rp; + if (pointtype(ivf.parentpt) == FREESEGVERTEX) { + face parentseg1, parentseg2; + sdecode(point2sh(newpt), parentseg1); + sdecode(point2sh(ivf.parentpt), parentseg2); + if (segsegadjacent(&parentseg1, &parentseg2)) { + rp = getpointinsradius(ivf.parentpt); + if (rv < rp) { + rv = rp; // The relaxed insertion radius of 'newpt'. + } + } + } else if (pointtype(ivf.parentpt) == FREEFACETVERTEX) { + face parentseg, parentsh; + sdecode(point2sh(newpt), parentseg); + sdecode(point2sh(ivf.parentpt), parentsh); + if (segfacetadjacent(&parentseg, &parentsh)) { + rp = getpointinsradius(ivf.parentpt); + if (rv < rp) { + rv = rp; // The relaxed insertion radius of 'newpt'. + } + } + } + setpointinsradius(newpt, rv); + } + if (flipstack != NULL) { + flipconstraints fc; + fc.chkencflag = chkencflag; + fc.enqflag = 2; + lawsonflip3d(&fc); + unflipqueue->restart(); + } + return 1; + } else { + // Point is not inserted. + pointdealloc(newpt); + return 0; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// repairencsegs() Repair encroached (sub) segments. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::repairencsegs(int chkencflag) +{ + face *bface; + point encpt = NULL; + int qflag = 0; + + // Loop until the pool 'badsubsegs' is empty. Note that steinerleft == -1 + // if an unlimited number of Steiner points is allowed. + while ((badsubsegs->items > 0) && (steinerleft != 0)) { + badsubsegs->traversalinit(); + bface = (face *) badsubsegs->traverse(); + while ((bface != NULL) && (steinerleft != 0)) { + // Skip a deleleted element. + if (bface->shver >= 0) { + // A queued segment may have been deleted (split). + if ((bface->sh != NULL) && (bface->sh[3] != NULL)) { + // A queued segment may have been processed. + if (smarktest2ed(*bface)) { + sunmarktest2(*bface); + if (checkseg4split(bface, encpt, qflag)) { + splitsegment(bface, encpt, 0, NULL, NULL, qflag, chkencflag); + } + } + } + // Remove this entry from list. + bface->shver = -1; // Signal it as a deleted element. + badsubsegs->dealloc((void *) bface); + } + bface = (face *) badsubsegs->traverse(); + } + } + + if (badsubsegs->items > 0) { + if (steinerleft == 0) { + if (b->verbose) { + printf("The desired number of Steiner points is reached.\n"); + } + } else { + assert(0); // Unknown case. + } + badsubsegs->traversalinit(); + bface = (face *) badsubsegs->traverse(); + while (bface != NULL) { + // Skip a deleleted element. + if (bface->shver >= 0) { + if ((bface->sh != NULL) && (bface->sh[3] != NULL)) { + if (smarktest2ed(*bface)) { + sunmarktest2(*bface); + } + } + } + bface = (face *) badsubsegs->traverse(); + } + badsubsegs->restart(); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// enqueuesubface() Queue a subface or a subsegment for encroachment chk. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::enqueuesubface(memorypool *pool, face *chkface) +{ + if (!smarktest2ed(*chkface)) { + smarktest2(*chkface); // Only queue it once. + face *queface = (face *) pool->alloc(); + *queface = *chkface; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// checkfac4encroach() Check if a subface is encroached by a point. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::checkfac4encroach(point pa, point pb, point pc, point checkpt, + REAL* cent, REAL* r) +{ + REAL rd, len; + + circumsphere(pa, pb, pc, NULL, cent, &rd); + assert(rd != 0); + len = distance(cent, checkpt); + if ((fabs(len - rd) / rd) < b->epsilon) len = rd; // Rounding. + + if (len < rd) { + // The point lies inside the circumsphere of this face. + if (b->metric) { // -m option. + if ((pa[pointmtrindex] > 0) && (pb[pointmtrindex] > 0) && + (pc[pointmtrindex] > 0)) { + // Get the projection of 'checkpt' in the plane of pa, pb, and pc. + REAL prjpt[3], n[3]; + REAL a, a1, a2, a3; + projpt2face(checkpt, pa, pb, pc, prjpt); + // Get the face area of [a,b,c]. + facenormal(pa, pb, pc, n, 1, NULL); + a = sqrt(dot(n,n)); + // Get the face areas of [a,b,p], [b,c,p], and [c,a,p]. + facenormal(pa, pb, prjpt, n, 1, NULL); + a1 = sqrt(dot(n,n)); + facenormal(pb, pc, prjpt, n, 1, NULL); + a2 = sqrt(dot(n,n)); + facenormal(pc, pa, prjpt, n, 1, NULL); + a3 = sqrt(dot(n,n)); + if ((fabs(a1 + a2 + a3 - a) / a) < b->epsilon) { + // This face contains the projection. + // Get the mesh size at the location of the projection point. + rd = a1 / a * pc[pointmtrindex] + + a2 / a * pa[pointmtrindex] + + a3 / a * pb[pointmtrindex]; + len = distance(prjpt, checkpt); + if (len < rd) { + return 1; // Encroached. + } + } + } else { + return 1; // No protecting ball. Encroached. + } + } else { + *r = rd; + return 1; // Encroached. + } + } + + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// checkfac4split() Check if a subface needs to be split. // +// // +// A subface needs to be split if it is in the following case: // +// (1) It is encroached by an existing vertex. // +// (2) It has bad quality (has a small angle, -q). // +// (3) It's area is larger than a prescribed value (.var). // +// // +// Return 1 if it needs to be split, otherwise, return 0. // +// 'chkfac' represents its longest edge. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::checkfac4split(face *chkfac, point& encpt, int& qflag, + REAL *cent) +{ + point pa, pb, pc; + REAL area, rd, len; + REAL A[4][4], rhs[4], D; + int indx[4]; + int i; + + encpt = NULL; + qflag = 0; + + pa = sorg(*chkfac); + pb = sdest(*chkfac); + pc = sapex(*chkfac); + + // Compute the coefficient matrix A (3x3). + A[0][0] = pb[0] - pa[0]; + A[0][1] = pb[1] - pa[1]; + A[0][2] = pb[2] - pa[2]; // vector V1 (pa->pb) + A[1][0] = pc[0] - pa[0]; + A[1][1] = pc[1] - pa[1]; + A[1][2] = pc[2] - pa[2]; // vector V2 (pa->pc) + cross(A[0], A[1], A[2]); // vector V3 (V1 X V2) + + area = 0.5 * sqrt(dot(A[2], A[2])); // The area of [a,b,c]. + + // Compute the right hand side vector b (3x1). + rhs[0] = 0.5 * dot(A[0], A[0]); // edge [a,b] + rhs[1] = 0.5 * dot(A[1], A[1]); // edge [a,c] + rhs[2] = 0.0; + + // Solve the 3 by 3 equations use LU decomposition with partial + // pivoting and backward and forward substitute. + if (!lu_decmp(A, 3, indx, &D, 0)) { + // A degenerate triangle. + assert(0); + } + + lu_solve(A, 3, indx, rhs, 0); + cent[0] = pa[0] + rhs[0]; + cent[1] = pa[1] + rhs[1]; + cent[2] = pa[2] + rhs[2]; + rd = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]); + + if (checkconstraints && (areabound(*chkfac) > 0.0)) { + // Check if the subface has too big area. + if (area > areabound(*chkfac)) { + qflag = 1; + return 1; + } + } + + if (b->fixedvolume) { + if ((area * sqrt(area)) > b->maxvolume) { + qflag = 1; + return 1; + } + } + + if (b->varvolume) { + triface adjtet; + REAL volbnd; + int t1ver; + + stpivot(*chkfac, adjtet); + if (!ishulltet(adjtet)) { + volbnd = volumebound(adjtet.tet); + if ((volbnd > 0) && (area * sqrt(area)) > volbnd) { + qflag = 1; + return 1; + } + } + fsymself(adjtet); + if (!ishulltet(adjtet)) { + volbnd = volumebound(adjtet.tet); + if ((volbnd > 0) && (area * sqrt(area)) > volbnd) { + qflag = 1; + return 1; + } + } + } + + if (b->metric) { // -m option. Check mesh size. + // Check if the ccent lies outside one of the prot.balls at vertices. + if (((pa[pointmtrindex] > 0) && (rd > pa[pointmtrindex])) || + ((pb[pointmtrindex] > 0) && (rd > pb[pointmtrindex])) || + ((pc[pointmtrindex] > 0) && (rd > pc[pointmtrindex]))) { + qflag = 1; // Enforce mesh size. + return 1; + } + } + + triface searchtet; + REAL smlen = 0; + + // Check if this subface is locally encroached. + for (i = 0; i < 2; i++) { + stpivot(*chkfac, searchtet); + if (!ishulltet(searchtet)) { + len = distance(oppo(searchtet), cent); + if ((fabs(len - rd) / rd) < b->epsilon) len = rd;// Rounding. + if (len < rd) { + if (smlen == 0) { + smlen = len; + encpt = oppo(searchtet); + } else { + if (len < smlen) { + smlen = len; + encpt = oppo(searchtet); + } + } + //return 1; + } + } + sesymself(*chkfac); + } + + return encpt != NULL; //return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// splitsubface() Split a subface. // +// // +// The subface may be encroached, or in bad-quality. It is split at its cir- // +// cumcenter ('ccent'). Do not split it if 'ccent' encroaches upon any seg- // +// ment. Instead, one of the encroached segments is split. It is possible // +// that none of the encroached segments can be split. // +// // +// The return value indicates whether a new point is inserted (> 0) or not // +// (= 0). Furthermore, it is inserted on an encroached segment (= 1) or // +// in-side the facet (= 2). // +// // +// 'encpt' is a vertex encroaching upon this subface, i.e., it causes the // +// split of this subface. If 'encpt' is NULL, then the cause of the split // +// this subface is a rejected tet circumcenter 'p', and 'encpt1' is the // +// parent of 'p'. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::splitsubface(face *splitfac, point encpt, point encpt1, + int qflag, REAL *ccent, int chkencflag) +{ + point pa = sorg(*splitfac); + point pb = sdest(*splitfac); + point pc = sapex(*splitfac); + + + + if (b->nobisect) { // With -Y option. + if (checkconstraints) { + // Only split if it is allowed to be split. + // Check if this facet has a non-zero constraint. + if (areabound(*splitfac) == 0) { + return 0; // Do not split it. + } + } else { + return 0; + } + } // if (b->nobisect) + + face searchsh; + insertvertexflags ivf; + point newpt; + REAL rv = 0., rp; // Insertion radius of newpt. + int i; + + // Initialize the inserting point. + makepoint(&newpt, FREEFACETVERTEX); + // Split the subface at its circumcenter. + for (i = 0; i < 3; i++) newpt[i] = ccent[i]; + + if (useinsertradius) { + if (encpt != NULL) { + rv = distance(newpt, encpt); + if (pointtype(encpt) == FREESEGVERTEX) { + face parentseg; + sdecode(point2sh(encpt), parentseg); + if (segfacetadjacent(&parentseg, splitfac)) { + rp = getpointinsradius(encpt); + if (rv < (sqrt(2.0) * rp)) { + // This insertion may cause no termination. + pointdealloc(newpt); + return 0; // Reject the insertion of newpt. + } + } + } else if (pointtype(encpt) == FREEFACETVERTEX) { + face parentsh; + sdecode(point2sh(encpt), parentsh); + if (facetfacetadjacent(&parentsh, splitfac)) { + rp = getpointinsradius(encpt); + if (rv < rp) { + pointdealloc(newpt); + return 0; // Reject the insertion of newpt. + } + } + } + } + } // if (useinsertradius) + + // Search a subface which contains 'newpt'. + searchsh = *splitfac; + // Calculate an above point. It lies above the plane containing + // the subface [a,b,c], and save it in dummypoint. Moreover, + // the vector cent->dummypoint is the normal of the plane. + calculateabovepoint4(newpt, pa, pb, pc); + // Parameters: 'aflag' = 1, - above point exists. + // 'cflag' = 0, - non-convex, check co-planarity of the result. + // 'rflag' = 0, - no need to round the locating result. + ivf.iloc = (int) slocate(newpt, &searchsh, 1, 0, 0); + + if (!((ivf.iloc == (int) ONFACE) || (ivf.iloc == (int) ONEDGE))) { + pointdealloc(newpt); + return 0; + } + + + triface searchtet; + face *paryseg; + int splitflag; + + // Insert the point. + stpivot(searchsh, searchtet); + //assert((ivf.iloc == (int) ONFACE) || (ivf.iloc == (int) ONEDGE)); + // Use Bowyer-Watson algorithm. Preserve subsegments and subfaces; + ivf.bowywat = 3; + ivf.lawson = 2; + ivf.rejflag = 1; // Do check the encroachment of segments. + if (b->metric) { + ivf.rejflag |= 4; // Do check encroachment of protecting balls. + } + ivf.chkencflag = chkencflag; + ivf.sloc = (int) INSTAR; // ivf.iloc; + ivf.sbowywat = 3; // ivf.bowywat; + ivf.splitbdflag = 1; + ivf.validflag = 1; + ivf.respectbdflag = 1; + ivf.assignmeshsize = b->metric; + + ivf.refineflag = 2; + ivf.refinesh = searchsh; + ivf.smlenflag = useinsertradius; // Update the insertion radius. + + + if (insertpoint(newpt, &searchtet, &searchsh, NULL, &ivf)) { + st_facref_count++; + if (steinerleft > 0) steinerleft--; + if (useinsertradius) { + // Update 'rv' (to be the shortest distance). + rv = ivf.smlen; + if (pointtype(ivf.parentpt) == FREESEGVERTEX) { + face parentseg, parentsh; + sdecode(point2sh(ivf.parentpt), parentseg); + sdecode(point2sh(newpt), parentsh); + if (segfacetadjacent(&parentseg, &parentsh)) { + rp = getpointinsradius(ivf.parentpt); + if (rv < (sqrt(2.0) * rp)) { + rv = sqrt(2.0) * rp; // The relaxed insertion radius of 'newpt'. + } + } + } else if (pointtype(ivf.parentpt) == FREEFACETVERTEX) { + face parentsh1, parentsh2; + sdecode(point2sh(ivf.parentpt), parentsh1); + sdecode(point2sh(newpt), parentsh2); + if (facetfacetadjacent(&parentsh1, &parentsh2)) { + rp = getpointinsradius(ivf.parentpt); + if (rv < rp) { + rv = rp; // The relaxed insertion radius of 'newpt'. + } + } + } + setpointinsradius(newpt, rv); + } // if (useinsertradius) + if (flipstack != NULL) { + flipconstraints fc; + fc.chkencflag = chkencflag; + fc.enqflag = 2; + lawsonflip3d(&fc); + unflipqueue->restart(); + } + return 1; + } else { + // Point was not inserted. + pointdealloc(newpt); + if (ivf.iloc == (int) ENCSEGMENT) { + // Select an encroached segment and split it. + splitflag = 0; + for (i = 0; i < encseglist->objects; i++) { + paryseg = (face *) fastlookup(encseglist, i); + if (splitsegment(paryseg, NULL, rv, encpt, encpt1, qflag, + chkencflag | 1)) { + splitflag = 1; // A point is inserted on a segment. + break; + } + } + encseglist->restart(); + if (splitflag) { + // Some segments may need to be repaired. + repairencsegs(chkencflag | 1); + // Queue this subface if it is still alive and not queued. + //if ((splitfac->sh != NULL) && (splitfac->sh[3] != NULL)) { + // // Only queue it if 'qflag' is set. + // if (qflag) { + // enqueuesubface(badsubfacs, splitfac); + // } + //} + } + return splitflag; + } else { + return 0; + } + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// repairencfacs() Repair encroached subfaces. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::repairencfacs(int chkencflag) +{ + face *bface; + point encpt = NULL; + int qflag = 0; + REAL ccent[3]; + + // Loop until the pool 'badsubfacs' is empty. Note that steinerleft == -1 + // if an unlimited number of Steiner points is allowed. + while ((badsubfacs->items > 0) && (steinerleft != 0)) { + badsubfacs->traversalinit(); + bface = (face *) badsubfacs->traverse(); + while ((bface != NULL) && (steinerleft != 0)) { + // Skip a deleted element. + if (bface->shver >= 0) { + // A queued subface may have been deleted (split). + if ((bface->sh != NULL) && (bface->sh[3] != NULL)) { + // A queued subface may have been processed. + if (smarktest2ed(*bface)) { + sunmarktest2(*bface); + if (checkfac4split(bface, encpt, qflag, ccent)) { + splitsubface(bface, encpt, NULL, qflag, ccent, chkencflag); + } + } + } + bface->shver = -1; // Signal it as a deleted element. + badsubfacs->dealloc((void *) bface); // Remove this entry from list. + } + bface = (face *) badsubfacs->traverse(); + } + } + + if (badsubfacs->items > 0) { + if (steinerleft == 0) { + if (b->verbose) { + printf("The desired number of Steiner points is reached.\n"); + } + } else { + assert(0); // Unknown case. + } + badsubfacs->traversalinit(); + bface = (face *) badsubfacs->traverse(); + while (bface != NULL) { + // Skip a deleted element. + if (bface->shver >= 0) { + if ((bface->sh != NULL) && (bface->sh[3] != NULL)) { + if (smarktest2ed(*bface)) { + sunmarktest2(*bface); + } + } + } + bface = (face *) badsubfacs->traverse(); + } + badsubfacs->restart(); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// enqueuetetrahedron() Queue a tetrahedron for quality check. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::enqueuetetrahedron(triface *chktet) +{ + if (!marktest2ed(*chktet)) { + marktest2(*chktet); // Only queue it once. + triface *quetet = (triface *) badtetrahedrons->alloc(); + *quetet = *chktet; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// checktet4split() Check if the tet needs to be split. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::checktet4split(triface *chktet, int &qflag, REAL *ccent) +{ + point pa, pb, pc, pd, *ppt; + REAL vda[3], vdb[3], vdc[3]; + REAL vab[3], vbc[3], vca[3]; + REAL N[4][3], L[4], cosd[6], elen[6]; + REAL maxcosd, vol, volbnd, smlen = 0, rd; + REAL A[4][4], rhs[4], D; + int indx[4]; + int i, j; + + if (b->convex) { // -c + // Skip this tet if it lies in the exterior. + if (elemattribute(chktet->tet, numelemattrib - 1) == -1.0) { + return 0; + } + } + + qflag = 0; + + pd = (point) chktet->tet[7]; + if (pd == dummypoint) { + return 0; // Do not split a hull tet. + } + + pa = (point) chktet->tet[4]; + pb = (point) chktet->tet[5]; + pc = (point) chktet->tet[6]; + + // Get the edge vectors vda: d->a, vdb: d->b, vdc: d->c. + // Set the matrix A = [vda, vdb, vdc]^T. + for (i = 0; i < 3; i++) A[0][i] = vda[i] = pa[i] - pd[i]; + for (i = 0; i < 3; i++) A[1][i] = vdb[i] = pb[i] - pd[i]; + for (i = 0; i < 3; i++) A[2][i] = vdc[i] = pc[i] - pd[i]; + + // Get the other edge vectors. + for (i = 0; i < 3; i++) vab[i] = pb[i] - pa[i]; + for (i = 0; i < 3; i++) vbc[i] = pc[i] - pb[i]; + for (i = 0; i < 3; i++) vca[i] = pa[i] - pc[i]; + + if (!lu_decmp(A, 3, indx, &D, 0)) { + // A degenerated tet (vol = 0). + // This is possible due to the use of exact arithmetic. We temporarily + // leave this tet. It should be fixed by mesh optimization. + return 0; + } + + // Check volume if '-a#' and '-a' options are used. + if (b->varvolume || b->fixedvolume) { + vol = fabs(A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0; + if (b->fixedvolume) { + if (vol > b->maxvolume) { + qflag = 1; + } + } + if (!qflag && b->varvolume) { + volbnd = volumebound(chktet->tet); + if ((volbnd > 0.0) && (vol > volbnd)) { + qflag = 1; + } + } + if (qflag == 1) { + // Calculate the circumcenter of this tet. + rhs[0] = 0.5 * dot(vda, vda); + rhs[1] = 0.5 * dot(vdb, vdb); + rhs[2] = 0.5 * dot(vdc, vdc); + lu_solve(A, 3, indx, rhs, 0); + for (i = 0; i < 3; i++) ccent[i] = pd[i] + rhs[i]; + return 1; + } + } + + if (b->metric) { // -m option. Check mesh size. + // Calculate the circumradius of this tet. + rhs[0] = 0.5 * dot(vda, vda); + rhs[1] = 0.5 * dot(vdb, vdb); + rhs[2] = 0.5 * dot(vdc, vdc); + lu_solve(A, 3, indx, rhs, 0); + for (i = 0; i < 3; i++) ccent[i] = pd[i] + rhs[i]; + rd = sqrt(dot(rhs, rhs)); + // Check if the ccent lies outside one of the prot.balls at vertices. + ppt = (point *) &(chktet->tet[4]); + for (i = 0; i < 4; i++) { + if (ppt[i][pointmtrindex] > 0) { + if (rd > ppt[i][pointmtrindex]) { + qflag = 1; // Enforce mesh size. + return 1; + } + } + } + } + + if (in->tetunsuitable != NULL) { + // Execute the user-defined meshing sizing evaluation. + if ((*(in->tetunsuitable))(pa, pb, pc, pd, NULL, 0)) { + // Calculate the circumcenter of this tet. + rhs[0] = 0.5 * dot(vda, vda); + rhs[1] = 0.5 * dot(vdb, vdb); + rhs[2] = 0.5 * dot(vdc, vdc); + lu_solve(A, 3, indx, rhs, 0); + for (i = 0; i < 3; i++) ccent[i] = pd[i] + rhs[i]; + return 1; + } + } + + if (useinsertradius) { + // Do not split this tet if the shortest edge is shorter than the + // insertion radius of one of its endpoints. + triface checkedge; + point e1, e2; + REAL rrv, smrrv; + + // Get the shortest edge of this tet. + checkedge.tet = chktet->tet; + for (i = 0; i < 6; i++) { + checkedge.ver = edge2ver[i]; + e1 = org(checkedge); + e2 = dest(checkedge); + elen[i] = distance(e1, e2); + if (i == 0) { + smlen = elen[i]; + j = 0; + } else { + if (elen[i] < smlen) { + smlen = elen[i]; + j = i; + } + } + } + // Check if the edge is too short. + checkedge.ver = edge2ver[j]; + // Get the smallest rrv of e1 and e2. + // Note: if rrv of e1 and e2 is zero. Do not use it. + e1 = org(checkedge); + smrrv = getpointinsradius(e1); + e2 = dest(checkedge); + rrv = getpointinsradius(e2); + if (rrv > 0) { + if (smrrv > 0) { + if (rrv < smrrv) { + smrrv = rrv; + } + } else { + smrrv = rrv; + } + } + if (smrrv > 0) { + // To avoid rounding error, round smrrv before doing comparison. + if ((fabs(smrrv - smlen) / smlen) < b->epsilon) { + smrrv = smlen; + } + if (smrrv > smlen) { + return 0; + } + } + } // if (useinsertradius) + + // Check the radius-edge ratio. Set by -q#. + if (b->minratio > 0) { + // Calculate the circumcenter and radius of this tet. + rhs[0] = 0.5 * dot(vda, vda); + rhs[1] = 0.5 * dot(vdb, vdb); + rhs[2] = 0.5 * dot(vdc, vdc); + lu_solve(A, 3, indx, rhs, 0); + for (i = 0; i < 3; i++) ccent[i] = pd[i] + rhs[i]; + rd = sqrt(dot(rhs, rhs)); + if (!useinsertradius) { + // Calculate the shortest edge length. + elen[0] = dot(vda, vda); + elen[1] = dot(vdb, vdb); + elen[2] = dot(vdc, vdc); + elen[3] = dot(vab, vab); + elen[4] = dot(vbc, vbc); + elen[5] = dot(vca, vca); + smlen = elen[0]; //sidx = 0; + for (i = 1; i < 6; i++) { + if (smlen > elen[i]) { + smlen = elen[i]; //sidx = i; + } + } + smlen = sqrt(smlen); + } + D = rd / smlen; + if (D > b->minratio) { + // A bad radius-edge ratio. + return 1; + } + } + + // Check the minimum dihedral angle. Set by -qq#. + if (b->mindihedral > 0) { + // Compute the 4 face normals (N[0], ..., N[3]). + for (j = 0; j < 3; j++) { + for (i = 0; i < 3; i++) N[j][i] = 0.0; + N[j][j] = 1.0; // Positive means the inside direction + lu_solve(A, 3, indx, N[j], 0); + } + for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i]; + // Normalize the normals. + for (i = 0; i < 4; i++) { + L[i] = sqrt(dot(N[i], N[i])); + assert(L[i] > 0); + //if (L[i] > 0.0) { + for (j = 0; j < 3; j++) N[i][j] /= L[i]; + //} + } + // Calculate the six dihedral angles. + cosd[0] = -dot(N[0], N[1]); // Edge cd, bd, bc. + cosd[1] = -dot(N[0], N[2]); + cosd[2] = -dot(N[0], N[3]); + cosd[3] = -dot(N[1], N[2]); // Edge ad, ac + cosd[4] = -dot(N[1], N[3]); + cosd[5] = -dot(N[2], N[3]); // Edge ab + // Get the smallest dihedral angle. + //maxcosd = mincosd = cosd[0]; + maxcosd = cosd[0]; + for (i = 1; i < 6; i++) { + //if (cosd[i] > maxcosd) maxcosd = cosd[i]; + maxcosd = (cosd[i] > maxcosd ? cosd[i] : maxcosd); + //mincosd = (cosd[i] < mincosd ? cosd[i] : maxcosd); + } + if (maxcosd > cosmindihed) { + // Calculate the circumcenter of this tet. + // A bad dihedral angle. + //if ((b->quality & 1) == 0) { + rhs[0] = 0.5 * dot(vda, vda); + rhs[1] = 0.5 * dot(vdb, vdb); + rhs[2] = 0.5 * dot(vdc, vdc); + lu_solve(A, 3, indx, rhs, 0); + for (i = 0; i < 3; i++) ccent[i] = pd[i] + rhs[i]; + //*rd = sqrt(dot(rhs, rhs)); + //} + return 1; + } + } + + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// splittetrahedron() Split a tetrahedron. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::splittetrahedron(triface* splittet, int qflag, REAL *ccent, + int chkencflag) +{ + triface searchtet; + face *paryseg; + point newpt; + badface *bface; + insertvertexflags ivf; + int splitflag; + int i; + + + + REAL rv = 0.; // Insertion radius of 'newpt'. + + makepoint(&newpt, FREEVOLVERTEX); + for (i = 0; i < 3; i++) newpt[i] = ccent[i]; + + if (useinsertradius) { + rv = distance(newpt, org(*splittet)); + setpointinsradius(newpt, rv); + } + + searchtet = *splittet; + ivf.iloc = (int) OUTSIDE; + // Use Bowyer-Watson algorithm. Preserve subsegments and subfaces; + ivf.bowywat = 3; + ivf.lawson = 2; + ivf.rejflag = 3; // Do check for encroached segments and subfaces. + if (b->metric) { + ivf.rejflag |= 4; // Reject it if it lies in some protecting balls. + } + ivf.chkencflag = chkencflag; + ivf.sloc = ivf.sbowywat = 0; // No use. + ivf.splitbdflag = 0; // No use. + ivf.validflag = 1; + ivf.respectbdflag = 1; + ivf.assignmeshsize = b->metric; + + ivf.refineflag = 1; + ivf.refinetet = *splittet; + + + if (insertpoint(newpt, &searchtet, NULL, NULL, &ivf)) { + // Vertex is inserted. + st_volref_count++; + if (steinerleft > 0) steinerleft--; + if (flipstack != NULL) { + flipconstraints fc; + fc.chkencflag = chkencflag; + fc.enqflag = 2; + lawsonflip3d(&fc); + unflipqueue->restart(); + } + return 1; + } else { + // Point is not inserted. + pointdealloc(newpt); + // Check if there are encroached segments/subfaces. + if (ivf.iloc == (int) ENCSEGMENT) { + splitflag = 0; + //if (!b->nobisect) { // not -Y option + if (!b->nobisect || checkconstraints) { + // Select an encroached segment and split it. + for (i = 0; i < encseglist->objects; i++) { + paryseg = (face *) fastlookup(encseglist, i); + if (splitsegment(paryseg, NULL, rv, org(*splittet), NULL, qflag, + chkencflag | 3)) { + splitflag = 1; // A point is inserted on a segment. + break; + } + } + } // if (!b->nobisect) + encseglist->restart(); + if (splitflag) { + // Some segments may need to be repaired. + repairencsegs(chkencflag | 3); + // Some subfaces may need to be repaired. + repairencfacs(chkencflag | 2); + // Queue the tet if it is still alive and not queued. + if ((splittet->tet != NULL) && (splittet->tet[4] != NULL)) { + enqueuetetrahedron(splittet); + } + } + return splitflag; + } else if (ivf.iloc == (int) ENCSUBFACE) { + splitflag = 0; + //if (!b->nobisect) { // not -Y option + if (!b->nobisect || checkconstraints) { + // Select an encroached subface and split it. + for (i = 0; i < encshlist->objects; i++) { + bface = (badface *) fastlookup(encshlist, i); + if (splitsubface(&(bface->ss), NULL, org(*splittet), qflag, + bface->cent, chkencflag | 2)){ + splitflag = 1; // A point is inserted on a subface or a segment. + break; + } + } + } // if (!b->nobisect) + encshlist->restart(); + if (splitflag) { + assert(badsubsegs->items == 0l); + // Some subfaces may need to be repaired. + repairencfacs(chkencflag | 2); + // Queue the tet if it is still alive. + if ((splittet->tet != NULL) && (splittet->tet[4] != NULL)) { + enqueuetetrahedron(splittet); + } + } + return splitflag; + } + return 0; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// repairbadtets() Repair bad quality tetrahedra. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::repairbadtets(int chkencflag) +{ + triface *bface; + REAL ccent[3]; + int qflag = 0; + + + // Loop until the pool 'badsubfacs' is empty. Note that steinerleft == -1 + // if an unlimited number of Steiner points is allowed. + while ((badtetrahedrons->items > 0) && (steinerleft != 0)) { + badtetrahedrons->traversalinit(); + bface = (triface *) badtetrahedrons->traverse(); + while ((bface != NULL) && (steinerleft != 0)) { + // Skip a deleted element. + if (bface->ver >= 0) { + // A queued tet may have been deleted. + if (!isdeadtet(*bface)) { + // A queued tet may have been processed. + if (marktest2ed(*bface)) { + unmarktest2(*bface); + if (checktet4split(bface, qflag, ccent)) { + splittetrahedron(bface, qflag, ccent, chkencflag); + } + } + } + bface->ver = -1; // Signal it as a deleted element. + badtetrahedrons->dealloc((void *) bface); + } + bface = (triface *) badtetrahedrons->traverse(); + } + } + + if (badtetrahedrons->items > 0) { + if (steinerleft == 0) { + if (b->verbose) { + printf("The desired number of Steiner points is reached.\n"); + } + } else { + assert(0); // Unknown case. + } + // Unmark all queued tet. + badtetrahedrons->traversalinit(); + bface = (triface *) badtetrahedrons->traverse(); + while (bface != NULL) { + // Skip a deleted element. + if (bface->ver >= 0) { + if (!isdeadtet(*bface)) { + if (marktest2ed(*bface)) { + unmarktest2(*bface); + } + } + } + bface = (triface *) badtetrahedrons->traverse(); + } + // Clear the pool. + badtetrahedrons->restart(); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// delaunayrefinement() Refine the mesh by Delaunay refinement. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::delaunayrefinement() +{ + triface checktet; + face checksh; + face checkseg; + long steinercount; + int chkencflag; + + long bak_segref_count, bak_facref_count, bak_volref_count; + long bak_flipcount = flip23count + flip32count + flip44count; + + if (!b->quiet) { + printf("Refining mesh...\n"); + } + + if (b->verbose) { + printf(" Min radiu-edge ratio = %g.\n", b->minratio); + printf(" Min dihedral angle = %g.\n", b->mindihedral); + //printf(" Min Edge length = %g.\n", b->minedgelength); + } + + steinerleft = b->steinerleft; // Upperbound of # Steiner points (by -S#). + if (steinerleft > 0) { + // Check if we've already used up the given number of Steiner points. + steinercount = st_segref_count + st_facref_count + st_volref_count; + if (steinercount < steinerleft) { + steinerleft -= steinercount; + } else { + if (!b->quiet) { + printf("\nWarning: "); + printf("The desired number of Steiner points (%d) has reached.\n\n", + b->steinerleft); + } + return; // No more Steiner points. + } + } + + if (useinsertradius) { + if ((b->plc && b->nobisect) || b->refine) { // '-pY' or '-r' option. + makesegmentendpointsmap(); + } + makefacetverticesmap(); + } + + + encseglist = new arraypool(sizeof(face), 8); + encshlist = new arraypool(sizeof(badface), 8); + + + //if (!b->nobisect) { // if no '-Y' option + if (!b->nobisect || checkconstraints) { + if (b->verbose) { + printf(" Splitting encroached subsegments.\n"); + } + + chkencflag = 1; // Only check encroaching subsegments. + steinercount = points->items; + + // Initialize the pool of encroached subsegments. + badsubsegs = new memorypool(sizeof(face), b->shellfaceperblock, + sizeof(void *), 0); + + // Add all segments into the pool. + subsegs->traversalinit(); + checkseg.sh = shellfacetraverse(subsegs); + while (checkseg.sh != (shellface *) NULL) { + enqueuesubface(badsubsegs, &checkseg); + checkseg.sh = shellfacetraverse(subsegs); + } + + // Split all encroached segments. + repairencsegs(chkencflag); + + if (b->verbose) { + printf(" Added %ld Steiner points.\n", points->items - steinercount); + } + + if (b->reflevel > 1) { // '-D2' option + if (b->verbose) { + printf(" Splitting encroached subfaces.\n"); + } + + chkencflag = 2; // Only check encroaching subfaces. + steinercount = points->items; + bak_segref_count = st_segref_count; + bak_facref_count = st_facref_count; + + // Initialize the pool of encroached subfaces. + badsubfacs = new memorypool(sizeof(face), b->shellfaceperblock, + sizeof(void *), 0); + + // Add all subfaces into the pool. + subfaces->traversalinit(); + checksh.sh = shellfacetraverse(subfaces); + while (checksh.sh != (shellface *) NULL) { + enqueuesubface(badsubfacs, &checksh); + checksh.sh = shellfacetraverse(subfaces); + } + + // Split all encroached subfaces. + repairencfacs(chkencflag); + + if (b->verbose) { + printf(" Added %ld (%ld,%ld) Steiner points.\n", + points->items-steinercount, st_segref_count-bak_segref_count, + st_facref_count-bak_facref_count); + } + } // if (b->reflevel > 1) + } // if (!b->nobisect) + + if (b->reflevel > 2) { // '-D3' option (The default option) + if (b->verbose) { + printf(" Splitting bad quality tets.\n"); + } + + chkencflag = 4; // Only check tetrahedra. + steinercount = points->items; + bak_segref_count = st_segref_count; + bak_facref_count = st_facref_count; + bak_volref_count = st_volref_count; + + // The cosine value of the min dihedral angle (-qq) for tetrahedra. + cosmindihed = cos(b->mindihedral / 180.0 * PI); + + // Initialize the pool of bad quality tetrahedra. + badtetrahedrons = new memorypool(sizeof(triface), b->tetrahedraperblock, + sizeof(void *), 0); + // Add all tetrahedra (no hull tets) into the pool. + tetrahedrons->traversalinit(); + checktet.tet = tetrahedrontraverse(); + while (checktet.tet != NULL) { + enqueuetetrahedron(&checktet); + checktet.tet = tetrahedrontraverse(); + } + + // Split all bad quality tetrahedra. + repairbadtets(chkencflag); + + if (b->verbose) { + printf(" Added %ld (%ld,%ld,%ld) Steiner points.\n", + points->items - steinercount, + st_segref_count - bak_segref_count, + st_facref_count - bak_facref_count, + st_volref_count - bak_volref_count); + } + } // if (b->reflevel > 2) + + if (b->verbose) { + if (flip23count + flip32count + flip44count > bak_flipcount) { + printf(" Performed %ld flips.\n", flip23count + flip32count + + flip44count - bak_flipcount); + } + } + + if (steinerleft == 0) { + if (!b->quiet) { + printf("\nWarnning: "); + printf("The desired number of Steiner points (%d) is reached.\n\n", + b->steinerleft); + } + } + + + delete encseglist; + delete encshlist; + + //if (!b->nobisect) { + if (!b->nobisect || checkconstraints) { + totalworkmemory += (badsubsegs->maxitems * badsubsegs->itembytes); + delete badsubsegs; + if (b->reflevel > 1) { + totalworkmemory += (badsubfacs->maxitems * badsubfacs->itembytes); + delete badsubfacs; + } + } + if (b->reflevel > 2) { + totalworkmemory += (badtetrahedrons->maxitems*badtetrahedrons->itembytes); + delete badtetrahedrons; + } +} + +//// //// +//// //// +//// refine_cxx /////////////////////////////////////////////////////////////// + +//// optimize_cxx ///////////////////////////////////////////////////////////// +//// //// +//// //// + +/////////////////////////////////////////////////////////////////////////////// +// // +// lawsonflip3d() A three-dimensional Lawson's algorithm. // +// // +/////////////////////////////////////////////////////////////////////////////// + +long tetgenmesh::lawsonflip3d(flipconstraints *fc) +{ + triface fliptets[5], neightet, hulltet; + face checksh, casingout; + badface *popface, *bface; + point pd, pe, *pts; + REAL sign, ori; + long flipcount, totalcount = 0l; + long sliver_peels = 0l; + int t1ver; + int i; + + + while (1) { + + if (b->verbose > 2) { + printf(" Lawson flip %ld faces.\n", flippool->items); + } + flipcount = 0l; + + while (flipstack != (badface *) NULL) { + // Pop a face from the stack. + popface = flipstack; + fliptets[0] = popface->tt; + flipstack = flipstack->nextitem; // The next top item in stack. + flippool->dealloc((void *) popface); + + // Skip it if it is a dead tet (destroyed by previous flips). + if (isdeadtet(fliptets[0])) continue; + // Skip it if it is not the same tet as we saved. + if (!facemarked(fliptets[0])) continue; + + unmarkface(fliptets[0]); + + if (ishulltet(fliptets[0])) continue; + + fsym(fliptets[0], fliptets[1]); + if (ishulltet(fliptets[1])) { + if (nonconvex) { + // Check if 'fliptets[0]' it is a hull sliver. + tspivot(fliptets[0], checksh); + for (i = 0; i < 3; i++) { + if (!isshsubseg(checksh)) { + spivot(checksh, casingout); + //assert(casingout.sh != NULL); + if (sorg(checksh) != sdest(casingout)) sesymself(casingout); + stpivot(casingout, neightet); + if (neightet.tet == fliptets[0].tet) { + // Found a hull sliver 'neightet'. Let it be [e,d,a,b], where + // [e,d,a] and [d,e,b] are hull faces. + edestoppo(neightet, hulltet); // [a,b,e,d] + fsymself(hulltet); // [b,a,e,#] + if (oppo(hulltet) == dummypoint) { + pe = org(neightet); + if ((pointtype(pe) == FREEFACETVERTEX) || + (pointtype(pe) == FREESEGVERTEX)) { + removevertexbyflips(pe); + } + } else { + eorgoppo(neightet, hulltet); // [b,a,d,e] + fsymself(hulltet); // [a,b,d,#] + if (oppo(hulltet) == dummypoint) { + pd = dest(neightet); + if ((pointtype(pd) == FREEFACETVERTEX) || + (pointtype(pd) == FREESEGVERTEX)) { + removevertexbyflips(pd); + } + } else { + // Perform a 3-to-2 flip to remove the sliver. + fliptets[0] = neightet; // [e,d,a,b] + fnext(fliptets[0], fliptets[1]); // [e,d,b,c] + fnext(fliptets[1], fliptets[2]); // [e,d,c,a] + flip32(fliptets, 1, fc); + // Update counters. + flip32count--; + flip22count--; + sliver_peels++; + if (fc->remove_ndelaunay_edge) { + // Update the volume (must be decreased). + //assert(fc->tetprism_vol_sum <= 0); + tetprism_vol_sum += fc->tetprism_vol_sum; + fc->tetprism_vol_sum = 0.0; // Clear it. + } + } + } + break; + } // if (neightet.tet == fliptets[0].tet) + } // if (!isshsubseg(checksh)) + senextself(checksh); + } // i + } // if (nonconvex) + continue; + } + + if (checksubfaceflag) { + // Do not flip if it is a subface. + if (issubface(fliptets[0])) continue; + } + + // Test whether the face is locally Delaunay or not. + pts = (point *) fliptets[1].tet; + sign = insphere_s(pts[4], pts[5], pts[6], pts[7], oppo(fliptets[0])); + + if (sign < 0) { + // A non-Delaunay face. Try to flip it. + pd = oppo(fliptets[0]); + pe = oppo(fliptets[1]); + + // Check the convexity of its three edges. Stop checking either a + // locally non-convex edge (ori < 0) or a flat edge (ori = 0) is + // encountered, and 'fliptet' represents that edge. + for (i = 0; i < 3; i++) { + ori = orient3d(org(fliptets[0]), dest(fliptets[0]), pd, pe); + if (ori <= 0) break; + enextself(fliptets[0]); + } + + if (ori > 0) { + // A 2-to-3 flip is found. + // [0] [a,b,c,d], + // [1] [b,a,c,e]. no dummypoint. + flip23(fliptets, 0, fc); + flipcount++; + if (fc->remove_ndelaunay_edge) { + // Update the volume (must be decreased). + //assert(fc->tetprism_vol_sum <= 0); + tetprism_vol_sum += fc->tetprism_vol_sum; + fc->tetprism_vol_sum = 0.0; // Clear it. + } + continue; + } else { // ori <= 0 + // The edge ('fliptets[0]' = [a',b',c',d]) is non-convex or flat, + // where the edge [a',b'] is one of [a,b], [b,c], and [c,a]. + if (checksubsegflag) { + // Do not flip if it is a segment. + if (issubseg(fliptets[0])) continue; + } + // Check if there are three or four tets sharing at this edge. + esymself(fliptets[0]); // [b,a,d,c] + for (i = 0; i < 3; i++) { + fnext(fliptets[i], fliptets[i+1]); + } + if (fliptets[3].tet == fliptets[0].tet) { + // A 3-to-2 flip is found. (No hull tet.) + flip32(fliptets, 0, fc); + flipcount++; + if (fc->remove_ndelaunay_edge) { + // Update the volume (must be decreased). + //assert(fc->tetprism_vol_sum <= 0); + tetprism_vol_sum += fc->tetprism_vol_sum; + fc->tetprism_vol_sum = 0.0; // Clear it. + } + continue; + } else { + // There are more than 3 tets at this edge. + fnext(fliptets[3], fliptets[4]); + if (fliptets[4].tet == fliptets[0].tet) { + // There are exactly 4 tets at this edge. + if (nonconvex) { + if (apex(fliptets[3]) == dummypoint) { + // This edge is locally non-convex on the hull. + // It can be removed by a 4-to-4 flip. + ori = 0; + } + } // if (nonconvex) + if (ori == 0) { + // A 4-to-4 flip is found. (Two hull tets may be involved.) + // Current tets in 'fliptets': + // [0] [b,a,d,c] (d may be newpt) + // [1] [b,a,c,e] + // [2] [b,a,e,f] (f may be dummypoint) + // [3] [b,a,f,d] + esymself(fliptets[0]); // [a,b,c,d] + // A 2-to-3 flip replaces face [a,b,c] by edge [e,d]. + // This creates a degenerate tet [e,d,a,b] (tmpfliptets[0]). + // It will be removed by the followed 3-to-2 flip. + flip23(fliptets, 0, fc); // No hull tet. + fnext(fliptets[3], fliptets[1]); + fnext(fliptets[1], fliptets[2]); + // Current tets in 'fliptets': + // [0] [...] + // [1] [b,a,d,e] (degenerated, d may be new point). + // [2] [b,a,e,f] (f may be dummypoint) + // [3] [b,a,f,d] + // A 3-to-2 flip replaces edge [b,a] by face [d,e,f]. + // Hull tets may be involved (f may be dummypoint). + flip32(&(fliptets[1]), (apex(fliptets[3]) == dummypoint), fc); + flipcount++; + flip23count--; + flip32count--; + flip44count++; + if (fc->remove_ndelaunay_edge) { + // Update the volume (must be decreased). + //assert(fc->tetprism_vol_sum <= 0); + tetprism_vol_sum += fc->tetprism_vol_sum; + fc->tetprism_vol_sum = 0.0; // Clear it. + } + continue; + } // if (ori == 0) + } + } + } // if (ori <= 0) + + // This non-Delaunay face is unflippable. Save it. + unflipqueue->newindex((void **) &bface); + bface->tt = fliptets[0]; + bface->forg = org(fliptets[0]); + bface->fdest = dest(fliptets[0]); + bface->fapex = apex(fliptets[0]); + } // if (sign < 0) + } // while (flipstack) + + if (b->verbose > 2) { + if (flipcount > 0) { + printf(" Performed %ld flips.\n", flipcount); + } + } + // Accumulate the counter of flips. + totalcount += flipcount; + + assert(flippool->items == 0l); + // Return if no unflippable faces left. + if (unflipqueue->objects == 0l) break; + // Return if no flip has been performed. + if (flipcount == 0l) break; + + // Try to flip the unflippable faces. + for (i = 0; i < unflipqueue->objects; i++) { + bface = (badface *) fastlookup(unflipqueue, i); + if (!isdeadtet(bface->tt) && + (org(bface->tt) == bface->forg) && + (dest(bface->tt) == bface->fdest) && + (apex(bface->tt) == bface->fapex)) { + flippush(flipstack, &(bface->tt)); + } + } + unflipqueue->restart(); + + } // while (1) + + if (b->verbose > 2) { + if (totalcount > 0) { + printf(" Performed %ld flips.\n", totalcount); + } + if (sliver_peels > 0) { + printf(" Removed %ld hull slivers.\n", sliver_peels); + } + if (unflipqueue->objects > 0l) { + printf(" %ld unflippable edges remained.\n", unflipqueue->objects); + } + } + + return totalcount + sliver_peels; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// recoverdelaunay() Recovery the locally Delaunay property. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::recoverdelaunay() +{ + arraypool *flipqueue, *nextflipqueue, *swapqueue; + triface tetloop, neightet, *parytet; + badface *bface, *parybface; + point *ppt; + flipconstraints fc; + int i, j; + + if (!b->quiet) { + printf("Recovering Delaunayness...\n"); + } + + tetprism_vol_sum = 0.0; // Initialize it. + + // Put all interior faces of the mesh into 'flipstack'. + tetrahedrons->traversalinit(); + tetloop.tet = tetrahedrontraverse(); + while (tetloop.tet != NULL) { + for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) { + decode(tetloop.tet[tetloop.ver], neightet); + if (!facemarked(neightet)) { + flippush(flipstack, &tetloop); + } + } + ppt = (point *) &(tetloop.tet[4]); + tetprism_vol_sum += tetprismvol(ppt[0], ppt[1], ppt[2], ppt[3]); + tetloop.tet = tetrahedrontraverse(); + } + + // Calulate a relatively lower bound for small improvement. + // Used to avoid rounding error in volume calculation. + fc.bak_tetprism_vol = tetprism_vol_sum * b->epsilon * 1e-3; + + if (b->verbose) { + printf(" Initial obj = %.17g\n", tetprism_vol_sum); + } + + if (b->verbose > 1) { + printf(" Recover Delaunay [Lawson] : %ld\n", flippool->items); + } + + // First only use the basic Lawson's flip. + fc.remove_ndelaunay_edge = 1; + fc.enqflag = 2; + + lawsonflip3d(&fc); + + if (b->verbose > 1) { + printf(" obj (after Lawson) = %.17g\n", tetprism_vol_sum); + } + + if (unflipqueue->objects == 0l) { + return; // The mesh is Delaunay. + } + + fc.unflip = 1; // Unflip if the edge is not flipped. + fc.collectnewtets = 1; // new tets are returned in 'cavetetlist'. + fc.enqflag = 0; + + autofliplinklevel = 1; // Init level. + b->fliplinklevel = -1; // No fixed level. + + // For efficiency reason, we limit the maximium size of the edge star. + int bakmaxflipstarsize = b->flipstarsize; + b->flipstarsize = 10; // default + + flipqueue = new arraypool(sizeof(badface), 10); + nextflipqueue = new arraypool(sizeof(badface), 10); + + // Swap the two flip queues. + swapqueue = flipqueue; + flipqueue = unflipqueue; + unflipqueue = swapqueue; + + while (flipqueue->objects > 0l) { + + if (b->verbose > 1) { + printf(" Recover Delaunay [level = %2d] #: %ld.\n", + autofliplinklevel, flipqueue->objects); + } + + for (i = 0; i < flipqueue->objects; i++) { + bface = (badface *) fastlookup(flipqueue, i); + if (getedge(bface->forg, bface->fdest, &bface->tt)) { + if (removeedgebyflips(&(bface->tt), &fc) == 2) { + tetprism_vol_sum += fc.tetprism_vol_sum; + fc.tetprism_vol_sum = 0.0; // Clear it. + // Queue new faces for flips. + for (j = 0; j < cavetetlist->objects; j++) { + parytet = (triface *) fastlookup(cavetetlist, j); + // A queued new tet may be dead. + if (!isdeadtet(*parytet)) { + for (parytet->ver = 0; parytet->ver < 4; parytet->ver++) { + // Avoid queue a face twice. + decode(parytet->tet[parytet->ver], neightet); + if (!facemarked(neightet)) { + flippush(flipstack, parytet); + } + } // parytet->ver + } + } // j + cavetetlist->restart(); + // Remove locally non-Delaunay faces. New non-Delaunay edges + // may be found. They are saved in 'unflipqueue'. + fc.enqflag = 2; + lawsonflip3d(&fc); + fc.enqflag = 0; + // There may be unflipable faces. Add them in flipqueue. + for (j = 0; j < unflipqueue->objects; j++) { + bface = (badface *) fastlookup(unflipqueue, j); + flipqueue->newindex((void **) &parybface); + *parybface = *bface; + } + unflipqueue->restart(); + } else { + // Unable to remove this edge. Save it. + nextflipqueue->newindex((void **) &parybface); + *parybface = *bface; + // Normally, it should be zero. + //assert(fc.tetprism_vol_sum == 0.0); + // However, due to rounding errors, a tiny value may appear. + fc.tetprism_vol_sum = 0.0; + } + } + } // i + + if (b->verbose > 1) { + printf(" obj (after level %d) = %.17g.\n", autofliplinklevel, + tetprism_vol_sum); + } + flipqueue->restart(); + + // Swap the two flip queues. + swapqueue = flipqueue; + flipqueue = nextflipqueue; + nextflipqueue = swapqueue; + + if (flipqueue->objects > 0l) { + // default 'b->delmaxfliplevel' is 1. + if (autofliplinklevel >= b->delmaxfliplevel) { + // For efficiency reason, we do not search too far. + break; + } + autofliplinklevel+=b->fliplinklevelinc; + } + } // while (flipqueue->objects > 0l) + + if (flipqueue->objects > 0l) { + if (b->verbose > 1) { + printf(" %ld non-Delaunay edges remained.\n", flipqueue->objects); + } + } + + if (b->verbose) { + printf(" Final obj = %.17g\n", tetprism_vol_sum); + } + + b->flipstarsize = bakmaxflipstarsize; + delete flipqueue; + delete nextflipqueue; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// gettetrahedron() Get a tetrahedron which have the given vertices. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::gettetrahedron(point pa, point pb, point pc, point pd, + triface *searchtet) +{ + triface spintet; + int t1ver; + + if (getedge(pa, pb, searchtet)) { + spintet = *searchtet; + while (1) { + if (apex(spintet) == pc) { + *searchtet = spintet; + break; + } + fnextself(spintet); + if (spintet.tet == searchtet->tet) break; + } + if (apex(*searchtet) == pc) { + if (oppo(*searchtet) == pd) { + return 1; + } else { + fsymself(*searchtet); + if (oppo(*searchtet) == pd) { + return 1; + } + } + } + } + + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// improvequalitybyflips() Improve the mesh quality by flips. // +// // +/////////////////////////////////////////////////////////////////////////////// + +long tetgenmesh::improvequalitybyflips() +{ + arraypool *flipqueue, *nextflipqueue, *swapqueue; + badface *bface, *parybface; + triface *parytet; + point *ppt; + flipconstraints fc; + REAL *cosdd, ncosdd[6], maxdd; + long totalremcount, remcount; + int remflag; + int n, i, j, k; + + //assert(unflipqueue->objects > 0l); + flipqueue = new arraypool(sizeof(badface), 10); + nextflipqueue = new arraypool(sizeof(badface), 10); + + // Backup flip edge options. + int bakautofliplinklevel = autofliplinklevel; + int bakfliplinklevel = b->fliplinklevel; + int bakmaxflipstarsize = b->flipstarsize; + + // Set flip edge options. + autofliplinklevel = 1; + b->fliplinklevel = -1; + b->flipstarsize = 10; // b->optmaxflipstarsize; + + fc.remove_large_angle = 1; + fc.unflip = 1; + fc.collectnewtets = 1; + fc.checkflipeligibility = 1; + + totalremcount = 0l; + + // Swap the two flip queues. + swapqueue = flipqueue; + flipqueue = unflipqueue; + unflipqueue = swapqueue; + + while (flipqueue->objects > 0l) { + + remcount = 0l; + + while (flipqueue->objects > 0l) { + if (b->verbose > 1) { + printf(" Improving mesh qualiy by flips [%d]#: %ld.\n", + autofliplinklevel, flipqueue->objects); + } + + for (k = 0; k < flipqueue->objects; k++) { + bface = (badface *) fastlookup(flipqueue, k); + if (gettetrahedron(bface->forg, bface->fdest, bface->fapex, + bface->foppo, &bface->tt)) { + //assert(!ishulltet(bface->tt)); + // There are bad dihedral angles in this tet. + if (bface->tt.ver != 11) { + // The dihedral angles are permuted. + // Here we simply re-compute them. Slow!!. + ppt = (point *) & (bface->tt.tet[4]); + tetalldihedral(ppt[0], ppt[1], ppt[2], ppt[3], bface->cent, + &bface->key, NULL); + bface->forg = ppt[0]; + bface->fdest = ppt[1]; + bface->fapex = ppt[2]; + bface->foppo = ppt[3]; + bface->tt.ver = 11; + } + if (bface->key == 0) { + // Re-comput the quality values. Due to smoothing operations. + ppt = (point *) & (bface->tt.tet[4]); + tetalldihedral(ppt[0], ppt[1], ppt[2], ppt[3], bface->cent, + &bface->key, NULL); + } + cosdd = bface->cent; + remflag = 0; + for (i = 0; (i < 6) && !remflag; i++) { + if (cosdd[i] < cosmaxdihed) { + // Found a large dihedral angle. + bface->tt.ver = edge2ver[i]; // Go to the edge. + fc.cosdihed_in = cosdd[i]; + fc.cosdihed_out = 0.0; // 90 degree. + n = removeedgebyflips(&(bface->tt), &fc); + if (n == 2) { + // Edge is flipped. + remflag = 1; + if (fc.cosdihed_out < cosmaxdihed) { + // Queue new bad tets for further improvements. + for (j = 0; j < cavetetlist->objects; j++) { + parytet = (triface *) fastlookup(cavetetlist, j); + if (!isdeadtet(*parytet)) { + ppt = (point *) & (parytet->tet[4]); + // Do not test a hull tet. + if (ppt[3] != dummypoint) { + tetalldihedral(ppt[0], ppt[1], ppt[2], ppt[3], ncosdd, + &maxdd, NULL); + if (maxdd < cosmaxdihed) { + // There are bad dihedral angles in this tet. + nextflipqueue->newindex((void **) &parybface); + parybface->tt.tet = parytet->tet; + parybface->tt.ver = 11; + parybface->forg = ppt[0]; + parybface->fdest = ppt[1]; + parybface->fapex = ppt[2]; + parybface->foppo = ppt[3]; + parybface->key = maxdd; + for (n = 0; n < 6; n++) { + parybface->cent[n] = ncosdd[n]; + } + } + } // if (ppt[3] != dummypoint) + } + } // j + } // if (fc.cosdihed_out < cosmaxdihed) + cavetetlist->restart(); + remcount++; + } + } + } // i + if (!remflag) { + // An unremoved bad tet. Queue it again. + unflipqueue->newindex((void **) &parybface); + *parybface = *bface; + } + } // if (gettetrahedron(...)) + } // k + + flipqueue->restart(); + + // Swap the two flip queues. + swapqueue = flipqueue; + flipqueue = nextflipqueue; + nextflipqueue = swapqueue; + } // while (flipqueues->objects > 0) + + if (b->verbose > 1) { + printf(" Removed %ld bad tets.\n", remcount); + } + totalremcount += remcount; + + if (unflipqueue->objects > 0l) { + //if (autofliplinklevel >= b->optmaxfliplevel) { + if (autofliplinklevel >= b->optlevel) { + break; + } + autofliplinklevel+=b->fliplinklevelinc; + //b->flipstarsize = 10 + (1 << (b->optlevel - 1)); + } + + // Swap the two flip queues. + swapqueue = flipqueue; + flipqueue = unflipqueue; + unflipqueue = swapqueue; + } // while (flipqueues->objects > 0) + + // Restore original flip edge options. + autofliplinklevel = bakautofliplinklevel; + b->fliplinklevel = bakfliplinklevel; + b->flipstarsize = bakmaxflipstarsize; + + delete flipqueue; + delete nextflipqueue; + + return totalremcount; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// smoothpoint() Moving a vertex to improve the mesh quality. // +// // +// 'smtpt' (p) is a point to be smoothed. Generally, it is a Steiner point. // +// It may be not a vertex of the mesh. // +// // +// This routine tries to move 'p' inside its star until a selected objective // +// function over all tetrahedra in the star is improved. The function may be // +// the some quality measures, i.e., aspect ratio, maximum dihedral angel, or // +// simply the volume of the tetrahedra. // +// // +// 'linkfacelist' contains the list of link faces of 'p'. Since a link face // +// has two orientations, ccw or cw, with respect to 'p'. 'ccw' indicates // +// the orientation is ccw (1) or not (0). // +// // +// 'opm' is a structure contains the parameters of the objective function. // +// It is needed by the evaluation of the function value. // +// // +// The return value indicates weather the point is smoothed or not. // +// // +// ASSUMPTION: This routine assumes that all link faces are true faces, i.e, // +// no face has 'dummypoint' as its vertex. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::smoothpoint(point smtpt, arraypool *linkfacelist, int ccw, + optparameters *opm) +{ + triface *parytet, *parytet1, swaptet; + point pa, pb, pc; + REAL fcent[3], startpt[3], nextpt[3], bestpt[3]; + REAL oldval, minval = 0.0, val; + REAL maxcosd; // oldang, newang; + REAL ori, diff; + int numdirs, iter; + int i, j, k; + + // Decide the number of moving directions. + numdirs = (int) linkfacelist->objects; + if (numdirs > opm->numofsearchdirs) { + numdirs = opm->numofsearchdirs; // Maximum search directions. + } + + // Set the initial value. + if (!opm->max_min_volume) { + assert(opm->initval >= 0.0); + } + opm->imprval = opm->initval; + iter = 0; + + for (i = 0; i < 3; i++) { + bestpt[i] = startpt[i] = smtpt[i]; + } + + // Iterate until the obj function is not improved. + while (1) { + + // Find the best next location. + oldval = opm->imprval; + + for (i = 0; i < numdirs; i++) { + // Randomly pick a link face (0 <= k <= objects - i - 1). + k = (int) randomnation(linkfacelist->objects - i); + parytet = (triface *) fastlookup(linkfacelist, k); + // Calculate a new position from 'p' to the center of this face. + pa = org(*parytet); + pb = dest(*parytet); + pc = apex(*parytet); + for (j = 0; j < 3; j++) { + fcent[j] = (pa[j] + pb[j] + pc[j]) / 3.0; + } + for (j = 0; j < 3; j++) { + nextpt[j] = startpt[j] + opm->searchstep * (fcent[j] - startpt[j]); + } + // Calculate the largest minimum function value for the new location. + for (j = 0; j < linkfacelist->objects; j++) { + parytet = (triface *) fastlookup(linkfacelist, j); + if (ccw) { + pa = org(*parytet); + pb = dest(*parytet); + } else { + pb = org(*parytet); + pa = dest(*parytet); + } + pc = apex(*parytet); + ori = orient3d(pa, pb, pc, nextpt); + if (ori < 0.0) { + // Calcuate the objective function value. + if (opm->max_min_volume) { + //val = -ori; + val = - orient3dfast(pa, pb, pc, nextpt); + } else if (opm->max_min_aspectratio) { + val = tetaspectratio(pa, pb, pc, nextpt); + } else if (opm->min_max_dihedangle) { + tetalldihedral(pa, pb, pc, nextpt, NULL, &maxcosd, NULL); + if (maxcosd < -1) maxcosd = -1.0; // Rounding. + val = maxcosd + 1.0; // Make it be positive. + } else { + // Unknown objective function. + val = 0.0; + } + } else { // ori >= 0.0; + // An invalid new tet. + // This may happen if the mesh contains inverted elements. + if (opm->max_min_volume) { + //val = -ori; + val = - orient3dfast(pa, pb, pc, nextpt); + } else { + // Discard this point. + break; // j + } + } // if (ori >= 0.0) + // Stop looping when the object value is not improved. + if (val <= opm->imprval) { + break; // j + } else { + // Remember the smallest improved value. + if (j == 0) { + minval = val; + } else { + minval = (val < minval) ? val : minval; + } + } + } // j + if (j == linkfacelist->objects) { + // The function value has been improved. + opm->imprval = minval; + // Save the new location of the point. + for (j = 0; j < 3; j++) bestpt[j] = nextpt[j]; + } + // Swap k-th and (object-i-1)-th entries. + j = linkfacelist->objects - i - 1; + parytet = (triface *) fastlookup(linkfacelist, k); + parytet1 = (triface *) fastlookup(linkfacelist, j); + swaptet = *parytet1; + *parytet1 = *parytet; + *parytet = swaptet; + } // i + + diff = opm->imprval - oldval; + if (diff > 0.0) { + // Is the function value improved effectively? + if (opm->max_min_volume) { + //if ((diff / oldval) < b->epsilon) diff = 0.0; + } else if (opm->max_min_aspectratio) { + if ((diff / oldval) < 1e-3) diff = 0.0; + } else if (opm->min_max_dihedangle) { + //oldang = acos(oldval - 1.0); + //newang = acos(opm->imprval - 1.0); + //if ((oldang - newang) < 0.00174) diff = 0.0; // about 0.1 degree. + } else { + // Unknown objective function. + assert(0); // Not possible. + } + } + + if (diff > 0.0) { + // Yes, move p to the new location and continue. + for (j = 0; j < 3; j++) startpt[j] = bestpt[j]; + iter++; + if ((opm->maxiter > 0) && (iter >= opm->maxiter)) { + // Maximum smoothing iterations reached. + break; + } + } else { + break; + } + + } // while (1) + + if (iter > 0) { + // The point has been smoothed. + opm->smthiter = iter; // Remember the number of iterations. + // The point has been smoothed. Update it to its new position. + for (i = 0; i < 3; i++) smtpt[i] = startpt[i]; + } + + return iter; +} + + +/////////////////////////////////////////////////////////////////////////////// +// // +// improvequalitysmoothing() Improve mesh quality by smoothing. // +// // +/////////////////////////////////////////////////////////////////////////////// + +long tetgenmesh::improvequalitybysmoothing(optparameters *opm) +{ + arraypool *flipqueue, *swapqueue; + triface *parytet; + badface *bface, *parybface; + point *ppt; + long totalsmtcount, smtcount; + int smtflag; + int iter, i, j, k; + + //assert(unflipqueue->objects > 0l); + flipqueue = new arraypool(sizeof(badface), 10); + + // Swap the two flip queues. + swapqueue = flipqueue; + flipqueue = unflipqueue; + unflipqueue = swapqueue; + + totalsmtcount = 0l; + iter = 0; + + while (flipqueue->objects > 0l) { + + smtcount = 0l; + + if (b->verbose > 1) { + printf(" Improving mesh quality by smoothing [%d]#: %ld.\n", + iter, flipqueue->objects); + } + + for (k = 0; k < flipqueue->objects; k++) { + bface = (badface *) fastlookup(flipqueue, k); + if (gettetrahedron(bface->forg, bface->fdest, bface->fapex, + bface->foppo, &bface->tt)) { + // Operate on it if it is not in 'unflipqueue'. + if (!marktested(bface->tt)) { + // Here we simply re-compute the quality. Since other smoothing + // operation may have moved the vertices of this tet. + ppt = (point *) & (bface->tt.tet[4]); + tetalldihedral(ppt[0], ppt[1], ppt[2], ppt[3], bface->cent, + &bface->key, NULL); + if (bface->key < cossmtdihed) { // if (maxdd < cosslidihed) { + // It is a sliver. Try to smooth its vertices. + smtflag = 0; + opm->initval = bface->key + 1.0; + for (i = 0; (i < 4) && !smtflag; i++) { + if (pointtype(ppt[i]) == FREEVOLVERTEX) { + getvertexstar(1, ppt[i], cavetetlist, NULL, NULL); + opm->searchstep = 0.001; // Search step size + smtflag = smoothpoint(ppt[i], cavetetlist, 1, opm); + if (smtflag) { + while (opm->smthiter == opm->maxiter) { + opm->searchstep *= 10.0; // Increase the step size. + opm->initval = opm->imprval; + opm->smthiter = 0; // reset + smoothpoint(ppt[i], cavetetlist, 1, opm); + } + // This tet is modifed. + smtcount++; + if ((opm->imprval - 1.0) < cossmtdihed) { + // There are slivers in new tets. Queue them. + for (j = 0; j < cavetetlist->objects; j++) { + parytet = (triface *) fastlookup(cavetetlist, j); + assert(!isdeadtet(*parytet)); + // Operate it if it is not in 'unflipqueue'. + if (!marktested(*parytet)) { + // Evaluate its quality. + // Re-use ppt, bface->key, bface->cent. + ppt = (point *) & (parytet->tet[4]); + tetalldihedral(ppt[0], ppt[1], ppt[2], ppt[3], + bface->cent, &bface->key, NULL); + if (bface->key < cossmtdihed) { + // A new sliver. Queue it. + marktest(*parytet); // It is in unflipqueue. + unflipqueue->newindex((void **) &parybface); + parybface->tt = *parytet; + parybface->forg = ppt[0]; + parybface->fdest = ppt[1]; + parybface->fapex = ppt[2]; + parybface->foppo = ppt[3]; + parybface->tt.ver = 11; + parybface->key = 0.0; + } + } + } // j + } // if ((opm->imprval - 1.0) < cossmtdihed) + } // if (smtflag) + cavetetlist->restart(); + } // if (pointtype(ppt[i]) == FREEVOLVERTEX) + } // i + if (!smtflag) { + // Didn't smooth. Queue it again. + marktest(bface->tt); // It is in unflipqueue. + unflipqueue->newindex((void **) &parybface); + parybface->tt = bface->tt; + parybface->forg = ppt[0]; + parybface->fdest = ppt[1]; + parybface->fapex = ppt[2]; + parybface->foppo = ppt[3]; + parybface->tt.ver = 11; + parybface->key = 0.0; + } + } // if (maxdd < cosslidihed) + } // if (!marktested(...)) + } // if (gettetrahedron(...)) + } // k + + flipqueue->restart(); + + // Unmark the tets in unflipqueue. + for (i = 0; i < unflipqueue->objects; i++) { + bface = (badface *) fastlookup(unflipqueue, i); + unmarktest(bface->tt); + } + + if (b->verbose > 1) { + printf(" Smooth %ld points.\n", smtcount); + } + totalsmtcount += smtcount; + + if (smtcount == 0l) { + // No point has been smoothed. + break; + } else { + iter++; + if (iter == 2) { //if (iter >= b->optpasses) { + break; + } + } + + // Swap the two flip queues. + swapqueue = flipqueue; + flipqueue = unflipqueue; + unflipqueue = swapqueue; + } // while + + delete flipqueue; + + return totalsmtcount; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// splitsliver() Split a sliver. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::splitsliver(triface *slitet, REAL cosd, int chkencflag) +{ + triface *abtets; + triface searchtet, spintet, *parytet; + point pa, pb, steinerpt; + optparameters opm; + insertvertexflags ivf; + REAL smtpt[3], midpt[3]; + int success; + int t1ver; + int n, i; + + // 'slitet' is [c,d,a,b], where [c,d] has a big dihedral angle. + // Go to the opposite edge [a,b]. + edestoppo(*slitet, searchtet); // [a,b,c,d]. + + // Do not split a segment. + if (issubseg(searchtet)) { + return 0; + } + + // Count the number of tets shared at [a,b]. + // Do not split it if it is a hull edge. + spintet = searchtet; + n = 0; + while (1) { + if (ishulltet(spintet)) break; + n++; + fnextself(spintet); + if (spintet.tet == searchtet.tet) break; + } + if (ishulltet(spintet)) { + return 0; // It is a hull edge. + } + assert(n >= 3); + + // Get all tets at edge [a,b]. + abtets = new triface[n]; + spintet = searchtet; + for (i = 0; i < n; i++) { + abtets[i] = spintet; + fnextself(spintet); + } + + // Initialize the list of 2n boundary faces. + for (i = 0; i < n; i++) { + eprev(abtets[i], searchtet); + esymself(searchtet); // [a,p_i,p_i+1]. + cavetetlist->newindex((void **) &parytet); + *parytet = searchtet; + enext(abtets[i], searchtet); + esymself(searchtet); // [p_i,b,p_i+1]. + cavetetlist->newindex((void **) &parytet); + *parytet = searchtet; + } + + // Init the Steiner point at the midpoint of edge [a,b]. + pa = org(abtets[0]); + pb = dest(abtets[0]); + for (i = 0; i < 3; i++) { + smtpt[i] = midpt[i] = 0.5 * (pa[i] + pb[i]); + } + + // Point smooth options. + opm.min_max_dihedangle = 1; + opm.initval = cosd + 1.0; // Initial volume is zero. + opm.numofsearchdirs = 20; + opm.searchstep = 0.001; + opm.maxiter = 100; // Limit the maximum iterations. + + success = smoothpoint(smtpt, cavetetlist, 1, &opm); + + if (success) { + while (opm.smthiter == opm.maxiter) { + // It was relocated and the prescribed maximum iteration reached. + // Try to increase the search stepsize. + opm.searchstep *= 10.0; + //opm.maxiter = 100; // Limit the maximum iterations. + opm.initval = opm.imprval; + opm.smthiter = 0; // Init. + smoothpoint(smtpt, cavetetlist, 1, &opm); + } + } // if (success) + + cavetetlist->restart(); + + if (!success) { + delete [] abtets; + return 0; + } + + + // Insert the Steiner point. + makepoint(&steinerpt, FREEVOLVERTEX); + for (i = 0; i < 3; i++) steinerpt[i] = smtpt[i]; + + // Insert the created Steiner point. + for (i = 0; i < n; i++) { + infect(abtets[i]); + caveoldtetlist->newindex((void **) &parytet); + *parytet = abtets[i]; + } + + searchtet = abtets[0]; // No need point location. + if (b->metric) { + locate(steinerpt, &searchtet); // For size interpolation. + } + + delete [] abtets; + + ivf.iloc = (int) INSTAR; + ivf.chkencflag = chkencflag; + ivf.assignmeshsize = b->metric; + + + if (insertpoint(steinerpt, &searchtet, NULL, NULL, &ivf)) { + // The vertex has been inserted. + st_volref_count++; + if (steinerleft > 0) steinerleft--; + return 1; + } else { + // The Steiner point is too close to an existing vertex. Reject it. + pointdealloc(steinerpt); + return 0; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// removeslivers() Remove slivers by adding Steiner points. // +// // +/////////////////////////////////////////////////////////////////////////////// + +long tetgenmesh::removeslivers(int chkencflag) +{ + arraypool *flipqueue, *swapqueue; + badface *bface, *parybface; + triface slitet, *parytet; + point *ppt; + REAL cosdd[6], maxcosd; + long totalsptcount, sptcount; + int iter, i, j, k; + + //assert(unflipqueue->objects > 0l); + flipqueue = new arraypool(sizeof(badface), 10); + + // Swap the two flip queues. + swapqueue = flipqueue; + flipqueue = unflipqueue; + unflipqueue = swapqueue; + + totalsptcount = 0l; + iter = 0; + + while ((flipqueue->objects > 0l) && (steinerleft != 0)) { + + sptcount = 0l; + + if (b->verbose > 1) { + printf(" Splitting bad quality tets [%d]#: %ld.\n", + iter, flipqueue->objects); + } + + for (k = 0; (k < flipqueue->objects) && (steinerleft != 0); k++) { + bface = (badface *) fastlookup(flipqueue, k); + if (gettetrahedron(bface->forg, bface->fdest, bface->fapex, + bface->foppo, &bface->tt)) { + if ((bface->key == 0) || (bface->tt.ver != 11)) { + // Here we need to re-compute the quality. Since other smoothing + // operation may have moved the vertices of this tet. + ppt = (point *) & (bface->tt.tet[4]); + tetalldihedral(ppt[0], ppt[1], ppt[2], ppt[3], bface->cent, + &bface->key, NULL); + } + if (bface->key < cosslidihed) { + // It is a sliver. Try to split it. + slitet.tet = bface->tt.tet; + //cosdd = bface->cent; + for (j = 0; j < 6; j++) { + if (bface->cent[j] < cosslidihed) { + // Found a large dihedral angle. + slitet.ver = edge2ver[j]; // Go to the edge. + if (splitsliver(&slitet, bface->cent[j], chkencflag)) { + sptcount++; + break; + } + } + } // j + if (j < 6) { + // A sliver is split. Queue new slivers. + badtetrahedrons->traversalinit(); + parytet = (triface *) badtetrahedrons->traverse(); + while (parytet != NULL) { + unmarktest2(*parytet); + ppt = (point *) & (parytet->tet[4]); + tetalldihedral(ppt[0], ppt[1], ppt[2], ppt[3], cosdd, + &maxcosd, NULL); + if (maxcosd < cosslidihed) { + // A new sliver. Queue it. + unflipqueue->newindex((void **) &parybface); + parybface->forg = ppt[0]; + parybface->fdest = ppt[1]; + parybface->fapex = ppt[2]; + parybface->foppo = ppt[3]; + parybface->tt.tet = parytet->tet; + parybface->tt.ver = 11; + parybface->key = maxcosd; + for (i = 0; i < 6; i++) { + parybface->cent[i] = cosdd[i]; + } + } + parytet = (triface *) badtetrahedrons->traverse(); + } + badtetrahedrons->restart(); + } else { + // Didn't split. Queue it again. + unflipqueue->newindex((void **) &parybface); + *parybface = *bface; + } // if (j == 6) + } // if (bface->key < cosslidihed) + } // if (gettetrahedron(...)) + } // k + + flipqueue->restart(); + + if (b->verbose > 1) { + printf(" Split %ld tets.\n", sptcount); + } + totalsptcount += sptcount; + + if (sptcount == 0l) { + // No point has been smoothed. + break; + } else { + iter++; + if (iter == 2) { //if (iter >= b->optpasses) { + break; + } + } + + // Swap the two flip queues. + swapqueue = flipqueue; + flipqueue = unflipqueue; + unflipqueue = swapqueue; + } // while + + delete flipqueue; + + return totalsptcount; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// optimizemesh() Optimize mesh for specified objective functions. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::optimizemesh() +{ + badface *parybface; + triface checktet; + point *ppt; + int optpasses; + optparameters opm; + REAL ncosdd[6], maxdd; + long totalremcount, remcount; + long totalsmtcount, smtcount; + long totalsptcount, sptcount; + int chkencflag; + int iter; + int n; + + if (!b->quiet) { + printf("Optimizing mesh...\n"); + } + + optpasses = ((1 << b->optlevel) - 1); + + if (b->verbose) { + printf(" Optimization level = %d.\n", b->optlevel); + printf(" Optimization scheme = %d.\n", b->optscheme); + printf(" Number of iteration = %d.\n", optpasses); + printf(" Min_Max dihed angle = %g.\n", b->optmaxdihedral); + } + + totalsmtcount = totalsptcount = totalremcount = 0l; + + cosmaxdihed = cos(b->optmaxdihedral / 180.0 * PI); + cossmtdihed = cos(b->optminsmtdihed / 180.0 * PI); + cosslidihed = cos(b->optminslidihed / 180.0 * PI); + + int attrnum = numelemattrib - 1; + + // Put all bad tetrahedra into array. + tetrahedrons->traversalinit(); + checktet.tet = tetrahedrontraverse(); + while (checktet.tet != NULL) { + if (b->convex) { // -c + // Skip this tet if it lies in the exterior. + if (elemattribute(checktet.tet, attrnum) == -1.0) { + checktet.tet = tetrahedrontraverse(); + continue; + } + } + ppt = (point *) & (checktet.tet[4]); + tetalldihedral(ppt[0], ppt[1], ppt[2], ppt[3], ncosdd, &maxdd, NULL); + if (maxdd < cosmaxdihed) { + // There are bad dihedral angles in this tet. + unflipqueue->newindex((void **) &parybface); + parybface->tt.tet = checktet.tet; + parybface->tt.ver = 11; + parybface->forg = ppt[0]; + parybface->fdest = ppt[1]; + parybface->fapex = ppt[2]; + parybface->foppo = ppt[3]; + parybface->key = maxdd; + for (n = 0; n < 6; n++) { + parybface->cent[n] = ncosdd[n]; + } + } + checktet.tet = tetrahedrontraverse(); + } + + totalremcount = improvequalitybyflips(); + + if ((unflipqueue->objects > 0l) && + ((b->optscheme & 2) || (b->optscheme & 4))) { + // The pool is only used by removeslivers(). + badtetrahedrons = new memorypool(sizeof(triface), b->tetrahedraperblock, + sizeof(void *), 0); + + // Smoothing options. + opm.min_max_dihedangle = 1; + opm.numofsearchdirs = 10; + // opm.searchstep = 0.001; + opm.maxiter = 30; // Limit the maximum iterations. + //opm.checkencflag = 4; // Queue affected tets after smoothing. + chkencflag = 4; // Queue affected tets after splitting a sliver. + iter = 0; + + while (iter < optpasses) { + smtcount = sptcount = remcount = 0l; + if (b->optscheme & 2) { + smtcount += improvequalitybysmoothing(&opm); + totalsmtcount += smtcount; + if (smtcount > 0l) { + remcount = improvequalitybyflips(); + totalremcount += remcount; + } + } + if (unflipqueue->objects > 0l) { + if (b->optscheme & 4) { + sptcount += removeslivers(chkencflag); + totalsptcount += sptcount; + if (sptcount > 0l) { + remcount = improvequalitybyflips(); + totalremcount += remcount; + } + } + } + if (unflipqueue->objects > 0l) { + if (remcount > 0l) { + iter++; + } else { + break; + } + } else { + break; + } + } // while (iter) + + delete badtetrahedrons; + + } + + if (unflipqueue->objects > 0l) { + if (b->verbose > 1) { + printf(" %ld bad tets remained.\n", unflipqueue->objects); + } + unflipqueue->restart(); + } + + if (b->verbose) { + if (totalremcount > 0l) { + printf(" Removed %ld edges.\n", totalremcount); + } + if (totalsmtcount > 0l) { + printf(" Smoothed %ld points.\n", totalsmtcount); + } + if (totalsptcount > 0l) { + printf(" Split %ld slivers.\n", totalsptcount); + } + } +} + +//// //// +//// //// +//// optimize_cxx ///////////////////////////////////////////////////////////// + +//// meshstat_cxx ///////////////////////////////////////////////////////////// +//// //// +//// //// + +/////////////////////////////////////////////////////////////////////////////// +// // +// printfcomma() Print a (large) number with the 'thousands separator'. // +// // +// The following code was simply copied from "stackoverflow". // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::printfcomma(unsigned long n) +{ + unsigned long n2 = 0; + int scale = 1; + while (n >= 1000) { + n2 = n2 + scale * (n % 1000); + n /= 1000; + scale *= 1000; + } + printf ("%ld", n); + while (scale != 1) { + scale /= 1000; + n = n2 / scale; + n2 = n2 % scale; + printf (",%03ld", n); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// checkmesh() Test the mesh for topological consistency. // +// // +// If 'topoflag' is set, only check the topological connection of the mesh, // +// i.e., do not report degenerated or inverted elements. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::checkmesh(int topoflag) +{ + triface tetloop, neightet, symtet; + point pa, pb, pc, pd; + REAL ori; + int horrors, i; + + if (!b->quiet) { + printf(" Checking consistency of mesh...\n"); + } + + horrors = 0; + tetloop.ver = 0; + // Run through the list of tetrahedra, checking each one. + tetrahedrons->traversalinit(); + tetloop.tet = alltetrahedrontraverse(); + while (tetloop.tet != (tetrahedron *) NULL) { + // Check all four faces of the tetrahedron. + for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) { + pa = org(tetloop); + pb = dest(tetloop); + pc = apex(tetloop); + pd = oppo(tetloop); + if (tetloop.ver == 0) { // Only test for inversion once. + if (!ishulltet(tetloop)) { // Only do test if it is not a hull tet. + if (!topoflag) { + ori = orient3d(pa, pb, pc, pd); + if (ori >= 0.0) { + printf(" !! !! %s ", ori > 0.0 ? "Inverted" : "Degenerated"); + printf(" (%d, %d, %d, %d) (ori = %.17g)\n", pointmark(pa), + pointmark(pb), pointmark(pc), pointmark(pd), ori); + horrors++; + } + } + } + if (infected(tetloop)) { + // This may be a bug. Report it. + printf(" !! (%d, %d, %d, %d) is infected.\n", pointmark(pa), + pointmark(pb), pointmark(pc), pointmark(pd)); + horrors++; + } + if (marktested(tetloop)) { + // This may be a bug. Report it. + printf(" !! (%d, %d, %d, %d) is marked.\n", pointmark(pa), + pointmark(pb), pointmark(pc), pointmark(pd)); + horrors++; + } + } + if (tetloop.tet[tetloop.ver] == NULL) { + printf(" !! !! No neighbor at face (%d, %d, %d).\n", pointmark(pa), + pointmark(pb), pointmark(pc)); + horrors++; + } else { + // Find the neighboring tetrahedron on this face. + fsym(tetloop, neightet); + // Check that the tetrahedron's neighbor knows it's a neighbor. + fsym(neightet, symtet); + if ((tetloop.tet != symtet.tet) || (tetloop.ver != symtet.ver)) { + printf(" !! !! Asymmetric tetra-tetra bond:\n"); + if (tetloop.tet == symtet.tet) { + printf(" (Right tetrahedron, wrong orientation)\n"); + } + printf(" First: (%d, %d, %d, %d)\n", pointmark(pa), + pointmark(pb), pointmark(pc), pointmark(pd)); + printf(" Second: (%d, %d, %d, %d)\n", pointmark(org(neightet)), + pointmark(dest(neightet)), pointmark(apex(neightet)), + pointmark(oppo(neightet))); + horrors++; + } + // Check if they have the same edge (the bond() operation). + if ((org(neightet) != pb) || (dest(neightet) != pa)) { + printf(" !! !! Wrong edge-edge bond:\n"); + printf(" First: (%d, %d, %d, %d)\n", pointmark(pa), + pointmark(pb), pointmark(pc), pointmark(pd)); + printf(" Second: (%d, %d, %d, %d)\n", pointmark(org(neightet)), + pointmark(dest(neightet)), pointmark(apex(neightet)), + pointmark(oppo(neightet))); + horrors++; + } + // Check if they have the same apex. + if (apex(neightet) != pc) { + printf(" !! !! Wrong face-face bond:\n"); + printf(" First: (%d, %d, %d, %d)\n", pointmark(pa), + pointmark(pb), pointmark(pc), pointmark(pd)); + printf(" Second: (%d, %d, %d, %d)\n", pointmark(org(neightet)), + pointmark(dest(neightet)), pointmark(apex(neightet)), + pointmark(oppo(neightet))); + horrors++; + } + // Check if they have the same opposite. + if (oppo(neightet) == pd) { + printf(" !! !! Two identical tetra:\n"); + printf(" First: (%d, %d, %d, %d)\n", pointmark(pa), + pointmark(pb), pointmark(pc), pointmark(pd)); + printf(" Second: (%d, %d, %d, %d)\n", pointmark(org(neightet)), + pointmark(dest(neightet)), pointmark(apex(neightet)), + pointmark(oppo(neightet))); + horrors++; + } + } + if (facemarked(tetloop)) { + // This may be a bug. Report it. + printf(" !! tetface (%d, %d, %d) %d is marked.\n", pointmark(pa), + pointmark(pb), pointmark(pc), pointmark(pd)); + } + } + // Check the six edges of this tet. + for (i = 0; i < 6; i++) { + tetloop.ver = edge2ver[i]; + if (edgemarked(tetloop)) { + // This may be a bug. Report it. + printf(" !! tetedge (%d, %d) %d, %d is marked.\n", + pointmark(org(tetloop)), pointmark(dest(tetloop)), + pointmark(apex(tetloop)), pointmark(oppo(tetloop))); + } + } + tetloop.tet = alltetrahedrontraverse(); + } + if (horrors == 0) { + if (!b->quiet) { + printf(" In my studied opinion, the mesh appears to be consistent.\n"); + } + } else { + printf(" !! !! !! !! %d %s witnessed.\n", horrors, + horrors > 1 ? "abnormity" : "abnormities"); + } + + return horrors; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// checkshells() Test the boundary mesh for topological consistency. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::checkshells() +{ + triface neightet, symtet; + face shloop, spinsh, nextsh; + face checkseg; + point pa, pb; + int bakcount; + int horrors, i; + + if (!b->quiet) { + printf(" Checking consistency of the mesh boundary...\n"); + } + horrors = 0; + + void **bakpathblock = subfaces->pathblock; + void *bakpathitem = subfaces->pathitem; + int bakpathitemsleft = subfaces->pathitemsleft; + int bakalignbytes = subfaces->alignbytes; + + subfaces->traversalinit(); + shloop.sh = shellfacetraverse(subfaces); + while (shloop.sh != NULL) { + shloop.shver = 0; + for (i = 0; i < 3; i++) { + // Check the face ring at this edge. + pa = sorg(shloop); + pb = sdest(shloop); + spinsh = shloop; + spivot(spinsh, nextsh); + bakcount = horrors; + while ((nextsh.sh != NULL) && (nextsh.sh != shloop.sh)) { + if (nextsh.sh[3] == NULL) { + printf(" !! !! Wrong subface-subface connection (Dead subface).\n"); + printf(" First: x%lx (%d, %d, %d).\n", (uintptr_t) spinsh.sh, + pointmark(sorg(spinsh)), pointmark(sdest(spinsh)), + pointmark(sapex(spinsh))); + printf(" Second: x%lx (DEAD)\n", (uintptr_t) nextsh.sh); + horrors++; + break; + } + // check if they have the same edge. + if (!(((sorg(nextsh) == pa) && (sdest(nextsh) == pb)) || + ((sorg(nextsh) == pb) && (sdest(nextsh) == pa)))) { + printf(" !! !! Wrong subface-subface connection.\n"); + printf(" First: x%lx (%d, %d, %d).\n", (uintptr_t) spinsh.sh, + pointmark(sorg(spinsh)), pointmark(sdest(spinsh)), + pointmark(sapex(spinsh))); + printf(" Scond: x%lx (%d, %d, %d).\n", (uintptr_t) nextsh.sh, + pointmark(sorg(nextsh)), pointmark(sdest(nextsh)), + pointmark(sapex(nextsh))); + horrors++; + break; + } + // Check they should not have the same apex. + if (sapex(nextsh) == sapex(spinsh)) { + printf(" !! !! Existing two duplicated subfaces.\n"); + printf(" First: x%lx (%d, %d, %d).\n", (uintptr_t) spinsh.sh, + pointmark(sorg(spinsh)), pointmark(sdest(spinsh)), + pointmark(sapex(spinsh))); + printf(" Scond: x%lx (%d, %d, %d).\n", (uintptr_t) nextsh.sh, + pointmark(sorg(nextsh)), pointmark(sdest(nextsh)), + pointmark(sapex(nextsh))); + horrors++; + break; + } + spinsh = nextsh; + spivot(spinsh, nextsh); + } + // Check subface-subseg bond. + sspivot(shloop, checkseg); + if (checkseg.sh != NULL) { + if (checkseg.sh[3] == NULL) { + printf(" !! !! Wrong subface-subseg connection (Dead subseg).\n"); + printf(" Sub: x%lx (%d, %d, %d).\n", (uintptr_t) shloop.sh, + pointmark(sorg(shloop)), pointmark(sdest(shloop)), + pointmark(sapex(shloop))); + printf(" Sub: x%lx (Dead)\n", (uintptr_t) checkseg.sh); + horrors++; + } else { + if (!(((sorg(checkseg) == pa) && (sdest(checkseg) == pb)) || + ((sorg(checkseg) == pb) && (sdest(checkseg) == pa)))) { + printf(" !! !! Wrong subface-subseg connection.\n"); + printf(" Sub: x%lx (%d, %d, %d).\n", (uintptr_t) shloop.sh, + pointmark(sorg(shloop)), pointmark(sdest(shloop)), + pointmark(sapex(shloop))); + printf(" Seg: x%lx (%d, %d).\n", (uintptr_t) checkseg.sh, + pointmark(sorg(checkseg)), pointmark(sdest(checkseg))); + horrors++; + } + } + } + if (horrors > bakcount) break; // An error detected. + senextself(shloop); + } + // Check tet-subface connection. + stpivot(shloop, neightet); + if (neightet.tet != NULL) { + if (neightet.tet[4] == NULL) { + printf(" !! !! Wrong sub-to-tet connection (Dead tet)\n"); + printf(" Sub: x%lx (%d, %d, %d).\n", (uintptr_t) shloop.sh, + pointmark(sorg(shloop)), pointmark(sdest(shloop)), + pointmark(sapex(shloop))); + printf(" Tet: x%lx (DEAD)\n", (uintptr_t) neightet.tet); + horrors++; + } else { + if (!((sorg(shloop) == org(neightet)) && + (sdest(shloop) == dest(neightet)))) { + printf(" !! !! Wrong sub-to-tet connection\n"); + printf(" Sub: x%lx (%d, %d, %d).\n", (uintptr_t) shloop.sh, + pointmark(sorg(shloop)), pointmark(sdest(shloop)), + pointmark(sapex(shloop))); + printf(" Tet: x%lx (%d, %d, %d, %d).\n", + (uintptr_t) neightet.tet, pointmark(org(neightet)), + pointmark(dest(neightet)), pointmark(apex(neightet)), + pointmark(oppo(neightet))); + horrors++; + } + tspivot(neightet, spinsh); + if (!((sorg(spinsh) == org(neightet)) && + (sdest(spinsh) == dest(neightet)))) { + printf(" !! !! Wrong tet-sub connection.\n"); + printf(" Sub: x%lx (%d, %d, %d).\n", (uintptr_t) spinsh.sh, + pointmark(sorg(spinsh)), pointmark(sdest(spinsh)), + pointmark(sapex(spinsh))); + printf(" Tet: x%lx (%d, %d, %d, %d).\n", + (uintptr_t) neightet.tet, pointmark(org(neightet)), + pointmark(dest(neightet)), pointmark(apex(neightet)), + pointmark(oppo(neightet))); + horrors++; + } + fsym(neightet, symtet); + tspivot(symtet, spinsh); + if (spinsh.sh != NULL) { + if (!((sorg(spinsh) == org(symtet)) && + (sdest(spinsh) == dest(symtet)))) { + printf(" !! !! Wrong tet-sub connection.\n"); + printf(" Sub: x%lx (%d, %d, %d).\n", (uintptr_t) spinsh.sh, + pointmark(sorg(spinsh)), pointmark(sdest(spinsh)), + pointmark(sapex(spinsh))); + printf(" Tet: x%lx (%d, %d, %d, %d).\n", + (uintptr_t) symtet.tet, pointmark(org(symtet)), + pointmark(dest(symtet)), pointmark(apex(symtet)), + pointmark(oppo(symtet))); + horrors++; + } + } else { + printf(" Warning: Broken tet-sub-tet connection.\n"); + } + } + } + if (sinfected(shloop)) { + // This may be a bug. report it. + printf(" !! A infected subface: (%d, %d, %d).\n", + pointmark(sorg(shloop)), pointmark(sdest(shloop)), + pointmark(sapex(shloop))); + } + if (smarktested(shloop)) { + // This may be a bug. report it. + printf(" !! A marked subface: (%d, %d, %d).\n", pointmark(sorg(shloop)), + pointmark(sdest(shloop)), pointmark(sapex(shloop))); + } + shloop.sh = shellfacetraverse(subfaces); + } + + if (horrors == 0) { + if (!b->quiet) { + printf(" Mesh boundaries connected correctly.\n"); + } + } else { + printf(" !! !! !! !! %d boundary connection viewed with horror.\n", + horrors); + } + + subfaces->pathblock = bakpathblock; + subfaces->pathitem = bakpathitem; + subfaces->pathitemsleft = bakpathitemsleft; + subfaces->alignbytes = bakalignbytes; + + return horrors; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// checksegments() Check the connections between tetrahedra and segments. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::checksegments() +{ + triface tetloop, neightet, spintet; + shellface *segs; + face neighsh, spinsh, checksh; + face sseg, checkseg; + point pa, pb; + int miscount; + int t1ver; + int horrors, i; + + + if (!b->quiet) { + printf(" Checking tet->seg connections...\n"); + } + + horrors = 0; + tetrahedrons->traversalinit(); + tetloop.tet = tetrahedrontraverse(); + while (tetloop.tet != NULL) { + // Loop the six edges of the tet. + if (tetloop.tet[8] != NULL) { + segs = (shellface *) tetloop.tet[8]; + for (i = 0; i < 6; i++) { + sdecode(segs[i], sseg); + if (sseg.sh != NULL) { + // Get the edge of the tet. + tetloop.ver = edge2ver[i]; + // Check if they are the same edge. + pa = (point) sseg.sh[3]; + pb = (point) sseg.sh[4]; + if (!(((org(tetloop) == pa) && (dest(tetloop) == pb)) || + ((org(tetloop) == pb) && (dest(tetloop) == pa)))) { + printf(" !! Wrong tet-seg connection.\n"); + printf(" Tet: x%lx (%d, %d, %d, %d) - Seg: x%lx (%d, %d).\n", + (uintptr_t) tetloop.tet, pointmark(org(tetloop)), + pointmark(dest(tetloop)), pointmark(apex(tetloop)), + pointmark(oppo(tetloop)), (uintptr_t) sseg.sh, + pointmark(pa), pointmark(pb)); + horrors++; + } else { + // Loop all tets sharing at this edge. + neightet = tetloop; + do { + tsspivot1(neightet, checkseg); + if (checkseg.sh != sseg.sh) { + printf(" !! Wrong tet->seg connection.\n"); + printf(" Tet: x%lx (%d, %d, %d, %d) - ", + (uintptr_t) neightet.tet, pointmark(org(neightet)), + pointmark(dest(neightet)), pointmark(apex(neightet)), + pointmark(oppo(neightet))); + if (checkseg.sh != NULL) { + printf("Seg x%lx (%d, %d).\n", (uintptr_t) checkseg.sh, + pointmark(sorg(checkseg)),pointmark(sdest(checkseg))); + } else { + printf("Seg: NULL.\n"); + } + horrors++; + } + fnextself(neightet); + } while (neightet.tet != tetloop.tet); + } + // Check the seg->tet pointer. + sstpivot1(sseg, neightet); + if (neightet.tet == NULL) { + printf(" !! Wrong seg->tet connection (A NULL tet).\n"); + horrors++; + } else { + if (!(((org(neightet) == pa) && (dest(neightet) == pb)) || + ((org(neightet) == pb) && (dest(neightet) == pa)))) { + printf(" !! Wrong seg->tet connection (Wrong edge).\n"); + printf(" Tet: x%lx (%d, %d, %d, %d) - Seg: x%lx (%d, %d).\n", + (uintptr_t) neightet.tet, pointmark(org(neightet)), + pointmark(dest(neightet)), pointmark(apex(neightet)), + pointmark(oppo(neightet)), (uintptr_t) sseg.sh, + pointmark(pa), pointmark(pb)); + horrors++; + } + } + } + } + } + // Loop the six edge of this tet. + neightet.tet = tetloop.tet; + for (i = 0; i < 6; i++) { + neightet.ver = edge2ver[i]; + if (edgemarked(neightet)) { + // A possible bug. Report it. + printf(" !! A marked edge: (%d, %d, %d, %d) -- x%lx %d.\n", + pointmark(org(neightet)), pointmark(dest(neightet)), + pointmark(apex(neightet)), pointmark(oppo(neightet)), + (uintptr_t) neightet.tet, neightet.ver); + // Check if all tets at the edge are marked. + spintet = neightet; + while (1) { + fnextself(spintet); + if (!edgemarked(spintet)) { + printf(" !! !! An unmarked edge (%d, %d, %d, %d) -- x%lx %d.\n", + pointmark(org(spintet)), pointmark(dest(spintet)), + pointmark(apex(spintet)), pointmark(oppo(spintet)), + (uintptr_t) spintet.tet, spintet.ver); + horrors++; + } + if (spintet.tet == neightet.tet) break; + } + } + } + tetloop.tet = tetrahedrontraverse(); + } + + if (!b->quiet) { + printf(" Checking seg->tet connections...\n"); + } + + miscount = 0; // Count the number of unrecovered segments. + subsegs->traversalinit(); + sseg.shver = 0; + sseg.sh = shellfacetraverse(subsegs); + while (sseg.sh != NULL) { + pa = sorg(sseg); + pb = sdest(sseg); + spivot(sseg, neighsh); + if (neighsh.sh != NULL) { + spinsh = neighsh; + while (1) { + // Check seg-subface bond. + if (((sorg(spinsh) == pa) && (sdest(spinsh) == pb)) || + ((sorg(spinsh) == pb) && (sdest(spinsh) == pa))) { + // Keep the same rotate direction. + //if (sorg(spinsh) != pa) { + // sesymself(spinsh); + // printf(" !! Wrong ori at subface (%d, %d, %d) -- x%lx %d\n", + // pointmark(sorg(spinsh)), pointmark(sdest(spinsh)), + // pointmark(sapex(spinsh)), (uintptr_t) spinsh.sh, + // spinsh.shver); + // horrors++; + //} + stpivot(spinsh, spintet); + if (spintet.tet != NULL) { + // Check if all tets at this segment. + while (1) { + tsspivot1(spintet, checkseg); + if (checkseg.sh == NULL) { + printf(" !! !! No seg at tet (%d, %d, %d, %d) -- x%lx %d\n", + pointmark(org(spintet)), pointmark(dest(spintet)), + pointmark(apex(spintet)), pointmark(oppo(spintet)), + (uintptr_t) spintet.tet, spintet.ver); + horrors++; + } + if (checkseg.sh != sseg.sh) { + printf(" !! !! Wrong seg (%d, %d) at tet (%d, %d, %d, %d)\n", + pointmark(sorg(checkseg)), pointmark(sdest(checkseg)), + pointmark(org(spintet)), pointmark(dest(spintet)), + pointmark(apex(spintet)), pointmark(oppo(spintet))); + horrors++; + } + fnextself(spintet); + // Stop at the next subface. + tspivot(spintet, checksh); + if (checksh.sh != NULL) break; + } // while (1) + } + } else { + printf(" !! Wrong seg-subface (%d, %d, %d) -- x%lx %d connect\n", + pointmark(sorg(spinsh)), pointmark(sdest(spinsh)), + pointmark(sapex(spinsh)), (uintptr_t) spinsh.sh, + spinsh.shver); + horrors++; + break; + } // if pa, pb + spivotself(spinsh); + if (spinsh.sh == NULL) break; // A dangling segment. + if (spinsh.sh == neighsh.sh) break; + } // while (1) + } // if (neighsh.sh != NULL) + // Count the number of "un-recovered" segments. + sstpivot1(sseg, neightet); + if (neightet.tet == NULL) { + miscount++; + } + sseg.sh = shellfacetraverse(subsegs); + } + + if (!b->quiet) { + printf(" Checking seg->seg connections...\n"); + } + + points->traversalinit(); + pa = pointtraverse(); + while (pa != NULL) { + if (pointtype(pa) == FREESEGVERTEX) { + // There should be two subsegments connected at 'pa'. + // Get a subsegment containing 'pa'. + sdecode(point2sh(pa), sseg); + if ((sseg.sh == NULL) || sseg.sh[3] == NULL) { + printf(" !! Dead point-to-seg pointer at point %d.\n", + pointmark(pa)); + horrors++; + } else { + sseg.shver = 0; + if (sorg(sseg) != pa) { + if (sdest(sseg) != pa) { + printf(" !! Wrong point-to-seg pointer at point %d.\n", + pointmark(pa)); + horrors++; + } else { + // Find the next subsegment at 'pa'. + senext(sseg, checkseg); + if ((checkseg.sh == NULL) || (checkseg.sh[3] == NULL)) { + printf(" !! Dead seg-seg connection at point %d.\n", + pointmark(pa)); + horrors++; + } else { + spivotself(checkseg); + checkseg.shver = 0; + if (sorg(checkseg) != pa) { + printf(" !! Wrong seg-seg connection at point %d.\n", + pointmark(pa)); + horrors++; + } + } + } + } else { + // Find the previous subsegment at 'pa'. + senext2(sseg, checkseg); + if ((checkseg.sh == NULL) || (checkseg.sh[3] == NULL)) { + printf(" !! Dead seg-seg connection at point %d.\n", + pointmark(pa)); + horrors++; + } else { + spivotself(checkseg); + checkseg.shver = 0; + if (sdest(checkseg) != pa) { + printf(" !! Wrong seg-seg connection at point %d.\n", + pointmark(pa)); + horrors++; + } + } + } + } + } + pa = pointtraverse(); + } + + if (horrors == 0) { + printf(" Segments are connected properly.\n"); + } else { + printf(" !! !! !! !! Found %d missing connections.\n", horrors); + } + if (miscount > 0) { + printf(" !! !! Found %d missing segments.\n", miscount); + } + + return horrors; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// checkdelaunay() Ensure that the mesh is (constrained) Delaunay. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::checkdelaunay() +{ + triface tetloop; + triface symtet; + face checksh; + point pa, pb, pc, pd, pe; + REAL sign; + int ndcount; // Count the non-locally Delaunay faces. + int horrors; + + if (!b->quiet) { + printf(" Checking Delaunay property of the mesh...\n"); + } + + ndcount = 0; + horrors = 0; + tetloop.ver = 0; + // Run through the list of triangles, checking each one. + tetrahedrons->traversalinit(); + tetloop.tet = tetrahedrontraverse(); + while (tetloop.tet != (tetrahedron *) NULL) { + // Check all four faces of the tetrahedron. + for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) { + fsym(tetloop, symtet); + // Only do test if its adjoining tet is not a hull tet or its pointer + // is larger (to ensure that each pair isn't tested twice). + if (((point) symtet.tet[7] != dummypoint)&&(tetloop.tet < symtet.tet)) { + pa = org(tetloop); + pb = dest(tetloop); + pc = apex(tetloop); + pd = oppo(tetloop); + pe = oppo(symtet); + sign = insphere_s(pa, pb, pc, pd, pe); + if (sign < 0.0) { + ndcount++; + if (checksubfaceflag) { + tspivot(tetloop, checksh); + } + if (checksh.sh == NULL) { + printf(" !! Non-locally Delaunay (%d, %d, %d) - %d, %d\n", + pointmark(pa), pointmark(pb), pointmark(pc), pointmark(pd), + pointmark(pe)); + horrors++; + } + } + } + } + tetloop.tet = tetrahedrontraverse(); + } + + if (horrors == 0) { + if (!b->quiet) { + if (ndcount > 0) { + printf(" The mesh is constrained Delaunay.\n"); + } else { + printf(" The mesh is Delaunay.\n"); + } + } + } else { + printf(" !! !! !! !! Found %d non-Delaunay faces.\n", horrors); + } + + return horrors; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// Check if the current tetrahedralization is (constrained) regular. // +// // +// The parameter 'type' determines which regularity should be checked: // +// - 0: check the Delaunay property. // +// - 1: check the Delaunay property with symbolic perturbation. // +// - 2: check the regular property, the weights are stored in p[3]. // +// - 3: check the regular property with symbolic perturbation. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::checkregular(int type) +{ + triface tetloop; + triface symtet; + face checksh; + point p[5]; + REAL sign; + int ndcount; // Count the non-locally Delaunay faces. + int horrors; + + if (!b->quiet) { + printf(" Checking %s %s property of the mesh...\n", + (type & 2) == 0 ? "Delaunay" : "regular", + (type & 1) == 0 ? " " : "(s)"); + } + + // Make sure orient3d(p[1], p[0], p[2], p[3]) > 0; + // Hence if (insphere(p[1], p[0], p[2], p[3], p[4]) > 0) means that + // p[4] lies inside the circumsphere of p[1], p[0], p[2], p[3]. + // The same if orient4d(p[1], p[0], p[2], p[3], p[4]) > 0 means that + // p[4] lies below the oriented hyperplane passing through + // p[1], p[0], p[2], p[3]. + + ndcount = 0; + horrors = 0; + tetloop.ver = 0; + // Run through the list of triangles, checking each one. + tetrahedrons->traversalinit(); + tetloop.tet = tetrahedrontraverse(); + while (tetloop.tet != (tetrahedron *) NULL) { + // Check all four faces of the tetrahedron. + for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) { + fsym(tetloop, symtet); + // Only do test if its adjoining tet is not a hull tet or its pointer + // is larger (to ensure that each pair isn't tested twice). + if (((point) symtet.tet[7] != dummypoint)&&(tetloop.tet < symtet.tet)) { + p[0] = org(tetloop); // pa + p[1] = dest(tetloop); // pb + p[2] = apex(tetloop); // pc + p[3] = oppo(tetloop); // pd + p[4] = oppo(symtet); // pe + + if (type == 0) { + sign = insphere(p[1], p[0], p[2], p[3], p[4]); + } else if (type == 1) { + sign = insphere_s(p[1], p[0], p[2], p[3], p[4]); + } else if (type == 2) { + sign = orient4d(p[1], p[0], p[2], p[3], p[4], + p[1][3], p[0][3], p[2][3], p[3][3], p[4][3]); + } else { // type == 3 + sign = orient4d_s(p[1], p[0], p[2], p[3], p[4], + p[1][3], p[0][3], p[2][3], p[3][3], p[4][3]); + } + + if (sign > 0.0) { + ndcount++; + if (checksubfaceflag) { + tspivot(tetloop, checksh); + } + if (checksh.sh == NULL) { + printf(" !! Non-locally %s (%d, %d, %d) - %d, %d\n", + (type & 2) == 0 ? "Delaunay" : "regular", + pointmark(p[0]), pointmark(p[1]), pointmark(p[2]), + pointmark(p[3]), pointmark(p[4])); + horrors++; + } + } + } + } + tetloop.tet = tetrahedrontraverse(); + } + + if (horrors == 0) { + if (!b->quiet) { + if (ndcount > 0) { + printf(" The mesh is constrained %s.\n", + (type & 2) == 0 ? "Delaunay" : "regular"); + } else { + printf(" The mesh is %s.\n", (type & 2) == 0 ? "Delaunay" : "regular"); + } + } + } else { + printf(" !! !! !! !! Found %d non-%s faces.\n", horrors, + (type & 2) == 0 ? "Delaunay" : "regular"); + } + + return horrors; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// checkconforming() Ensure that the mesh is conforming Delaunay. // +// // +// If 'flag' is 1, only check subsegments. If 'flag' is 2, check subfaces. // +// If 'flag' is 3, check both subsegments and subfaces. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int tetgenmesh::checkconforming(int flag) +{ + triface searchtet, neightet, spintet; + face shloop; + face segloop; + point eorg, edest, eapex, pa, pb, pc; + REAL cent[3], radius, dist, diff, rd, len; + bool enq; + int encsubsegs, encsubfaces; + int t1ver; + int i; + + REAL A[4][4], rhs[4], D; + int indx[4]; + REAL elen[3]; + + encsubsegs = 0; + + if (flag & 1) { + if (!b->quiet) { + printf(" Checking conforming property of segments...\n"); + } + encsubsegs = 0; + + // Run through the list of subsegments, check each one. + subsegs->traversalinit(); + segloop.sh = shellfacetraverse(subsegs); + while (segloop.sh != (shellface *) NULL) { + eorg = (point) segloop.sh[3]; + edest = (point) segloop.sh[4]; + radius = 0.5 * distance(eorg, edest); + for (i = 0; i < 3; i++) cent[i] = 0.5 * (eorg[i] + edest[i]); + + enq = false; + sstpivot1(segloop, neightet); + if (neightet.tet != NULL) { + spintet = neightet; + while (1) { + eapex= apex(spintet); + if (eapex != dummypoint) { + dist = distance(eapex, cent); + diff = dist - radius; + if (fabs(diff) / radius <= b->epsilon) diff = 0.0; // Rounding. + if (diff < 0) { + enq = true; break; + } + } + fnextself(spintet); + if (spintet.tet == neightet.tet) break; + } + } + if (enq) { + printf(" !! !! Non-conforming segment: (%d, %d)\n", + pointmark(eorg), pointmark(edest)); + encsubsegs++; + } + segloop.sh = shellfacetraverse(subsegs); + } + + if (encsubsegs == 0) { + if (!b->quiet) { + printf(" The segments are conforming Delaunay.\n"); + } + } else { + printf(" !! !! %d subsegments are non-conforming.\n", encsubsegs); + } + } // if (flag & 1) + + encsubfaces = 0; + + if (flag & 2) { + if (!b->quiet) { + printf(" Checking conforming property of subfaces...\n"); + } + + // Run through the list of subfaces, check each one. + subfaces->traversalinit(); + shloop.sh = shellfacetraverse(subfaces); + while (shloop.sh != (shellface *) NULL) { + pa = (point) shloop.sh[3]; + pb = (point) shloop.sh[4]; + pc = (point) shloop.sh[5]; + + // Compute the coefficient matrix A (3x3). + A[0][0] = pb[0] - pa[0]; + A[0][1] = pb[1] - pa[1]; + A[0][2] = pb[2] - pa[2]; // vector V1 (pa->pb) + A[1][0] = pc[0] - pa[0]; + A[1][1] = pc[1] - pa[1]; + A[1][2] = pc[2] - pa[2]; // vector V2 (pa->pc) + cross(A[0], A[1], A[2]); // vector V3 (V1 X V2) + + // Compute the right hand side vector b (3x1). + elen[0] = dot(A[0], A[0]); + elen[1] = dot(A[1], A[1]); + rhs[0] = 0.5 * elen[0]; + rhs[1] = 0.5 * elen[1]; + rhs[2] = 0.0; + + if (lu_decmp(A, 3, indx, &D, 0)) { + lu_solve(A, 3, indx, rhs, 0); + cent[0] = pa[0] + rhs[0]; + cent[1] = pa[1] + rhs[1]; + cent[2] = pa[2] + rhs[2]; + rd = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]); + + // Check if this subface is encroached. + for (i = 0; i < 2; i++) { + stpivot(shloop, searchtet); + if (!ishulltet(searchtet)) { + len = distance(oppo(searchtet), cent); + if ((fabs(len - rd) / rd) < b->epsilon) len = rd; // Rounding. + if (len < rd) { + printf(" !! !! Non-conforming subface: (%d, %d, %d)\n", + pointmark(pa), pointmark(pb), pointmark(pc)); + encsubfaces++; + enq = true; break; + } + } + sesymself(shloop); + } + } + shloop.sh = shellfacetraverse(subfaces); + } + + if (encsubfaces == 0) { + if (!b->quiet) { + printf(" The subfaces are conforming Delaunay.\n"); + } + } else { + printf(" !! !! %d subfaces are non-conforming.\n", encsubfaces); + } + } // if (flag & 2) + + return encsubsegs + encsubfaces; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// qualitystatistics() Print statistics about the quality of the mesh. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::qualitystatistics() +{ + triface tetloop, neightet; + point p[4]; + char sbuf[128]; + REAL radiusratiotable[12]; + REAL aspectratiotable[12]; + REAL A[4][4], rhs[4], D; + REAL V[6][3], N[4][3], H[4]; // edge-vectors, face-normals, face-heights. + REAL edgelength[6], alldihed[6], faceangle[3]; + REAL shortest, longest; + REAL smallestvolume, biggestvolume; + REAL smallestratio, biggestratio; + REAL smallestdiangle, biggestdiangle; + REAL smallestfaangle, biggestfaangle; + REAL total_tet_vol, total_tetprism_vol; + REAL tetvol, minaltitude; + REAL cirradius, minheightinv; // insradius; + REAL shortlen, longlen; + REAL tetaspect, tetradius; + REAL smalldiangle, bigdiangle; + REAL smallfaangle, bigfaangle; + unsigned long radiustable[12]; + unsigned long aspecttable[16]; + unsigned long dihedangletable[18]; + unsigned long faceangletable[18]; + int indx[4]; + int radiusindex; + int aspectindex; + int tendegree; + int i, j; + + printf("Mesh quality statistics:\n\n"); + + shortlen = longlen = 0.0; + smalldiangle = bigdiangle = 0.0; + total_tet_vol = 0.0; + total_tetprism_vol = 0.0; + + radiusratiotable[0] = 0.707; radiusratiotable[1] = 1.0; + radiusratiotable[2] = 1.1; radiusratiotable[3] = 1.2; + radiusratiotable[4] = 1.4; radiusratiotable[5] = 1.6; + radiusratiotable[6] = 1.8; radiusratiotable[7] = 2.0; + radiusratiotable[8] = 2.5; radiusratiotable[9] = 3.0; + radiusratiotable[10] = 10.0; radiusratiotable[11] = 0.0; + + aspectratiotable[0] = 1.5; aspectratiotable[1] = 2.0; + aspectratiotable[2] = 2.5; aspectratiotable[3] = 3.0; + aspectratiotable[4] = 4.0; aspectratiotable[5] = 6.0; + aspectratiotable[6] = 10.0; aspectratiotable[7] = 15.0; + aspectratiotable[8] = 25.0; aspectratiotable[9] = 50.0; + aspectratiotable[10] = 100.0; aspectratiotable[11] = 0.0; + + for (i = 0; i < 12; i++) radiustable[i] = 0l; + for (i = 0; i < 12; i++) aspecttable[i] = 0l; + for (i = 0; i < 18; i++) dihedangletable[i] = 0l; + for (i = 0; i < 18; i++) faceangletable[i] = 0l; + + minaltitude = xmax - xmin + ymax - ymin + zmax - zmin; + minaltitude = minaltitude * minaltitude; + shortest = minaltitude; + longest = 0.0; + smallestvolume = minaltitude; + biggestvolume = 0.0; + smallestratio = 1e+16; // minaltitude; + biggestratio = 0.0; + smallestdiangle = smallestfaangle = 180.0; + biggestdiangle = biggestfaangle = 0.0; + + + int attrnum = numelemattrib - 1; + + // Loop all elements, calculate quality parameters for each element. + tetrahedrons->traversalinit(); + tetloop.tet = tetrahedrontraverse(); + while (tetloop.tet != (tetrahedron *) NULL) { + + if (b->convex) { + // Skip tets in the exterior. + if (elemattribute(tetloop.tet, attrnum) == -1.0) { + tetloop.tet = tetrahedrontraverse(); + continue; + } + } + + // Get four vertices: p0, p1, p2, p3. + for (i = 0; i < 4; i++) p[i] = (point) tetloop.tet[4 + i]; + + // Get the tet volume. + tetvol = orient3dfast(p[1], p[0], p[2], p[3]) / 6.0; + total_tet_vol += tetvol; + total_tetprism_vol += tetprismvol(p[0], p[1], p[2], p[3]); + + // Calculate the largest and smallest volume. + if (tetvol < smallestvolume) { + smallestvolume = tetvol; + } + if (tetvol > biggestvolume) { + biggestvolume = tetvol; + } + + // Set the edge vectors: V[0], ..., V[5] + for (i = 0; i < 3; i++) V[0][i] = p[0][i] - p[3][i]; // V[0]: p3->p0. + for (i = 0; i < 3; i++) V[1][i] = p[1][i] - p[3][i]; // V[1]: p3->p1. + for (i = 0; i < 3; i++) V[2][i] = p[2][i] - p[3][i]; // V[2]: p3->p2. + for (i = 0; i < 3; i++) V[3][i] = p[1][i] - p[0][i]; // V[3]: p0->p1. + for (i = 0; i < 3; i++) V[4][i] = p[2][i] - p[1][i]; // V[4]: p1->p2. + for (i = 0; i < 3; i++) V[5][i] = p[0][i] - p[2][i]; // V[5]: p2->p0. + + // Get the squares of the edge lengths. + for (i = 0; i < 6; i++) edgelength[i] = dot(V[i], V[i]); + + // Calculate the longest and shortest edge length. + for (i = 0; i < 6; i++) { + if (i == 0) { + shortlen = longlen = edgelength[i]; + } else { + shortlen = edgelength[i] < shortlen ? edgelength[i] : shortlen; + longlen = edgelength[i] > longlen ? edgelength[i] : longlen; + } + if (edgelength[i] > longest) { + longest = edgelength[i]; + } + if (edgelength[i] < shortest) { + shortest = edgelength[i]; + } + } + + // Set the matrix A = [V[0], V[1], V[2]]^T. + for (j = 0; j < 3; j++) { + for (i = 0; i < 3; i++) A[j][i] = V[j][i]; + } + + // Decompose A just once. + if (lu_decmp(A, 3, indx, &D, 0)) { + // Get the three faces normals. + for (j = 0; j < 3; j++) { + for (i = 0; i < 3; i++) rhs[i] = 0.0; + rhs[j] = 1.0; // Positive means the inside direction + lu_solve(A, 3, indx, rhs, 0); + for (i = 0; i < 3; i++) N[j][i] = rhs[i]; + } + // Get the fourth face normal by summing up the first three. + for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i]; + // Get the radius of the circumsphere. + for (i = 0; i < 3; i++) rhs[i] = 0.5 * dot(V[i], V[i]); + lu_solve(A, 3, indx, rhs, 0); + cirradius = sqrt(dot(rhs, rhs)); + // Normalize the face normals. + for (i = 0; i < 4; i++) { + // H[i] is the inverse of height of its corresponding face. + H[i] = sqrt(dot(N[i], N[i])); + for (j = 0; j < 3; j++) N[i][j] /= H[i]; + } + // Get the radius of the inscribed sphere. + // insradius = 1.0 / (H[0] + H[1] + H[2] + H[3]); + // Get the biggest H[i] (corresponding to the smallest height). + minheightinv = H[0]; + for (i = 1; i < 3; i++) { + if (H[i] > minheightinv) minheightinv = H[i]; + } + } else { + // A nearly degenerated tet. + if (tetvol <= 0.0) { + // assert(tetvol != 0.0); + printf(" !! Warning: A %s tet (%d,%d,%d,%d).\n", + tetvol < 0 ? "inverted" : "degenerated", pointmark(p[0]), + pointmark(p[1]), pointmark(p[2]), pointmark(p[3])); + // Skip it. + tetloop.tet = tetrahedrontraverse(); + continue; + } + // Calculate the four face normals. + facenormal(p[2], p[1], p[3], N[0], 1, NULL); + facenormal(p[0], p[2], p[3], N[1], 1, NULL); + facenormal(p[1], p[0], p[3], N[2], 1, NULL); + facenormal(p[0], p[1], p[2], N[3], 1, NULL); + // Normalize the face normals. + for (i = 0; i < 4; i++) { + // H[i] is the twice of the area of the face. + H[i] = sqrt(dot(N[i], N[i])); + for (j = 0; j < 3; j++) N[i][j] /= H[i]; + } + // Get the biggest H[i] / tetvol (corresponding to the smallest height). + minheightinv = (H[0] / tetvol); + for (i = 1; i < 3; i++) { + if ((H[i] / tetvol) > minheightinv) minheightinv = (H[i] / tetvol); + } + // Let the circumradius to be the half of its longest edge length. + cirradius = 0.5 * sqrt(longlen); + } + + // Get the dihedrals (in degree) at each edges. + j = 0; + for (i = 1; i < 4; i++) { + alldihed[j] = -dot(N[0], N[i]); // Edge cd, bd, bc. + if (alldihed[j] < -1.0) alldihed[j] = -1; // Rounding. + else if (alldihed[j] > 1.0) alldihed[j] = 1; + alldihed[j] = acos(alldihed[j]) / PI * 180.0; + j++; + } + for (i = 2; i < 4; i++) { + alldihed[j] = -dot(N[1], N[i]); // Edge ad, ac. + if (alldihed[j] < -1.0) alldihed[j] = -1; // Rounding. + else if (alldihed[j] > 1.0) alldihed[j] = 1; + alldihed[j] = acos(alldihed[j]) / PI * 180.0; + j++; + } + alldihed[j] = -dot(N[2], N[3]); // Edge ab. + if (alldihed[j] < -1.0) alldihed[j] = -1; // Rounding. + else if (alldihed[j] > 1.0) alldihed[j] = 1; + alldihed[j] = acos(alldihed[j]) / PI * 180.0; + + // Calculate the largest and smallest dihedral angles. + for (i = 0; i < 6; i++) { + if (i == 0) { + smalldiangle = bigdiangle = alldihed[i]; + } else { + smalldiangle = alldihed[i] < smalldiangle ? alldihed[i] : smalldiangle; + bigdiangle = alldihed[i] > bigdiangle ? alldihed[i] : bigdiangle; + } + if (alldihed[i] < smallestdiangle) { + smallestdiangle = alldihed[i]; + } + if (alldihed[i] > biggestdiangle) { + biggestdiangle = alldihed[i]; + } + // Accumulate the corresponding number in the dihedral angle histogram. + if (alldihed[i] < 5.0) { + tendegree = 0; + } else if (alldihed[i] >= 5.0 && alldihed[i] < 10.0) { + tendegree = 1; + } else if (alldihed[i] >= 80.0 && alldihed[i] < 110.0) { + tendegree = 9; // Angles between 80 to 110 degree are in one entry. + } else if (alldihed[i] >= 170.0 && alldihed[i] < 175.0) { + tendegree = 16; + } else if (alldihed[i] >= 175.0) { + tendegree = 17; + } else { + tendegree = (int) (alldihed[i] / 10.); + if (alldihed[i] < 80.0) { + tendegree++; // In the left column. + } else { + tendegree--; // In the right column. + } + } + dihedangletable[tendegree]++; + } + + + + // Calculate the largest and smallest face angles. + for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) { + fsym(tetloop, neightet); + // Only do the calulation once for a face. + if (((point) neightet.tet[7] == dummypoint) || + (tetloop.tet < neightet.tet)) { + p[0] = org(tetloop); + p[1] = dest(tetloop); + p[2] = apex(tetloop); + faceangle[0] = interiorangle(p[0], p[1], p[2], NULL); + faceangle[1] = interiorangle(p[1], p[2], p[0], NULL); + faceangle[2] = PI - (faceangle[0] + faceangle[1]); + // Translate angles into degrees. + for (i = 0; i < 3; i++) { + faceangle[i] = (faceangle[i] * 180.0) / PI; + } + // Calculate the largest and smallest face angles. + for (i = 0; i < 3; i++) { + if (i == 0) { + smallfaangle = bigfaangle = faceangle[i]; + } else { + smallfaangle = faceangle[i] < smallfaangle ? + faceangle[i] : smallfaangle; + bigfaangle = faceangle[i] > bigfaangle ? faceangle[i] : bigfaangle; + } + if (faceangle[i] < smallestfaangle) { + smallestfaangle = faceangle[i]; + } + if (faceangle[i] > biggestfaangle) { + biggestfaangle = faceangle[i]; + } + tendegree = (int) (faceangle[i] / 10.); + faceangletable[tendegree]++; + } + } + } + + // Calculate aspect ratio and radius-edge ratio for this element. + tetradius = cirradius / sqrt(shortlen); + // tetaspect = sqrt(longlen) / (2.0 * insradius); + tetaspect = sqrt(longlen) * minheightinv; + // Remember the largest and smallest aspect ratio. + if (tetaspect < smallestratio) { + smallestratio = tetaspect; + } + if (tetaspect > biggestratio) { + biggestratio = tetaspect; + } + // Accumulate the corresponding number in the aspect ratio histogram. + aspectindex = 0; + while ((tetaspect > aspectratiotable[aspectindex]) && (aspectindex < 11)) { + aspectindex++; + } + aspecttable[aspectindex]++; + radiusindex = 0; + while ((tetradius > radiusratiotable[radiusindex]) && (radiusindex < 11)) { + radiusindex++; + } + radiustable[radiusindex]++; + + tetloop.tet = tetrahedrontraverse(); + } + + shortest = sqrt(shortest); + longest = sqrt(longest); + minaltitude = sqrt(minaltitude); + + printf(" Smallest volume: %16.5g | Largest volume: %16.5g\n", + smallestvolume, biggestvolume); + printf(" Shortest edge: %16.5g | Longest edge: %16.5g\n", + shortest, longest); + printf(" Smallest asp.ratio: %13.5g | Largest asp.ratio: %13.5g\n", + smallestratio, biggestratio); + sprintf(sbuf, "%.17g", biggestfaangle); + if (strlen(sbuf) > 8) { + sbuf[8] = '\0'; + } + printf(" Smallest facangle: %14.5g | Largest facangle: %s\n", + smallestfaangle, sbuf); + sprintf(sbuf, "%.17g", biggestdiangle); + if (strlen(sbuf) > 8) { + sbuf[8] = '\0'; + } + printf(" Smallest dihedral: %14.5g | Largest dihedral: %s\n\n", + smallestdiangle, sbuf); + + printf(" Aspect ratio histogram:\n"); + printf(" < %-6.6g : %8ld | %6.6g - %-6.6g : %8ld\n", + aspectratiotable[0], aspecttable[0], aspectratiotable[5], + aspectratiotable[6], aspecttable[6]); + for (i = 1; i < 5; i++) { + printf(" %6.6g - %-6.6g : %8ld | %6.6g - %-6.6g : %8ld\n", + aspectratiotable[i - 1], aspectratiotable[i], aspecttable[i], + aspectratiotable[i + 5], aspectratiotable[i + 6], + aspecttable[i + 6]); + } + printf(" %6.6g - %-6.6g : %8ld | %6.6g - : %8ld\n", + aspectratiotable[4], aspectratiotable[5], aspecttable[5], + aspectratiotable[10], aspecttable[11]); + printf(" (A tetrahedron's aspect ratio is its longest edge length"); + printf(" divided by its\n"); + printf(" smallest side height)\n\n"); + + printf(" Face angle histogram:\n"); + for (i = 0; i < 9; i++) { + printf(" %3d - %3d degrees: %8ld | %3d - %3d degrees: %8ld\n", + i * 10, i * 10 + 10, faceangletable[i], + i * 10 + 90, i * 10 + 100, faceangletable[i + 9]); + } + if (minfaceang != PI) { + printf(" Minimum input face angle is %g (degree).\n", + minfaceang / PI * 180.0); + } + printf("\n"); + + printf(" Dihedral angle histogram:\n"); + // Print the three two rows: + printf(" %3d - %2d degrees: %8ld | %3d - %3d degrees: %8ld\n", + 0, 5, dihedangletable[0], 80, 110, dihedangletable[9]); + printf(" %3d - %2d degrees: %8ld | %3d - %3d degrees: %8ld\n", + 5, 10, dihedangletable[1], 110, 120, dihedangletable[10]); + // Print the third to seventh rows. + for (i = 2; i < 7; i++) { + printf(" %3d - %2d degrees: %8ld | %3d - %3d degrees: %8ld\n", + (i - 1) * 10, (i - 1) * 10 + 10, dihedangletable[i], + (i - 1) * 10 + 110, (i - 1) * 10 + 120, dihedangletable[i + 9]); + } + // Print the last two rows. + printf(" %3d - %2d degrees: %8ld | %3d - %3d degrees: %8ld\n", + 60, 70, dihedangletable[7], 170, 175, dihedangletable[16]); + printf(" %3d - %2d degrees: %8ld | %3d - %3d degrees: %8ld\n", + 70, 80, dihedangletable[8], 175, 180, dihedangletable[17]); + if (minfacetdihed != PI) { + printf(" Minimum input dihedral angle is %g (degree).\n", + minfacetdihed / PI * 180.0); + } + printf("\n"); + + printf("\n"); +} + + +/////////////////////////////////////////////////////////////////////////////// +// // +// memorystatistics() Report the memory usage. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::memorystatistics() +{ + printf("Memory usage statistics:\n\n"); + + // Count the number of blocks of tetrahedra. + int tetblocks = 0; + tetrahedrons->pathblock = tetrahedrons->firstblock; + while (tetrahedrons->pathblock != NULL) { + tetblocks++; + tetrahedrons->pathblock = (void **) *(tetrahedrons->pathblock); + } + + // Calculate the total memory (in bytes) used by storing meshes. + unsigned long totalmeshmemory = 0l, totalt2shmemory = 0l; + totalmeshmemory = points->maxitems * points->itembytes + + tetrahedrons->maxitems * tetrahedrons->itembytes; + if (b->plc || b->refine) { + totalmeshmemory += (subfaces->maxitems * subfaces->itembytes + + subsegs->maxitems * subsegs->itembytes); + totalt2shmemory = (tet2subpool->maxitems * tet2subpool->itembytes + + tet2segpool->maxitems * tet2segpool->itembytes); + } + + unsigned long totalalgomemory = 0l; + totalalgomemory = cavetetlist->totalmemory + cavebdrylist->totalmemory + + caveoldtetlist->totalmemory + + flippool->maxitems * flippool->itembytes; + if (b->plc || b->refine) { + totalalgomemory += (subsegstack->totalmemory + subfacstack->totalmemory + + subvertstack->totalmemory + + caveshlist->totalmemory + caveshbdlist->totalmemory + + cavesegshlist->totalmemory + + cavetetshlist->totalmemory + + cavetetseglist->totalmemory + + caveencshlist->totalmemory + + caveencseglist->totalmemory + + cavetetvertlist->totalmemory + + unflipqueue->totalmemory); + } + + printf(" Maximum number of tetrahedra: %ld\n", tetrahedrons->maxitems); + printf(" Maximum number of tet blocks (blocksize = %d): %d\n", + b->tetrahedraperblock, tetblocks); + /* + if (b->plc || b->refine) { + printf(" Approximate memory for tetrahedral mesh (bytes): %ld\n", + totalmeshmemory); + + printf(" Approximate memory for extra pointers (bytes): %ld\n", + totalt2shmemory); + } else { + printf(" Approximate memory for tetrahedralization (bytes): %ld\n", + totalmeshmemory); + } + printf(" Approximate memory for algorithms (bytes): %ld\n", + totalalgomemory); + printf(" Approximate memory for working arrays (bytes): %ld\n", + totalworkmemory); + printf(" Approximate total used memory (bytes): %ld\n", + totalmeshmemory + totalt2shmemory + totalalgomemory + + totalworkmemory); + */ + if (b->plc || b->refine) { + printf(" Approximate memory for tetrahedral mesh (bytes): "); + printfcomma(totalmeshmemory); printf("\n"); + + printf(" Approximate memory for extra pointers (bytes): "); + printfcomma(totalt2shmemory); printf("\n"); + } else { + printf(" Approximate memory for tetrahedralization (bytes): "); + printfcomma(totalmeshmemory); printf("\n"); + } + printf(" Approximate memory for algorithms (bytes): "); + printfcomma(totalalgomemory); printf("\n"); + printf(" Approximate memory for working arrays (bytes): "); + printfcomma(totalworkmemory); printf("\n"); + printf(" Approximate total used memory (bytes): "); + printfcomma(totalmeshmemory + totalt2shmemory + totalalgomemory + + totalworkmemory); + printf("\n"); + + printf("\n"); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// statistics() Print all sorts of cool facts. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::statistics() +{ + long tetnumber, facenumber; + + printf("\nStatistics:\n\n"); + printf(" Input points: %d\n", in->numberofpoints); + if (b->refine) { + printf(" Input tetrahedra: %d\n", in->numberoftetrahedra); + } + if (b->plc) { + printf(" Input facets: %d\n", in->numberoffacets); + printf(" Input segments: %ld\n", insegments); + printf(" Input holes: %d\n", in->numberofholes); + printf(" Input regions: %d\n", in->numberofregions); + } + + tetnumber = tetrahedrons->items - hullsize; + facenumber = (tetnumber * 4l + hullsize) / 2l; + + if (b->weighted) { // -w option + printf("\n Mesh points: %ld\n", points->items - nonregularcount); + } else { + printf("\n Mesh points: %ld\n", points->items); + } + printf(" Mesh tetrahedra: %ld\n", tetnumber); + printf(" Mesh faces: %ld\n", facenumber); + if (meshedges > 0l) { + printf(" Mesh edges: %ld\n", meshedges); + } else { + if (!nonconvex) { + long vsize = points->items - dupverts - unuverts; + if (b->weighted) vsize -= nonregularcount; + meshedges = vsize + facenumber - tetnumber - 1; + printf(" Mesh edges: %ld\n", meshedges); + } + } + + if (b->plc || b->refine) { + printf(" Mesh faces on facets: %ld\n", subfaces->items); + printf(" Mesh edges on segments: %ld\n", subsegs->items); + if (st_volref_count > 0l) { + printf(" Steiner points inside domain: %ld\n", st_volref_count); + } + if (st_facref_count > 0l) { + printf(" Steiner points on facets: %ld\n", st_facref_count); + } + if (st_segref_count > 0l) { + printf(" Steiner points on segments: %ld\n", st_segref_count); + } + } else { + printf(" Convex hull faces: %ld\n", hullsize); + if (meshhulledges > 0l) { + printf(" Convex hull edges: %ld\n", meshhulledges); + } + } + if (b->weighted) { // -w option + printf(" Skipped non-regular points: %ld\n", nonregularcount); + } + printf("\n"); + + + if (b->verbose > 0) { + if (b->plc || b->refine) { // -p or -r + if (tetrahedrons->items > 0l) { + qualitystatistics(); + } + } + if (tetrahedrons->items > 0l) { + memorystatistics(); + } + } +} + +//// //// +//// //// +//// meshstat_cxx ///////////////////////////////////////////////////////////// + +//// output_cxx /////////////////////////////////////////////////////////////// +//// //// +//// //// + +/////////////////////////////////////////////////////////////////////////////// +// // +// jettisonnodes() Jettison unused or duplicated vertices. // +// // +// Unused points are those input points which are outside the mesh domain or // +// have no connection (isolated) to the mesh. Duplicated points exist for // +// example if the input PLC is read from a .stl mesh file (marked during the // +// Delaunay tetrahedralization step. This routine remove these points from // +// points list. All existing points are reindexed. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::jettisonnodes() +{ + point pointloop; + bool jetflag; + int oldidx, newidx; + int remcount; + + if (!b->quiet) { + printf("Jettisoning redundant points.\n"); + } + + points->traversalinit(); + pointloop = pointtraverse(); + oldidx = newidx = 0; // in->firstnumber; + remcount = 0; + while (pointloop != (point) NULL) { + jetflag = (pointtype(pointloop) == DUPLICATEDVERTEX) || + (pointtype(pointloop) == UNUSEDVERTEX); + if (jetflag) { + // It is a duplicated or unused point, delete it. + pointdealloc(pointloop); + remcount++; + } else { + // Re-index it. + setpointmark(pointloop, newidx + in->firstnumber); + if (in->pointmarkerlist != (int *) NULL) { + if (oldidx < in->numberofpoints) { + // Re-index the point marker as well. + in->pointmarkerlist[newidx] = in->pointmarkerlist[oldidx]; + } + } + newidx++; + } + oldidx++; + pointloop = pointtraverse(); + } + if (b->verbose) { + printf(" %ld duplicated vertices are removed.\n", dupverts); + printf(" %ld unused vertices are removed.\n", unuverts); + } + dupverts = 0l; + unuverts = 0l; + + // The following line ensures that dead items in the pool of nodes cannot + // be allocated for the new created nodes. This ensures that the input + // nodes will occur earlier in the output files, and have lower indices. + points->deaditemstack = (void *) NULL; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// highorder() Create extra nodes for quadratic subparametric elements. // +// // +// 'highordertable' is an array (size = numberoftetrahedra * 6) for storing // +// high-order nodes of each tetrahedron. This routine is used only when -o2 // +// switch is used. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::highorder() +{ + triface tetloop, worktet, spintet; + point *extralist, *adjextralist; + point torg, tdest, newpoint; + int highorderindex; + int t1ver; + int i, j; + + if (!b->quiet) { + printf("Adding vertices for second-order tetrahedra.\n"); + } + + // Initialize the 'highordertable'. + highordertable = new point[tetrahedrons->items * 6]; + if (highordertable == (point *) NULL) { + terminatetetgen(this, 1); + } + + // This will overwrite the slot for element markers. + highorderindex = 11; + + // The following line ensures that dead items in the pool of nodes cannot + // be allocated for the extra nodes associated with high order elements. + // This ensures that the primary nodes (at the corners of elements) will + // occur earlier in the output files, and have lower indices, than the + // extra nodes. + points->deaditemstack = (void *) NULL; + + // Assign an entry for each tetrahedron to find its extra nodes. At the + // mean while, initialize all extra nodes be NULL. + i = 0; + tetrahedrons->traversalinit(); + tetloop.tet = tetrahedrontraverse(); + while (tetloop.tet != (tetrahedron *) NULL) { + tetloop.tet[highorderindex] = (tetrahedron) &highordertable[i]; + for (j = 0; j < 6; j++) { + highordertable[i + j] = (point) NULL; + } + i += 6; + tetloop.tet = tetrahedrontraverse(); + } + + // To create a unique node on each edge. Loop over all tetrahedra, and + // look at the six edges of each tetrahedron. If the extra node in + // the tetrahedron corresponding to this edge is NULL, create a node + // for this edge, at the same time, set the new node into the extra + // node lists of all other tetrahedra sharing this edge. + tetrahedrons->traversalinit(); + tetloop.tet = tetrahedrontraverse(); + while (tetloop.tet != (tetrahedron *) NULL) { + // Get the list of extra nodes. + extralist = (point *) tetloop.tet[highorderindex]; + worktet.tet = tetloop.tet; + for (i = 0; i < 6; i++) { + if (extralist[i] == (point) NULL) { + // Go to the ith-edge. + worktet.ver = edge2ver[i]; + // Create a new point in the middle of this edge. + torg = org(worktet); + tdest = dest(worktet); + makepoint(&newpoint, FREEVOLVERTEX); + for (j = 0; j < 3 + numpointattrib; j++) { + newpoint[j] = 0.5 * (torg[j] + tdest[j]); + } + // Interpolate its metrics. + for (j = 0; j < in->numberofpointmtrs; j++) { + newpoint[pointmtrindex + j] = + 0.5 * (torg[pointmtrindex + j] + tdest[pointmtrindex + j]); + } + // Set this point into all extra node lists at this edge. + spintet = worktet; + while (1) { + if (!ishulltet(spintet)) { + adjextralist = (point *) spintet.tet[highorderindex]; + adjextralist[ver2edge[spintet.ver]] = newpoint; + } + fnextself(spintet); + if (spintet.tet == worktet.tet) break; + } + } // if (!extralist[i]) + } // i + tetloop.tet = tetrahedrontraverse(); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// numberedges() Count the number of edges, save in "meshedges". // +// // +// This routine is called when '-p' or '-r', and '-E' options are used. The // +// total number of edges depends on the genus of the input surface mesh. // +// // +// NOTE: This routine must be called after outelements(). So all elements // +// have been indexed. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::numberedges() +{ + triface worktet, spintet; + int ishulledge; + int t1ver; + int i; + + meshedges = meshhulledges = 0l; + + tetrahedrons->traversalinit(); + worktet.tet = tetrahedrontraverse(); + while (worktet.tet != NULL) { + // Count the number of Voronoi faces. Look at the six edges of this + // tet. Count an edge only if this tet's index is smaller than + // those of other non-hull tets which share this edge. + for (i = 0; i < 6; i++) { + worktet.ver = edge2ver[i]; + ishulledge = 0; + fnext(worktet, spintet); + do { + if (!ishulltet(spintet)) { + if (elemindex(spintet.tet) < elemindex(worktet.tet)) break; + } else { + ishulledge = 1; + } + fnextself(spintet); + } while (spintet.tet != worktet.tet); + // Count this edge if no adjacent tets are smaller than this tet. + if (spintet.tet == worktet.tet) { + meshedges++; + if (ishulledge) meshhulledges++; + } + } + worktet.tet = tetrahedrontraverse(); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// outnodes() Output the points to a .node file or a tetgenio structure. // +// // +// Note: each point has already been numbered on input (the first index is // +// 'in->firstnumber'). // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::outnodes(tetgenio* out) +{ + FILE *outfile = NULL; + char outnodefilename[FILENAMESIZE]; + face parentsh; + point pointloop; + int nextras, bmark, marker = 0, weightDT = 0; + int coordindex, attribindex; + int pointnumber, firstindex; + int index, i; + + if (out == (tetgenio *) NULL) { + strcpy(outnodefilename, b->outfilename); + strcat(outnodefilename, ".node"); + } + + if (!b->quiet) { + if (out == (tetgenio *) NULL) { + printf("Writing %s.\n", outnodefilename); + } else { + printf("Writing nodes.\n"); + } + } + + nextras = numpointattrib; + if (b->weighted) { // -w + if (b->weighted_param == 0) weightDT = 1; // Weighted DT. + } + + bmark = !b->nobound && in->pointmarkerlist; + + if (out == (tetgenio *) NULL) { + outfile = fopen(outnodefilename, "w"); + if (outfile == (FILE *) NULL) { + printf("File I/O Error: Cannot create file %s.\n", outnodefilename); + terminatetetgen(this, 1); + } + // Number of points, number of dimensions, number of point attributes, + // and number of boundary markers (zero or one). + fprintf(outfile, "%ld %d %d %d\n", points->items, 3, nextras, bmark); + } else { + // Allocate space for 'pointlist'; + out->pointlist = new REAL[points->items * 3]; + if (out->pointlist == (REAL *) NULL) { + printf("Error: Out of memory.\n"); + terminatetetgen(this, 1); + } + // Allocate space for 'pointattributelist' if necessary; + if (nextras > 0) { + out->pointattributelist = new REAL[points->items * nextras]; + if (out->pointattributelist == (REAL *) NULL) { + printf("Error: Out of memory.\n"); + terminatetetgen(this, 1); + } + } + // Allocate space for 'pointmarkerlist' if necessary; + if (bmark) { + out->pointmarkerlist = new int[points->items]; + if (out->pointmarkerlist == (int *) NULL) { + printf("Error: Out of memory.\n"); + terminatetetgen(this, 1); + } + } + if (b->psc) { + out->pointparamlist = new tetgenio::pointparam[points->items]; + if (out->pointparamlist == NULL) { + printf("Error: Out of memory.\n"); + terminatetetgen(this, 1); + } + } + out->numberofpoints = points->items; + out->numberofpointattributes = nextras; + coordindex = 0; + attribindex = 0; + } + + // Determine the first index (0 or 1). + firstindex = b->zeroindex ? 0 : in->firstnumber; + + points->traversalinit(); + pointloop = pointtraverse(); + pointnumber = firstindex; // in->firstnumber; + index = 0; + while (pointloop != (point) NULL) { + if (bmark) { + // Default the vertex has a zero marker. + marker = 0; + // Is it an input vertex? + if (index < in->numberofpoints) { + // Input point's marker is directly copied to output. + marker = in->pointmarkerlist[index]; + } else { + if ((pointtype(pointloop) == FREESEGVERTEX) || + (pointtype(pointloop) == FREEFACETVERTEX)) { + sdecode(point2sh(pointloop), parentsh); + if (parentsh.sh != NULL) { + marker = shellmark(parentsh); + if (pointtype(pointloop) == FREEFACETVERTEX) { + if (in->facetmarkerlist != NULL) { + marker = in->facetmarkerlist[marker - 1]; + } + } + } + } // if (pointtype(...)) + } + } + if (out == (tetgenio *) NULL) { + // Point number, x, y and z coordinates. + fprintf(outfile, "%4d %.17g %.17g %.17g", pointnumber, + pointloop[0], pointloop[1], pointloop[2]); + for (i = 0; i < nextras; i++) { + // Write an attribute. + if ((i == 0) && weightDT) { + fprintf(outfile, " %.17g", pointloop[0] * pointloop[0] + + pointloop[1] * pointloop[1] + pointloop[2] * pointloop[2] + - pointloop[3 + i]); + } else { + fprintf(outfile, " %.17g", pointloop[3 + i]); + } + } + if (bmark) { + // Write the boundary marker. + fprintf(outfile, " %d", marker); + } + if (b->psc) { + fprintf(outfile, " %.8g %.8g %d", pointgeomuv(pointloop, 0), + pointgeomuv(pointloop, 1), pointgeomtag(pointloop)); + if (pointtype(pointloop) == RIDGEVERTEX) { + fprintf(outfile, " 0"); + } else if (pointtype(pointloop) == ACUTEVERTEX) { + fprintf(outfile, " 0"); + } else if (pointtype(pointloop) == FREESEGVERTEX) { + fprintf(outfile, " 1"); + } else if (pointtype(pointloop) == FREEFACETVERTEX) { + fprintf(outfile, " 2"); + } else if (pointtype(pointloop) == FREEVOLVERTEX) { + fprintf(outfile, " 3"); + } else { + fprintf(outfile, " -1"); // Unknown type. + } + } + fprintf(outfile, "\n"); + } else { + // X, y, and z coordinates. + out->pointlist[coordindex++] = pointloop[0]; + out->pointlist[coordindex++] = pointloop[1]; + out->pointlist[coordindex++] = pointloop[2]; + // Point attributes. + for (i = 0; i < nextras; i++) { + // Output an attribute. + if ((i == 0) && weightDT) { + out->pointattributelist[attribindex++] = + pointloop[0] * pointloop[0] + pointloop[1] * pointloop[1] + + pointloop[2] * pointloop[2] - pointloop[3 + i]; + } else { + out->pointattributelist[attribindex++] = pointloop[3 + i]; + } + } + if (bmark) { + // Output the boundary marker. + out->pointmarkerlist[index] = marker; + } + if (b->psc) { + out->pointparamlist[index].uv[0] = pointgeomuv(pointloop, 0); + out->pointparamlist[index].uv[1] = pointgeomuv(pointloop, 1); + out->pointparamlist[index].tag = pointgeomtag(pointloop); + if (pointtype(pointloop) == RIDGEVERTEX) { + out->pointparamlist[index].type = 0; + } else if (pointtype(pointloop) == ACUTEVERTEX) { + out->pointparamlist[index].type = 0; + } else if (pointtype(pointloop) == FREESEGVERTEX) { + out->pointparamlist[index].type = 1; + } else if (pointtype(pointloop) == FREEFACETVERTEX) { + out->pointparamlist[index].type = 2; + } else if (pointtype(pointloop) == FREEVOLVERTEX) { + out->pointparamlist[index].type = 3; + } else { + out->pointparamlist[index].type = -1; // Unknown type. + } + } + } + pointloop = pointtraverse(); + pointnumber++; + index++; + } + + if (out == (tetgenio *) NULL) { + fprintf(outfile, "# Generated by %s\n", b->commandline); + fclose(outfile); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// outmetrics() Output the metric to a file (*.mtr) or a tetgenio obj. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::outmetrics(tetgenio* out) +{ + FILE *outfile = NULL; + char outmtrfilename[FILENAMESIZE]; + point ptloop; + int mtrindex; + + if (out == (tetgenio *) NULL) { + strcpy(outmtrfilename, b->outfilename); + strcat(outmtrfilename, ".mtr"); + } + + if (!b->quiet) { + if (out == (tetgenio *) NULL) { + printf("Writing %s.\n", outmtrfilename); + } else { + printf("Writing metrics.\n"); + } + } + + if (out == (tetgenio *) NULL) { + outfile = fopen(outmtrfilename, "w"); + if (outfile == (FILE *) NULL) { + printf("File I/O Error: Cannot create file %s.\n", outmtrfilename); + terminatetetgen(this, 3); + } + // Number of points, number of point metrices, + // fprintf(outfile, "%ld %d\n", points->items, sizeoftensor + 3); + fprintf(outfile, "%ld %d\n", points->items, 1); + } else { + // Allocate space for 'pointmtrlist' if necessary; + // out->pointmtrlist = new REAL[points->items * (sizeoftensor + 3)]; + out->pointmtrlist = new REAL[points->items]; + if (out->pointmtrlist == (REAL *) NULL) { + terminatetetgen(this, 1); + } + out->numberofpointmtrs = 1; // (sizeoftensor + 3); + mtrindex = 0; + } + + points->traversalinit(); + ptloop = pointtraverse(); + while (ptloop != (point) NULL) { + if (out == (tetgenio *) NULL) { + // for (i = 0; i < sizeoftensor; i++) { + // fprintf(outfile, "%-16.8e ", ptloop[pointmtrindex + i]); + // } + fprintf(outfile, "%-16.8e\n", ptloop[pointmtrindex]); + } else { + // for (i = 0; i < sizeoftensor; i++) { + // out->pointmtrlist[mtrindex++] = ptloop[pointmtrindex + i]; + // } + out->pointmtrlist[mtrindex++] = ptloop[pointmtrindex]; + } + ptloop = pointtraverse(); + } + + if (out == (tetgenio *) NULL) { + fprintf(outfile, "# Generated by %s\n", b->commandline); + fclose(outfile); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// outelements() Output the tetrahedra to an .ele file or a tetgenio // +// structure. // +// // +// This routine also indexes all tetrahedra (exclusing hull tets) (from in-> // +// firstnumber). The total number of mesh edges is counted in 'meshedges'. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::outelements(tetgenio* out) +{ + FILE *outfile = NULL; + char outelefilename[FILENAMESIZE]; + tetrahedron* tptr; + point p1, p2, p3, p4; + point *extralist; + REAL *talist = NULL; + int *tlist = NULL; + long ntets; + int firstindex, shift; + int pointindex, attribindex; + int highorderindex = 11; + int elementnumber; + int eextras; + int i; + + if (out == (tetgenio *) NULL) { + strcpy(outelefilename, b->outfilename); + strcat(outelefilename, ".ele"); + } + + if (!b->quiet) { + if (out == (tetgenio *) NULL) { + printf("Writing %s.\n", outelefilename); + } else { + printf("Writing elements.\n"); + } + } + + // The number of tets excluding hull tets. + ntets = tetrahedrons->items - hullsize; + + eextras = numelemattrib; + if (out == (tetgenio *) NULL) { + outfile = fopen(outelefilename, "w"); + if (outfile == (FILE *) NULL) { + printf("File I/O Error: Cannot create file %s.\n", outelefilename); + terminatetetgen(this, 1); + } + // Number of tetras, points per tetra, attributes per tetra. + fprintf(outfile, "%ld %d %d\n", ntets, b->order == 1 ? 4 : 10, eextras); + } else { + // Allocate memory for output tetrahedra. + out->tetrahedronlist = new int[ntets * (b->order == 1 ? 4 : 10)]; + if (out->tetrahedronlist == (int *) NULL) { + printf("Error: Out of memory.\n"); + terminatetetgen(this, 1); + } + // Allocate memory for output tetrahedron attributes if necessary. + if (eextras > 0) { + out->tetrahedronattributelist = new REAL[ntets * eextras]; + if (out->tetrahedronattributelist == (REAL *) NULL) { + printf("Error: Out of memory.\n"); + terminatetetgen(this, 1); + } + } + out->numberoftetrahedra = ntets; + out->numberofcorners = b->order == 1 ? 4 : 10; + out->numberoftetrahedronattributes = eextras; + tlist = out->tetrahedronlist; + talist = out->tetrahedronattributelist; + pointindex = 0; + attribindex = 0; + } + + // Determine the first index (0 or 1). + firstindex = b->zeroindex ? 0 : in->firstnumber; + shift = 0; // Default no shift. + if ((in->firstnumber == 1) && (firstindex == 0)) { + shift = 1; // Shift the output indices by 1. + } + + tetrahedrons->traversalinit(); + tptr = tetrahedrontraverse(); + elementnumber = firstindex; // in->firstnumber; + while (tptr != (tetrahedron *) NULL) { + if (!b->reversetetori) { + p1 = (point) tptr[4]; + p2 = (point) tptr[5]; + } else { + p1 = (point) tptr[5]; + p2 = (point) tptr[4]; + } + p3 = (point) tptr[6]; + p4 = (point) tptr[7]; + if (out == (tetgenio *) NULL) { + // Tetrahedron number, indices for four points. + fprintf(outfile, "%5d %5d %5d %5d %5d", elementnumber, + pointmark(p1) - shift, pointmark(p2) - shift, + pointmark(p3) - shift, pointmark(p4) - shift); + if (b->order == 2) { + extralist = (point *) tptr[highorderindex]; + // indices for six extra points. + fprintf(outfile, " %5d %5d %5d %5d %5d %5d", + pointmark(extralist[0]) - shift, pointmark(extralist[1]) - shift, + pointmark(extralist[2]) - shift, pointmark(extralist[3]) - shift, + pointmark(extralist[4]) - shift, pointmark(extralist[5]) - shift); + } + for (i = 0; i < eextras; i++) { + fprintf(outfile, " %.17g", elemattribute(tptr, i)); + } + fprintf(outfile, "\n"); + } else { + tlist[pointindex++] = pointmark(p1) - shift; + tlist[pointindex++] = pointmark(p2) - shift; + tlist[pointindex++] = pointmark(p3) - shift; + tlist[pointindex++] = pointmark(p4) - shift; + if (b->order == 2) { + extralist = (point *) tptr[highorderindex]; + tlist[pointindex++] = pointmark(extralist[0]) - shift; + tlist[pointindex++] = pointmark(extralist[1]) - shift; + tlist[pointindex++] = pointmark(extralist[2]) - shift; + tlist[pointindex++] = pointmark(extralist[3]) - shift; + tlist[pointindex++] = pointmark(extralist[4]) - shift; + tlist[pointindex++] = pointmark(extralist[5]) - shift; + } + for (i = 0; i < eextras; i++) { + talist[attribindex++] = elemattribute(tptr, i); + } + } + // Remember the index of this element (for counting edges). + setelemindex(tptr, elementnumber); + tptr = tetrahedrontraverse(); + elementnumber++; + } + + + if (out == (tetgenio *) NULL) { + fprintf(outfile, "# Generated by %s\n", b->commandline); + fclose(outfile); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// outfaces() Output all faces to a .face file or a tetgenio object. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::outfaces(tetgenio* out) +{ + FILE *outfile = NULL; + char facefilename[FILENAMESIZE]; + triface tface, tsymface; + face checkmark; + point torg, tdest, tapex; + long ntets, faces; + int *elist = NULL, *emlist = NULL; + int neigh1 = 0, neigh2 = 0; + int faceid, marker = 0; + int firstindex, shift; + int facenumber; + int index = 0; + + // For -o2 option. + triface workface; + point *extralist, pp[3] = {0,0,0}; + int highorderindex = 11; + int o2index = 0, i; + + if (out == (tetgenio *) NULL) { + strcpy(facefilename, b->outfilename); + strcat(facefilename, ".face"); + } + + if (!b->quiet) { + if (out == (tetgenio *) NULL) { + printf("Writing %s.\n", facefilename); + } else { + printf("Writing faces.\n"); + } + } + + ntets = tetrahedrons->items - hullsize; + faces = (ntets * 4l + hullsize) / 2l; + + if (out == (tetgenio *) NULL) { + outfile = fopen(facefilename, "w"); + if (outfile == (FILE *) NULL) { + printf("File I/O Error: Cannot create file %s.\n", facefilename); + terminatetetgen(this, 1); + } + fprintf(outfile, "%ld %d\n", faces, !b->nobound); + } else { + // Allocate memory for 'trifacelist'. + out->trifacelist = new int[faces * 3]; + if (out->trifacelist == (int *) NULL) { + printf("Error: Out of memory.\n"); + terminatetetgen(this, 1); + } + if (b->order == 2) { + out->o2facelist = new int[faces * 3]; + } + // Allocate memory for 'trifacemarkerlist' if necessary. + if (!b->nobound) { + out->trifacemarkerlist = new int[faces]; + if (out->trifacemarkerlist == (int *) NULL) { + printf("Error: Out of memory.\n"); + terminatetetgen(this, 1); + } + } + if (b->neighout > 1) { + // '-nn' switch. + out->adjtetlist = new int[faces * 2]; + if (out->adjtetlist == (int *) NULL) { + printf("Error: Out of memory.\n"); + terminatetetgen(this, 1); + } + } + out->numberoftrifaces = faces; + elist = out->trifacelist; + emlist = out->trifacemarkerlist; + } + + // Determine the first index (0 or 1). + firstindex = b->zeroindex ? 0 : in->firstnumber; + shift = 0; // Default no shiftment. + if ((in->firstnumber == 1) && (firstindex == 0)) { + shift = 1; // Shift the output indices by 1. + } + + tetrahedrons->traversalinit(); + tface.tet = tetrahedrontraverse(); + facenumber = firstindex; // in->firstnumber; + // To loop over the set of faces, loop over all tetrahedra, and look at + // the four faces of each one. If its adjacent tet is a hull tet, + // operate on the face, otherwise, operate on the face only if the + // current tet has a smaller index than its neighbor. + while (tface.tet != (tetrahedron *) NULL) { + for (tface.ver = 0; tface.ver < 4; tface.ver ++) { + fsym(tface, tsymface); + if (ishulltet(tsymface) || + (elemindex(tface.tet) < elemindex(tsymface.tet))) { + torg = org(tface); + tdest = dest(tface); + tapex = apex(tface); + if (b->order == 2) { // -o2 + // Get the three extra vertices on edges. + extralist = (point *) (tface.tet[highorderindex]); + // The extra vertices are on edges opposite the corners. + enext(tface, workface); + for (i = 0; i < 3; i++) { + pp[i] = extralist[ver2edge[workface.ver]]; + enextself(workface); + } + } + if (!b->nobound) { + // Get the boundary marker of this face. + if (b->plc || b->refine) { + // Shell face is used. + tspivot(tface, checkmark); + if (checkmark.sh == NULL) { + marker = 0; // It is an inner face. It's marker is 0. + } else { + if (in->facetmarkerlist) { + // The facet marker is given, get it. + faceid = shellmark(checkmark) - 1; + marker = in->facetmarkerlist[faceid]; + } else { + marker = 1; // The default marker for subface is 1. + } + } + } else { + // Shell face is not used, only distinguish outer and inner face. + marker = (int) ishulltet(tsymface); + } + } + if (b->neighout > 1) { + // '-nn' switch. Output adjacent tets indices. + neigh1 = elemindex(tface.tet); + if (!ishulltet(tsymface)) { + neigh2 = elemindex(tsymface.tet); + } else { + neigh2 = -1; + } + } + if (out == (tetgenio *) NULL) { + // Face number, indices of three vertices. + fprintf(outfile, "%5d %4d %4d %4d", facenumber, + pointmark(torg) - shift, pointmark(tdest) - shift, + pointmark(tapex) - shift); + if (b->order == 2) { // -o2 + fprintf(outfile, " %4d %4d %4d", pointmark(pp[0]) - shift, + pointmark(pp[1]) - shift, pointmark(pp[2]) - shift); + } + if (!b->nobound) { + // Output a boundary marker. + fprintf(outfile, " %d", marker); + } + if (b->neighout > 1) { + fprintf(outfile, " %5d %5d", neigh1, neigh2); + } + fprintf(outfile, "\n"); + } else { + // Output indices of three vertices. + elist[index++] = pointmark(torg) - shift; + elist[index++] = pointmark(tdest) - shift; + elist[index++] = pointmark(tapex) - shift; + if (b->order == 2) { // -o2 + out->o2facelist[o2index++] = pointmark(pp[0]) - shift; + out->o2facelist[o2index++] = pointmark(pp[1]) - shift; + out->o2facelist[o2index++] = pointmark(pp[2]) - shift; + } + if (!b->nobound) { + emlist[facenumber - in->firstnumber] = marker; + } + if (b->neighout > 1) { + out->adjtetlist[(facenumber - in->firstnumber) * 2] = neigh1; + out->adjtetlist[(facenumber - in->firstnumber) * 2 + 1] = neigh2; + } + } + facenumber++; + } + } + tface.tet = tetrahedrontraverse(); + } + + if (out == (tetgenio *) NULL) { + fprintf(outfile, "# Generated by %s\n", b->commandline); + fclose(outfile); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// outhullfaces() Output hull faces to a .face file or a tetgenio object. // +// // +// The normal of each face is pointing to the outside of the domain. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::outhullfaces(tetgenio* out) +{ + FILE *outfile = NULL; + char facefilename[FILENAMESIZE]; + triface hulltet; + point torg, tdest, tapex; + int *elist = NULL; + int firstindex, shift; + int facenumber; + int index; + + if (out == (tetgenio *) NULL) { + strcpy(facefilename, b->outfilename); + strcat(facefilename, ".face"); + } + + if (!b->quiet) { + if (out == (tetgenio *) NULL) { + printf("Writing %s.\n", facefilename); + } else { + printf("Writing faces.\n"); + } + } + + if (out == (tetgenio *) NULL) { + outfile = fopen(facefilename, "w"); + if (outfile == (FILE *) NULL) { + printf("File I/O Error: Cannot create file %s.\n", facefilename); + terminatetetgen(this, 1); + } + fprintf(outfile, "%ld 0\n", hullsize); + } else { + // Allocate memory for 'trifacelist'. + out->trifacelist = new int[hullsize * 3]; + if (out->trifacelist == (int *) NULL) { + printf("Error: Out of memory.\n"); + terminatetetgen(this, 1); + } + out->numberoftrifaces = hullsize; + elist = out->trifacelist; + index = 0; + } + + // Determine the first index (0 or 1). + firstindex = b->zeroindex ? 0 : in->firstnumber; + shift = 0; // Default no shiftment. + if ((in->firstnumber == 1) && (firstindex == 0)) { + shift = 1; // Shift the output indices by 1. + } + + tetrahedrons->traversalinit(); + hulltet.tet = alltetrahedrontraverse(); + facenumber = firstindex; + while (hulltet.tet != (tetrahedron *) NULL) { + if (ishulltet(hulltet)) { + torg = (point) hulltet.tet[4]; + tdest = (point) hulltet.tet[5]; + tapex = (point) hulltet.tet[6]; + if (out == (tetgenio *) NULL) { + // Face number, indices of three vertices. + fprintf(outfile, "%5d %4d %4d %4d", facenumber, + pointmark(torg) - shift, pointmark(tdest) - shift, + pointmark(tapex) - shift); + fprintf(outfile, "\n"); + } else { + // Output indices of three vertices. + elist[index++] = pointmark(torg) - shift; + elist[index++] = pointmark(tdest) - shift; + elist[index++] = pointmark(tapex) - shift; + } + facenumber++; + } + hulltet.tet = alltetrahedrontraverse(); + } + + if (out == (tetgenio *) NULL) { + fprintf(outfile, "# Generated by %s\n", b->commandline); + fclose(outfile); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// outsubfaces() Output subfaces (i.e. boundary faces) to a .face file or // +// a tetgenio structure. // +// // +// The boundary faces are found in 'subfaces'. For listing triangle vertices // +// in the same sense for all triangles in the mesh, the direction determined // +// by right-hand rule is pointer to the inside of the volume. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::outsubfaces(tetgenio* out) +{ + FILE *outfile = NULL; + char facefilename[FILENAMESIZE]; + int *elist = NULL; + int *emlist = NULL; + int index = 0, index1 = 0, index2 = 0; + triface abuttingtet; + face faceloop; + point torg, tdest, tapex; + int faceid = 0, marker = 0; + int firstindex, shift; + int neigh1 = 0, neigh2 = 0; + int facenumber; + + // For -o2 option. + triface workface; + point *extralist, pp[3] = {0,0,0}; + int highorderindex = 11; + int o2index = 0, i; + + int t1ver; // used by fsymself() + + if (out == (tetgenio *) NULL) { + strcpy(facefilename, b->outfilename); + strcat(facefilename, ".face"); + } + + if (!b->quiet) { + if (out == (tetgenio *) NULL) { + printf("Writing %s.\n", facefilename); + } else { + printf("Writing faces.\n"); + } + } + + if (out == (tetgenio *) NULL) { + outfile = fopen(facefilename, "w"); + if (outfile == (FILE *) NULL) { + printf("File I/O Error: Cannot create file %s.\n", facefilename); + terminatetetgen(this, 3); + } + // Number of subfaces. + fprintf(outfile, "%ld %d\n", subfaces->items, !b->nobound); + } else { + // Allocate memory for 'trifacelist'. + out->trifacelist = new int[subfaces->items * 3]; + if (out->trifacelist == (int *) NULL) { + terminatetetgen(this, 1); + } + if (b->order == 2) { + out->o2facelist = new int[subfaces->items * 3]; + } + if (!b->nobound) { + // Allocate memory for 'trifacemarkerlist'. + out->trifacemarkerlist = new int[subfaces->items]; + if (out->trifacemarkerlist == (int *) NULL) { + terminatetetgen(this, 1); + } + } + if (b->neighout > 1) { + // '-nn' switch. + out->adjtetlist = new int[subfaces->items * 2]; + if (out->adjtetlist == (int *) NULL) { + terminatetetgen(this, 1); + } + } + out->numberoftrifaces = subfaces->items; + elist = out->trifacelist; + emlist = out->trifacemarkerlist; + } + + // Determine the first index (0 or 1). + firstindex = b->zeroindex ? 0 : in->firstnumber; + shift = 0; // Default no shiftment. + if ((in->firstnumber == 1) && (firstindex == 0)) { + shift = 1; // Shift the output indices by 1. + } + + subfaces->traversalinit(); + faceloop.sh = shellfacetraverse(subfaces); + facenumber = firstindex; // in->firstnumber; + while (faceloop.sh != (shellface *) NULL) { + stpivot(faceloop, abuttingtet); + // If there is a tetrahedron containing this subface, orient it so + // that the normal of this face points to inside of the volume by + // right-hand rule. + if (abuttingtet.tet != NULL) { + if (ishulltet(abuttingtet)) { + fsymself(abuttingtet); + assert(!ishulltet(abuttingtet)); + } + } + if (abuttingtet.tet != NULL) { + torg = org(abuttingtet); + tdest = dest(abuttingtet); + tapex = apex(abuttingtet); + if (b->order == 2) { // -o2 + // Get the three extra vertices on edges. + extralist = (point *) (abuttingtet.tet[highorderindex]); + workface = abuttingtet; + for (i = 0; i < 3; i++) { + pp[i] = extralist[ver2edge[workface.ver]]; + enextself(workface); + } + } + } else { + // This may happen when only a surface mesh be generated. + torg = sorg(faceloop); + tdest = sdest(faceloop); + tapex = sapex(faceloop); + if (b->order == 2) { // -o2 + // There is no extra node list available. + pp[0] = torg; + pp[1] = tdest; + pp[2] = tapex; + } + } + if (!b->nobound) { + if (b->refine) { // -r option. + if (in->trifacemarkerlist) { + marker = shellmark(faceloop); + } else { + marker = 1; // Default marker for a subface is 1. + } + } else { + if (in->facetmarkerlist) { + faceid = shellmark(faceloop) - 1; + marker = in->facetmarkerlist[faceid]; + } else { + marker = 1; // Default marker for a subface is 1. + } + } + } + if (b->neighout > 1) { + // '-nn' switch. Output adjacent tets indices. + neigh1 = -1; + neigh2 = -1; + stpivot(faceloop, abuttingtet); + if (abuttingtet.tet != NULL) { + neigh1 = elemindex(abuttingtet.tet); + fsymself(abuttingtet); + if (!ishulltet(abuttingtet)) { + neigh2 = elemindex(abuttingtet.tet); + } + } + } + if (out == (tetgenio *) NULL) { + fprintf(outfile, "%5d %4d %4d %4d", facenumber, + pointmark(torg) - shift, pointmark(tdest) - shift, + pointmark(tapex) - shift); + if (b->order == 2) { // -o2 + fprintf(outfile, " %4d %4d %4d", pointmark(pp[0]) - shift, + pointmark(pp[1]) - shift, pointmark(pp[2]) - shift); + } + if (!b->nobound) { + fprintf(outfile, " %d", marker); + } + if (b->neighout > 1) { + fprintf(outfile, " %5d %5d", neigh1, neigh2); + } + fprintf(outfile, "\n"); + } else { + // Output three vertices of this face; + elist[index++] = pointmark(torg) - shift; + elist[index++] = pointmark(tdest) - shift; + elist[index++] = pointmark(tapex) - shift; + if (b->order == 2) { // -o2 + out->o2facelist[o2index++] = pointmark(pp[0]) - shift; + out->o2facelist[o2index++] = pointmark(pp[1]) - shift; + out->o2facelist[o2index++] = pointmark(pp[2]) - shift; + } + if (!b->nobound) { + emlist[index1++] = marker; + } + if (b->neighout > 1) { + out->adjtetlist[index2++] = neigh1; + out->adjtetlist[index2++] = neigh2; + } + } + facenumber++; + faceloop.sh = shellfacetraverse(subfaces); + } + + if (out == (tetgenio *) NULL) { + fprintf(outfile, "# Generated by %s\n", b->commandline); + fclose(outfile); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// outedges() Output all edges to a .edge file or a tetgenio object. // +// // +// Note: This routine must be called after outelements(), so that the total // +// number of edges 'meshedges' has been counted. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::outedges(tetgenio* out) +{ + FILE *outfile = NULL; + char edgefilename[FILENAMESIZE]; + triface tetloop, worktet, spintet; + face checkseg; + point torg, tdest; + int *elist = NULL, *emlist = NULL; + int ishulledge; + int firstindex, shift; + int edgenumber, marker; + int index = 0, index1 = 0, index2 = 0; + int t1ver; + int i; + + // For -o2 option. + point *extralist, pp = NULL; + int highorderindex = 11; + int o2index = 0; + + if (out == (tetgenio *) NULL) { + strcpy(edgefilename, b->outfilename); + strcat(edgefilename, ".edge"); + } + + if (!b->quiet) { + if (out == (tetgenio *) NULL) { + printf("Writing %s.\n", edgefilename); + } else { + printf("Writing edges.\n"); + } + } + + if (meshedges == 0l) { + if (nonconvex) { + numberedges(); // Count the edges. + } else { + // Use Euler's characteristic to get the numbe of edges. + // It states V - E + F - C = 1, hence E = V + F - C - 1. + long tsize = tetrahedrons->items - hullsize; + long fsize = (tsize * 4l + hullsize) / 2l; + long vsize = points->items - dupverts - unuverts; + if (b->weighted) vsize -= nonregularcount; + meshedges = vsize + fsize - tsize - 1; + } + } + + if (out == (tetgenio *) NULL) { + outfile = fopen(edgefilename, "w"); + if (outfile == (FILE *) NULL) { + printf("File I/O Error: Cannot create file %s.\n", edgefilename); + terminatetetgen(this, 1); + } + // Write the number of edges, boundary markers (0 or 1). + fprintf(outfile, "%ld %d\n", meshedges, !b->nobound); + } else { + // Allocate memory for 'edgelist'. + out->edgelist = new int[meshedges * 2]; + if (out->edgelist == (int *) NULL) { + printf("Error: Out of memory.\n"); + terminatetetgen(this, 1); + } + if (b->order == 2) { // -o2 switch + out->o2edgelist = new int[meshedges]; + } + if (!b->nobound) { + out->edgemarkerlist = new int[meshedges]; + } + if (b->neighout > 1) { // '-nn' switch. + out->edgeadjtetlist = new int[meshedges]; + } + out->numberofedges = meshedges; + elist = out->edgelist; + emlist = out->edgemarkerlist; + } + + // Determine the first index (0 or 1). + firstindex = b->zeroindex ? 0 : in->firstnumber; + shift = 0; // Default no shiftment. + if ((in->firstnumber == 1) && (firstindex == 0)) { + shift = 1; // Shift (reduce) the output indices by 1. + } + + tetrahedrons->traversalinit(); + tetloop.tet = tetrahedrontraverse(); + edgenumber = firstindex; // in->firstnumber; + while (tetloop.tet != (tetrahedron *) NULL) { + // Count the number of Voronoi faces. + worktet.tet = tetloop.tet; + for (i = 0; i < 6; i++) { + worktet.ver = edge2ver[i]; + ishulledge = 0; + fnext(worktet, spintet); + do { + if (!ishulltet(spintet)) { + if (elemindex(spintet.tet) < elemindex(worktet.tet)) break; + } else { + ishulledge = 1; + } + fnextself(spintet); + } while (spintet.tet != worktet.tet); + // Count this edge if no adjacent tets are smaller than this tet. + if (spintet.tet == worktet.tet) { + torg = org(worktet); + tdest = dest(worktet); + if (b->order == 2) { // -o2 + // Get the extra vertex on this edge. + extralist = (point *) worktet.tet[highorderindex]; + pp = extralist[ver2edge[worktet.ver]]; + } + if (out == (tetgenio *) NULL) { + fprintf(outfile, "%5d %4d %4d", edgenumber, + pointmark(torg) - shift, pointmark(tdest) - shift); + if (b->order == 2) { // -o2 + fprintf(outfile, " %4d", pointmark(pp) - shift); + } + } else { + // Output three vertices of this face; + elist[index++] = pointmark(torg) - shift; + elist[index++] = pointmark(tdest) - shift; + if (b->order == 2) { // -o2 + out->o2edgelist[o2index++] = pointmark(pp) - shift; + } + } + if (!b->nobound) { + if (b->plc || b->refine) { + // Check if the edge is a segment. + tsspivot1(worktet, checkseg); + if (checkseg.sh != NULL) { + marker = shellmark(checkseg); + if (marker == 0) { // Does it have no marker? + marker = 1; // Set the default marker for this segment. + } + } else { + marker = 0; // It's not a segment. + } + } else { + // Mark it if it is a hull edge. + marker = ishulledge ? 1 : 0; + } + if (out == (tetgenio *) NULL) { + fprintf(outfile, " %d", marker); + } else { + emlist[index1++] = marker; + } + } + if (b->neighout > 1) { // '-nn' switch. + if (out == (tetgenio *) NULL) { + fprintf(outfile, " %d", elemindex(tetloop.tet)); + } else { + out->edgeadjtetlist[index2++] = elemindex(tetloop.tet); + } + } + if (out == (tetgenio *) NULL) { + fprintf(outfile, "\n"); + } + edgenumber++; + } + } + tetloop.tet = tetrahedrontraverse(); + } + + if (out == (tetgenio *) NULL) { + fprintf(outfile, "# Generated by %s\n", b->commandline); + fclose(outfile); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// outsubsegments() Output segments to a .edge file or a structure. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::outsubsegments(tetgenio* out) +{ + FILE *outfile = NULL; + char edgefilename[FILENAMESIZE]; + int *elist = NULL; + int index, i; + face edgeloop; + point torg, tdest; + int firstindex, shift; + int marker; + int edgenumber; + + // For -o2 option. + triface workface, spintet; + point *extralist, pp = NULL; + int highorderindex = 11; + int o2index = 0; + + // For -nn option. + int neigh = -1; + int index2 = 0; + + int t1ver; // used by fsymself() + + if (out == (tetgenio *) NULL) { + strcpy(edgefilename, b->outfilename); + strcat(edgefilename, ".edge"); + } + + if (!b->quiet) { + if (out == (tetgenio *) NULL) { + printf("Writing %s.\n", edgefilename); + } else { + printf("Writing edges.\n"); + } + } + + if (out == (tetgenio *) NULL) { + outfile = fopen(edgefilename, "w"); + if (outfile == (FILE *) NULL) { + printf("File I/O Error: Cannot create file %s.\n", edgefilename); + terminatetetgen(this, 3); + } + // Number of subsegments. + fprintf(outfile, "%ld 1\n", subsegs->items); + } else { + // Allocate memory for 'edgelist'. + out->edgelist = new int[subsegs->items * (b->order == 1 ? 2 : 3)]; + if (out->edgelist == (int *) NULL) { + terminatetetgen(this, 1); + } + if (b->order == 2) { + out->o2edgelist = new int[subsegs->items]; + } + out->edgemarkerlist = new int[subsegs->items]; + if (out->edgemarkerlist == (int *) NULL) { + terminatetetgen(this, 1); + } + if (b->neighout > 1) { + out->edgeadjtetlist = new int[subsegs->items]; + } + out->numberofedges = subsegs->items; + elist = out->edgelist; + } + + // Determine the first index (0 or 1). + firstindex = b->zeroindex ? 0 : in->firstnumber; + shift = 0; // Default no shiftment. + if ((in->firstnumber == 1) && (firstindex == 0)) { + shift = 1; // Shift the output indices by 1. + } + index = 0; + i = 0; + + subsegs->traversalinit(); + edgeloop.sh = shellfacetraverse(subsegs); + edgenumber = firstindex; // in->firstnumber; + while (edgeloop.sh != (shellface *) NULL) { + torg = sorg(edgeloop); + tdest = sdest(edgeloop); + if ((b->order == 2) || (b->neighout > 1)) { + sstpivot1(edgeloop, workface); + if (workface.tet != NULL) { + // We must find a non-hull tet. + if (ishulltet(workface)) { + spintet = workface; + while (1) { + fnextself(spintet); + if (!ishulltet(spintet)) break; + if (spintet.tet == workface.tet) break; + } + assert(!ishulltet(spintet)); + workface = spintet; + } + } + } + if (b->order == 2) { // -o2 + // Get the extra vertex on this edge. + if (workface.tet != NULL) { + extralist = (point *) workface.tet[highorderindex]; + pp = extralist[ver2edge[workface.ver]]; + } else { + pp = torg; // There is no extra node available. + } + } + if (b->neighout > 1) { // -nn + if (workface.tet != NULL) { + neigh = elemindex(workface.tet); + } else { + neigh = -1; + } + } + marker = shellmark(edgeloop); + if (marker == 0) { + marker = 1; // Default marker of a boundary edge is 1. + } + if (out == (tetgenio *) NULL) { + fprintf(outfile, "%5d %4d %4d", edgenumber, + pointmark(torg) - shift, pointmark(tdest) - shift); + if (b->order == 2) { // -o2 + fprintf(outfile, " %4d", pointmark(pp) - shift); + } + fprintf(outfile, " %d", marker); + if (b->neighout > 1) { // -nn + fprintf(outfile, " %4d", neigh); + } + fprintf(outfile, "\n"); + } else { + // Output three vertices of this face; + elist[index++] = pointmark(torg) - shift; + elist[index++] = pointmark(tdest) - shift; + if (b->order == 2) { // -o2 + out->o2edgelist[o2index++] = pointmark(pp) - shift; + } + out->edgemarkerlist[i++] = marker; + if (b->neighout > 1) { // -nn + out->edgeadjtetlist[index2++] = neigh; + } + } + edgenumber++; + edgeloop.sh = shellfacetraverse(subsegs); + } + + if (out == (tetgenio *) NULL) { + fprintf(outfile, "# Generated by %s\n", b->commandline); + fclose(outfile); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// outneighbors() Output tet neighbors to a .neigh file or a structure. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::outneighbors(tetgenio* out) +{ + FILE *outfile = NULL; + char neighborfilename[FILENAMESIZE]; + int *nlist = NULL; + int index = 0; + triface tetloop, tetsym; + int neighbori[4]; + int firstindex; + int elementnumber; + long ntets; + + if (out == (tetgenio *) NULL) { + strcpy(neighborfilename, b->outfilename); + strcat(neighborfilename, ".neigh"); + } + + if (!b->quiet) { + if (out == (tetgenio *) NULL) { + printf("Writing %s.\n", neighborfilename); + } else { + printf("Writing neighbors.\n"); + } + } + + ntets = tetrahedrons->items - hullsize; + + if (out == (tetgenio *) NULL) { + outfile = fopen(neighborfilename, "w"); + if (outfile == (FILE *) NULL) { + printf("File I/O Error: Cannot create file %s.\n", neighborfilename); + terminatetetgen(this, 1); + } + // Number of tetrahedra, four faces per tetrahedron. + fprintf(outfile, "%ld %d\n", ntets, 4); + } else { + // Allocate memory for 'neighborlist'. + out->neighborlist = new int[ntets * 4]; + if (out->neighborlist == (int *) NULL) { + printf("Error: Out of memory.\n"); + terminatetetgen(this, 1); + } + nlist = out->neighborlist; + } + + // Determine the first index (0 or 1). + firstindex = b->zeroindex ? 0 : in->firstnumber; + + tetrahedrons->traversalinit(); + tetloop.tet = tetrahedrontraverse(); + elementnumber = firstindex; // in->firstnumber; + while (tetloop.tet != (tetrahedron *) NULL) { + for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) { + fsym(tetloop, tetsym); + if (!ishulltet(tetsym)) { + neighbori[tetloop.ver] = elemindex(tetsym.tet); + } else { + neighbori[tetloop.ver] = -1; + } + } + if (out == (tetgenio *) NULL) { + // Tetrahedra number, neighboring tetrahedron numbers. + fprintf(outfile, "%4d %4d %4d %4d %4d\n", elementnumber, + neighbori[0], neighbori[1], neighbori[2], neighbori[3]); + } else { + nlist[index++] = neighbori[0]; + nlist[index++] = neighbori[1]; + nlist[index++] = neighbori[2]; + nlist[index++] = neighbori[3]; + } + tetloop.tet = tetrahedrontraverse(); + elementnumber++; + } + + if (out == (tetgenio *) NULL) { + fprintf(outfile, "# Generated by %s\n", b->commandline); + fclose(outfile); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// outvoronoi() Output the Voronoi diagram to .v.node, .v.edge, v.face, // +// and .v.cell. // +// // +// The Voronoi diagram is the geometric dual of the Delaunay triangulation. // +// The Voronoi vertices are the circumcenters of Delaunay tetrahedra. Each // +// Voronoi edge connects two Voronoi vertices at two sides of a common Dela- // +// unay face. At a face of convex hull, it becomes a ray (goto the infinity).// +// A Voronoi face is the convex hull of all Voronoi vertices around a common // +// Delaunay edge. It is a closed polygon for any internal Delaunay edge. At a// +// ridge, it is unbounded. Each Voronoi cell is the convex hull of all Vor- // +// onoi vertices around a common Delaunay vertex. It is a polytope for any // +// internal Delaunay vertex. It is an unbounded polyhedron for a Delaunay // +// vertex belonging to the convex hull. // +// // +// NOTE: This routine is only used when the input is only a set of point. // +// Comment: Special thanks to Victor Liu for finding and fixing few bugs. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::outvoronoi(tetgenio* out) +{ + FILE *outfile = NULL; + char outfilename[FILENAMESIZE]; + tetgenio::voroedge *vedge = NULL; + tetgenio::vorofacet *vfacet = NULL; + arraypool *tetlist, *ptlist; + triface tetloop, worktet, spintet, firsttet; + point pt[4], ploop, neipt; + REAL ccent[3], infvec[3], vec1[3], vec2[3], L; + long ntets, faces, edges; + int *indexarray, *fidxs, *eidxs; + int arraysize, *vertarray = NULL; + int vpointcount, vedgecount, vfacecount, tcount; + int ishullvert, ishullface; + int index, shift, end1, end2; + int i, j; + + int t1ver; // used by fsymself() + + // Output Voronoi vertices to .v.node file. + if (out == (tetgenio *) NULL) { + strcpy(outfilename, b->outfilename); + strcat(outfilename, ".v.node"); + } + + if (!b->quiet) { + if (out == (tetgenio *) NULL) { + printf("Writing %s.\n", outfilename); + } else { + printf("Writing Voronoi vertices.\n"); + } + } + + // Determine the first index (0 or 1). + shift = (b->zeroindex ? 0 : in->firstnumber); + + // Each face and edge of the tetrahedral mesh will be indexed for indexing + // the Voronoi edges and facets. Indices of faces and edges are saved in + // each tetrahedron (including hull tets). + + // Allocate the total space once. + indexarray = new int[tetrahedrons->items * 10]; + + // Allocate space (10 integers) into each tetrahedron. It re-uses the slot + // for element markers, flags. + i = 0; + tetrahedrons->traversalinit(); + tetloop.tet = alltetrahedrontraverse(); + while (tetloop.tet != NULL) { + tetloop.tet[11] = (tetrahedron) &(indexarray[i * 10]); + i++; + tetloop.tet = alltetrahedrontraverse(); + } + + // The number of tetrahedra (excluding hull tets) (Voronoi vertices). + ntets = tetrahedrons->items - hullsize; + // The number of Delaunay faces (Voronoi edges). + faces = (4l * ntets + hullsize) / 2l; + // The number of Delaunay edges (Voronoi faces). + long vsize = points->items - dupverts - unuverts; + if (b->weighted) vsize -= nonregularcount; + edges = vsize + faces - ntets - 1; + + if (out == (tetgenio *) NULL) { + outfile = fopen(outfilename, "w"); + if (outfile == (FILE *) NULL) { + printf("File I/O Error: Cannot create file %s.\n", outfilename); + terminatetetgen(this, 3); + } + // Number of voronoi points, 3 dim, no attributes, no marker. + fprintf(outfile, "%ld 3 0 0\n", ntets); + } else { + // Allocate space for 'vpointlist'. + out->numberofvpoints = (int) ntets; + out->vpointlist = new REAL[out->numberofvpoints * 3]; + if (out->vpointlist == (REAL *) NULL) { + terminatetetgen(this, 1); + } + } + + // Output Voronoi vertices (the circumcenters of tetrahedra). + tetrahedrons->traversalinit(); + tetloop.tet = tetrahedrontraverse(); + vpointcount = 0; // The (internal) v-index always starts from 0. + index = 0; + while (tetloop.tet != (tetrahedron *) NULL) { + for (i = 0; i < 4; i++) { + pt[i] = (point) tetloop.tet[4 + i]; + setpoint2tet(pt[i], encode(tetloop)); + } + if (b->weighted) { + orthosphere(pt[0], pt[1], pt[2], pt[3], pt[0][3], pt[1][3], pt[2][3], + pt[3][3], ccent, NULL); + } else { + circumsphere(pt[0], pt[1], pt[2], pt[3], ccent, NULL); + } + if (out == (tetgenio *) NULL) { + fprintf(outfile, "%4d %16.8e %16.8e %16.8e\n", vpointcount + shift, + ccent[0], ccent[1], ccent[2]); + } else { + out->vpointlist[index++] = ccent[0]; + out->vpointlist[index++] = ccent[1]; + out->vpointlist[index++] = ccent[2]; + } + setelemindex(tetloop.tet, vpointcount); + vpointcount++; + tetloop.tet = tetrahedrontraverse(); + } + + if (out == (tetgenio *) NULL) { + fprintf(outfile, "# Generated by %s\n", b->commandline); + fclose(outfile); + } + + // Output Voronoi edges to .v.edge file. + if (out == (tetgenio *) NULL) { + strcpy(outfilename, b->outfilename); + strcat(outfilename, ".v.edge"); + } + + if (!b->quiet) { + if (out == (tetgenio *) NULL) { + printf("Writing %s.\n", outfilename); + } else { + printf("Writing Voronoi edges.\n"); + } + } + + if (out == (tetgenio *) NULL) { + outfile = fopen(outfilename, "w"); + if (outfile == (FILE *) NULL) { + printf("File I/O Error: Cannot create file %s.\n", outfilename); + terminatetetgen(this, 3); + } + // Number of Voronoi edges, no marker. + fprintf(outfile, "%ld 0\n", faces); + } else { + // Allocate space for 'vpointlist'. + out->numberofvedges = (int) faces; + out->vedgelist = new tetgenio::voroedge[out->numberofvedges]; + } + + // Output the Voronoi edges. + tetrahedrons->traversalinit(); + tetloop.tet = tetrahedrontraverse(); + vedgecount = 0; // D-Face (V-edge) index (from zero). + index = 0; // The Delaunay-face index. + while (tetloop.tet != (tetrahedron *) NULL) { + // Count the number of Voronoi edges. Look at the four faces of each + // tetrahedron. Count the face if the tetrahedron's index is + // smaller than its neighbor's or the neighbor is outside. + end1 = elemindex(tetloop.tet); + for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) { + fsym(tetloop, worktet); + if (ishulltet(worktet) || + (elemindex(tetloop.tet) < elemindex(worktet.tet))) { + // Found a Voronoi edge. Operate on it. + if (out == (tetgenio *) NULL) { + fprintf(outfile, "%4d %4d", vedgecount + shift, end1 + shift); + } else { + vedge = &(out->vedgelist[index++]); + vedge->v1 = end1 + shift; + } + if (!ishulltet(worktet)) { + end2 = elemindex(worktet.tet); + } else { + end2 = -1; + } + // Note that end2 may be -1 (worktet.tet is outside). + if (end2 == -1) { + // Calculate the out normal of this hull face. + pt[0] = dest(worktet); + pt[1] = org(worktet); + pt[2] = apex(worktet); + for (j = 0; j < 3; j++) vec1[j] = pt[1][j] - pt[0][j]; + for (j = 0; j < 3; j++) vec2[j] = pt[2][j] - pt[0][j]; + cross(vec1, vec2, infvec); + // Normalize it. + L = sqrt(infvec[0] * infvec[0] + infvec[1] * infvec[1] + + infvec[2] * infvec[2]); + if (L > 0) for (j = 0; j < 3; j++) infvec[j] /= L; + if (out == (tetgenio *) NULL) { + fprintf(outfile, " -1"); + fprintf(outfile, " %g %g %g\n", infvec[0], infvec[1], infvec[2]); + } else { + vedge->v2 = -1; + vedge->vnormal[0] = infvec[0]; + vedge->vnormal[1] = infvec[1]; + vedge->vnormal[2] = infvec[2]; + } + } else { + if (out == (tetgenio *) NULL) { + fprintf(outfile, " %4d\n", end2 + shift); + } else { + vedge->v2 = end2 + shift; + vedge->vnormal[0] = 0.0; + vedge->vnormal[1] = 0.0; + vedge->vnormal[2] = 0.0; + } + } + // Save the V-edge index in this tet and its neighbor. + fidxs = (int *) (tetloop.tet[11]); + fidxs[tetloop.ver] = vedgecount; + fidxs = (int *) (worktet.tet[11]); + fidxs[worktet.ver & 3] = vedgecount; + vedgecount++; + } + } // tetloop.ver + tetloop.tet = tetrahedrontraverse(); + } + + if (out == (tetgenio *) NULL) { + fprintf(outfile, "# Generated by %s\n", b->commandline); + fclose(outfile); + } + + // Output Voronoi faces to .v.face file. + if (out == (tetgenio *) NULL) { + strcpy(outfilename, b->outfilename); + strcat(outfilename, ".v.face"); + } + + if (!b->quiet) { + if (out == (tetgenio *) NULL) { + printf("Writing %s.\n", outfilename); + } else { + printf("Writing Voronoi faces.\n"); + } + } + + if (out == (tetgenio *) NULL) { + outfile = fopen(outfilename, "w"); + if (outfile == (FILE *) NULL) { + printf("File I/O Error: Cannot create file %s.\n", outfilename); + terminatetetgen(this, 3); + } + // Number of Voronoi faces. + fprintf(outfile, "%ld 0\n", edges); + } else { + out->numberofvfacets = edges; + out->vfacetlist = new tetgenio::vorofacet[out->numberofvfacets]; + if (out->vfacetlist == (tetgenio::vorofacet *) NULL) { + terminatetetgen(this, 1); + } + } + + // Output the Voronoi facets. + tetrahedrons->traversalinit(); + tetloop.tet = tetrahedrontraverse(); + vfacecount = 0; // D-edge (V-facet) index (from zero). + while (tetloop.tet != (tetrahedron *) NULL) { + // Count the number of Voronoi faces. Look at the six edges of each + // tetrahedron. Count the edge only if the tetrahedron's index is + // smaller than those of all other tetrahedra that share the edge. + worktet.tet = tetloop.tet; + for (i = 0; i < 6; i++) { + worktet.ver = edge2ver[i]; + // Count the number of faces at this edge. If the edge is a hull edge, + // the face containing dummypoint is also counted. + //ishulledge = 0; // Is it a hull edge. + tcount = 0; + firsttet = worktet; + spintet = worktet; + while (1) { + tcount++; + fnextself(spintet); + if (spintet.tet == worktet.tet) break; + if (!ishulltet(spintet)) { + if (elemindex(spintet.tet) < elemindex(worktet.tet)) break; + } else { + //ishulledge = 1; + if (apex(spintet) == dummypoint) { + // We make this V-edge appear in the end of the edge list. + fnext(spintet, firsttet); + } + } + } // while (1) + if (spintet.tet == worktet.tet) { + // Found a Voronoi facet. Operate on it. + pt[0] = org(worktet); + pt[1] = dest(worktet); + end1 = pointmark(pt[0]) - in->firstnumber; // V-cell index + end2 = pointmark(pt[1]) - in->firstnumber; + if (out == (tetgenio *) NULL) { + fprintf(outfile, "%4d %4d %4d %-2d ", vfacecount + shift, + end1 + shift, end2 + shift, tcount); + } else { + vfacet = &(out->vfacetlist[vfacecount]); + vfacet->c1 = end1 + shift; + vfacet->c2 = end2 + shift; + vfacet->elist = new int[tcount + 1]; + vfacet->elist[0] = tcount; + index = 1; + } + // Output V-edges of this V-facet. + spintet = firsttet; //worktet; + while (1) { + fidxs = (int *) (spintet.tet[11]); + if (apex(spintet) != dummypoint) { + vedgecount = fidxs[spintet.ver & 3]; + ishullface = 0; + } else { + ishullface = 1; // It's not a real face. + } + if (out == (tetgenio *) NULL) { + fprintf(outfile, " %d", !ishullface ? (vedgecount + shift) : -1); + } else { + vfacet->elist[index++] = !ishullface ? (vedgecount + shift) : -1; + } + // Save the V-facet index in this tet at this edge. + eidxs = &(fidxs[4]); + eidxs[ver2edge[spintet.ver]] = vfacecount; + // Go to the next face. + fnextself(spintet); + if (spintet.tet == firsttet.tet) break; + } // while (1) + if (out == (tetgenio *) NULL) { + fprintf(outfile, "\n"); + } + vfacecount++; + } // if (spintet.tet == worktet.tet) + } // if (i = 0; i < 6; i++) + tetloop.tet = tetrahedrontraverse(); + } + + if (out == (tetgenio *) NULL) { + fprintf(outfile, "# Generated by %s\n", b->commandline); + fclose(outfile); + } + + // Output Voronoi cells to .v.cell file. + if (out == (tetgenio *) NULL) { + strcpy(outfilename, b->outfilename); + strcat(outfilename, ".v.cell"); + } + + if (!b->quiet) { + if (out == (tetgenio *) NULL) { + printf("Writing %s.\n", outfilename); + } else { + printf("Writing Voronoi cells.\n"); + } + } + + if (out == (tetgenio *) NULL) { + outfile = fopen(outfilename, "w"); + if (outfile == (FILE *) NULL) { + printf("File I/O Error: Cannot create file %s.\n", outfilename); + terminatetetgen(this, 3); + } + // Number of Voronoi cells. + fprintf(outfile, "%ld\n", points->items - unuverts - dupverts); + } else { + out->numberofvcells = points->items - unuverts - dupverts; + out->vcelllist = new int*[out->numberofvcells]; + if (out->vcelllist == (int **) NULL) { + terminatetetgen(this, 1); + } + } + + // Output Voronoi cells. + tetlist = cavetetlist; + ptlist = cavetetvertlist; + points->traversalinit(); + ploop = pointtraverse(); + vpointcount = 0; + while (ploop != (point) NULL) { + if ((pointtype(ploop) != UNUSEDVERTEX) && + (pointtype(ploop) != DUPLICATEDVERTEX) && + (pointtype(ploop) != NREGULARVERTEX)) { + getvertexstar(1, ploop, tetlist, ptlist, NULL); + // Mark all vertices. Check if it is a hull vertex. + ishullvert = 0; + for (i = 0; i < ptlist->objects; i++) { + neipt = * (point *) fastlookup(ptlist, i); + if (neipt != dummypoint) { + pinfect(neipt); + } else { + ishullvert = 1; + } + } + tcount = (int) ptlist->objects; + if (out == (tetgenio *) NULL) { + fprintf(outfile, "%4d %-2d ", vpointcount + shift, tcount); + } else { + arraysize = tcount; + vertarray = new int[arraysize + 1]; + out->vcelllist[vpointcount] = vertarray; + vertarray[0] = tcount; + index = 1; + } + // List Voronoi facets bounding this cell. + for (i = 0; i < tetlist->objects; i++) { + worktet = * (triface *) fastlookup(tetlist, i); + // Let 'worktet' be [a,b,c,d] where d = ploop. + for (j = 0; j < 3; j++) { + neipt = org(worktet); // neipt is a, or b, or c + // Skip the dummypoint. + if (neipt != dummypoint) { + if (pinfected(neipt)) { + // It's not processed yet. + puninfect(neipt); + // Go to the DT edge [a,d], or [b,d], or [c,d]. + esym(worktet, spintet); + enextself(spintet); + // Get the V-face dual to this edge. + eidxs = (int *) spintet.tet[11]; + vfacecount = eidxs[4 + ver2edge[spintet.ver]]; + if (out == (tetgenio *) NULL) { + fprintf(outfile, " %d", vfacecount + shift); + } else { + vertarray[index++] = vfacecount + shift; + } + } + } + enextself(worktet); + } // j + } // i + if (ishullvert) { + // Add a hull facet (-1) to the facet list. + if (out == (tetgenio *) NULL) { + fprintf(outfile, " -1"); + } else { + vertarray[index++] = -1; + } + } + if (out == (tetgenio *) NULL) { + fprintf(outfile, "\n"); + } + tetlist->restart(); + ptlist->restart(); + vpointcount++; + } + ploop = pointtraverse(); + } + + // Delete the space for face/edge indices. + delete [] indexarray; + + if (out == (tetgenio *) NULL) { + fprintf(outfile, "# Generated by %s\n", b->commandline); + fclose(outfile); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// outsmesh() Write surface mesh to a .smesh file, which can be read and // +// tetrahedralized by TetGen. // +// // +// You can specify a filename (without suffix) in 'smfilename'. If you don't // +// supply a filename (let smfilename be NULL), the default name stored in // +// 'tetgenbehavior' will be used. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::outsmesh(char* smfilename) +{ + FILE *outfile; + char nodfilename[FILENAMESIZE]; + char smefilename[FILENAMESIZE]; + face faceloop; + point p1, p2, p3; + int firstindex, shift; + int bmark; + int faceid, marker; + int i; + + if (smfilename != (char *) NULL && smfilename[0] != '\0') { + strcpy(smefilename, smfilename); + } else if (b->outfilename[0] != '\0') { + strcpy(smefilename, b->outfilename); + } else { + strcpy(smefilename, "unnamed"); + } + strcpy(nodfilename, smefilename); + strcat(smefilename, ".smesh"); + strcat(nodfilename, ".node"); + + if (!b->quiet) { + printf("Writing %s.\n", smefilename); + } + outfile = fopen(smefilename, "w"); + if (outfile == (FILE *) NULL) { + printf("File I/O Error: Cannot create file %s.\n", smefilename); + return; + } + + // Determine the first index (0 or 1). + firstindex = b->zeroindex ? 0 : in->firstnumber; + shift = 0; // Default no shiftment. + if ((in->firstnumber == 1) && (firstindex == 0)) { + shift = 1; // Shift the output indices by 1. + } + + fprintf(outfile, "# %s. TetGen's input file.\n", smefilename); + fprintf(outfile, "\n# part 1: node list.\n"); + fprintf(outfile, "0 3 0 0 # nodes are found in %s.\n", nodfilename); + + marker = 0; // avoid compile warning. + bmark = !b->nobound && in->facetmarkerlist; + + fprintf(outfile, "\n# part 2: facet list.\n"); + // Number of facets, boundary marker. + fprintf(outfile, "%ld %d\n", subfaces->items, bmark); + + subfaces->traversalinit(); + faceloop.sh = shellfacetraverse(subfaces); + while (faceloop.sh != (shellface *) NULL) { + p1 = sorg(faceloop); + p2 = sdest(faceloop); + p3 = sapex(faceloop); + if (bmark) { + faceid = shellmark(faceloop) - 1; + if (faceid >= 0) { + marker = in->facetmarkerlist[faceid]; + } else { + marker = 0; // This subface must be added manually later. + } + } + fprintf(outfile, "3 %4d %4d %4d", pointmark(p1) - shift, + pointmark(p2) - shift, pointmark(p3) - shift); + if (bmark) { + fprintf(outfile, " %d", marker); + } + fprintf(outfile, "\n"); + faceloop.sh = shellfacetraverse(subfaces); + } + + // Copy input holelist. + fprintf(outfile, "\n# part 3: hole list.\n"); + fprintf(outfile, "%d\n", in->numberofholes); + for (i = 0; i < in->numberofholes; i++) { + fprintf(outfile, "%d %g %g %g\n", i + in->firstnumber, + in->holelist[i * 3], in->holelist[i * 3 + 1], + in->holelist[i * 3 + 2]); + } + + // Copy input regionlist. + fprintf(outfile, "\n# part 4: region list.\n"); + fprintf(outfile, "%d\n", in->numberofregions); + for (i = 0; i < in->numberofregions; i++) { + fprintf(outfile, "%d %g %g %g %d %g\n", i + in->firstnumber, + in->regionlist[i * 5], in->regionlist[i * 5 + 1], + in->regionlist[i * 5 + 2], (int) in->regionlist[i * 5 + 3], + in->regionlist[i * 5 + 4]); + } + + fprintf(outfile, "# Generated by %s\n", b->commandline); + fclose(outfile); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// outmesh2medit() Write mesh to a .mesh file, which can be read and // +// rendered by Medit (a free mesh viewer from INRIA). // +// // +// You can specify a filename (without suffix) in 'mfilename'. If you don't // +// supply a filename (let mfilename be NULL), the default name stored in // +// 'tetgenbehavior' will be used. The output file will have the suffix .mesh.// +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::outmesh2medit(char* mfilename) +{ + FILE *outfile; + char mefilename[FILENAMESIZE]; + tetrahedron* tetptr; + triface tface, tsymface; + face segloop, checkmark; + point ptloop, p1, p2, p3, p4; + long ntets, faces; + int pointnumber; + int faceid, marker; + int i; + + if (mfilename != (char *) NULL && mfilename[0] != '\0') { + strcpy(mefilename, mfilename); + } else if (b->outfilename[0] != '\0') { + strcpy(mefilename, b->outfilename); + } else { + strcpy(mefilename, "unnamed"); + } + strcat(mefilename, ".mesh"); + + if (!b->quiet) { + printf("Writing %s.\n", mefilename); + } + outfile = fopen(mefilename, "w"); + if (outfile == (FILE *) NULL) { + printf("File I/O Error: Cannot create file %s.\n", mefilename); + return; + } + + fprintf(outfile, "MeshVersionFormatted 1\n"); + fprintf(outfile, "\n"); + fprintf(outfile, "Dimension\n"); + fprintf(outfile, "3\n"); + fprintf(outfile, "\n"); + + fprintf(outfile, "\n# Set of mesh vertices\n"); + fprintf(outfile, "Vertices\n"); + fprintf(outfile, "%ld\n", points->items); + + points->traversalinit(); + ptloop = pointtraverse(); + pointnumber = 1; // Medit need start number form 1. + while (ptloop != (point) NULL) { + // Point coordinates. + fprintf(outfile, "%.17g %.17g %.17g", ptloop[0], ptloop[1], ptloop[2]); + if (in->numberofpointattributes > 0) { + // Write an attribute, ignore others if more than one. + fprintf(outfile, " %.17g\n", ptloop[3]); + } else { + fprintf(outfile, " 0\n"); + } + setpointmark(ptloop, pointnumber); + ptloop = pointtraverse(); + pointnumber++; + } + + // Compute the number of faces. + ntets = tetrahedrons->items - hullsize; + faces = (ntets * 4l + hullsize) / 2l; + + fprintf(outfile, "\n# Set of Triangles\n"); + fprintf(outfile, "Triangles\n"); + fprintf(outfile, "%ld\n", faces); + + tetrahedrons->traversalinit(); + tface.tet = tetrahedrontraverse(); + while (tface.tet != (tetrahedron *) NULL) { + for (tface.ver = 0; tface.ver < 4; tface.ver ++) { + fsym(tface, tsymface); + if (ishulltet(tsymface) || + (elemindex(tface.tet) < elemindex(tsymface.tet))) { + p1 = org (tface); + p2 = dest(tface); + p3 = apex(tface); + fprintf(outfile, "%5d %5d %5d", + pointmark(p1), pointmark(p2), pointmark(p3)); + // Check if it is a subface. + tspivot(tface, checkmark); + if (checkmark.sh == NULL) { + marker = 0; // It is an inner face. It's marker is 0. + } else { + if (in->facetmarkerlist) { + // The facet marker is given, get it. + faceid = shellmark(checkmark) - 1; + marker = in->facetmarkerlist[faceid]; + } else { + marker = 1; // The default marker for subface is 1. + } + } + fprintf(outfile, " %d\n", marker); + } + } + tface.tet = tetrahedrontraverse(); + } + + fprintf(outfile, "\n# Set of Tetrahedra\n"); + fprintf(outfile, "Tetrahedra\n"); + fprintf(outfile, "%ld\n", ntets); + + tetrahedrons->traversalinit(); + tetptr = tetrahedrontraverse(); + while (tetptr != (tetrahedron *) NULL) { + if (!b->reversetetori) { + p1 = (point) tetptr[4]; + p2 = (point) tetptr[5]; + } else { + p1 = (point) tetptr[5]; + p2 = (point) tetptr[4]; + } + p3 = (point) tetptr[6]; + p4 = (point) tetptr[7]; + fprintf(outfile, "%5d %5d %5d %5d", + pointmark(p1), pointmark(p2), pointmark(p3), pointmark(p4)); + if (numelemattrib > 0) { + fprintf(outfile, " %.17g", elemattribute(tetptr, 0)); + } else { + fprintf(outfile, " 0"); + } + fprintf(outfile, "\n"); + tetptr = tetrahedrontraverse(); + } + + fprintf(outfile, "\nCorners\n"); + fprintf(outfile, "%d\n", in->numberofpoints); + + for (i = 0; i < in->numberofpoints; i++) { + fprintf(outfile, "%4d\n", i + 1); + } + + if (b->plc || b->refine) { + fprintf(outfile, "\nEdges\n"); + fprintf(outfile, "%ld\n", subsegs->items); + + subsegs->traversalinit(); + segloop.sh = shellfacetraverse(subsegs); + while (segloop.sh != (shellface *) NULL) { + p1 = sorg(segloop); + p2 = sdest(segloop); + fprintf(outfile, "%5d %5d", pointmark(p1), pointmark(p2)); + marker = shellmark(segloop); + fprintf(outfile, " %d\n", marker); + segloop.sh = shellfacetraverse(subsegs); + } + } + + fprintf(outfile, "\nEnd\n"); + fclose(outfile); +} + + + +/////////////////////////////////////////////////////////////////////////////// +// // +// outmesh2vtk() Save mesh to file in VTK Legacy format. // +// // +// This function was contributed by Bryn Llyod from ETH, 2007. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetgenmesh::outmesh2vtk(char* ofilename) +{ + FILE *outfile; + char vtkfilename[FILENAMESIZE]; + point pointloop, p1, p2, p3, p4; + tetrahedron* tptr; + double x, y, z; + int n1, n2, n3, n4; + int nnodes = 4; + int celltype = 10; + + if (b->order == 2) { + printf(" Write VTK not implemented for order 2 elements \n"); + return; + } + + int NEL = tetrahedrons->items - hullsize; + int NN = points->items; + + if (ofilename != (char *) NULL && ofilename[0] != '\0') { + strcpy(vtkfilename, ofilename); + } else if (b->outfilename[0] != '\0') { + strcpy(vtkfilename, b->outfilename); + } else { + strcpy(vtkfilename, "unnamed"); + } + strcat(vtkfilename, ".vtk"); + + if (!b->quiet) { + printf("Writing %s.\n", vtkfilename); + } + outfile = fopen(vtkfilename, "w"); + if (outfile == (FILE *) NULL) { + printf("File I/O Error: Cannot create file %s.\n", vtkfilename); + return; + } + + //always write big endian + //bool ImALittleEndian = !testIsBigEndian(); + + fprintf(outfile, "# vtk DataFile Version 2.0\n"); + fprintf(outfile, "Unstructured Grid\n"); + fprintf(outfile, "ASCII\n"); // BINARY + fprintf(outfile, "DATASET UNSTRUCTURED_GRID\n"); + fprintf(outfile, "POINTS %d double\n", NN); + + points->traversalinit(); + pointloop = pointtraverse(); + for(int id=0; idtraversalinit(); + tptr = tetrahedrontraverse(); + //elementnumber = firstindex; // in->firstnumber; + while (tptr != (tetrahedron *) NULL) { + if (!b->reversetetori) { + p1 = (point) tptr[4]; + p2 = (point) tptr[5]; + } else { + p1 = (point) tptr[5]; + p2 = (point) tptr[4]; + } + p3 = (point) tptr[6]; + p4 = (point) tptr[7]; + n1 = pointmark(p1) - in->firstnumber; + n2 = pointmark(p2) - in->firstnumber; + n3 = pointmark(p3) - in->firstnumber; + n4 = pointmark(p4) - in->firstnumber; + fprintf(outfile, "%d %4d %4d %4d %4d\n", nnodes, n1, n2, n3, n4); + tptr = tetrahedrontraverse(); + } + fprintf(outfile, "\n"); + + fprintf(outfile, "CELL_TYPES %d\n", NEL); + for(int tid=0; tid 0) { + // Output tetrahedra region attributes. + fprintf(outfile, "CELL_DATA %d\n", NEL); + fprintf(outfile, "SCALARS cell_scalars int 1\n"); + fprintf(outfile, "LOOKUP_TABLE default\n"); + tetrahedrons->traversalinit(); + tptr = tetrahedrontraverse(); + while (tptr != (tetrahedron *) NULL) { + fprintf(outfile, "%d\n", (int) elemattribute(tptr, numelemattrib - 1)); + tptr = tetrahedrontraverse(); + } + fprintf(outfile, "\n"); + } + + fclose(outfile); +} + +//// //// +//// //// +//// output_cxx /////////////////////////////////////////////////////////////// + +//// main_cxx ///////////////////////////////////////////////////////////////// +//// //// +//// //// + +/////////////////////////////////////////////////////////////////////////////// +// // +// tetrahedralize() The interface for users using TetGen library to // +// generate tetrahedral meshes with all features. // +// // +// The sequence is roughly as follows. Many of these steps can be skipped, // +// depending on the command line switches. // +// // +// - Initialize constants and parse the command line. // +// - Read the vertices from a file and either // +// - tetrahedralize them (no -r), or // +// - read an old mesh from files and reconstruct it (-r). // +// - Insert the boundary segments and facets (-p or -Y). // +// - Read the holes (-p), regional attributes (-pA), and regional volume // +// constraints (-pa). Carve the holes and concavities, and spread the // +// regional attributes and volume constraints. // +// - Enforce the constraints on minimum quality bound (-q) and maximum // +// volume (-a), and a mesh size function (-m). // +// - Optimize the mesh wrt. specified quality measures (-O and -o). // +// - Write the output files and print the statistics. // +// - Check the consistency of the mesh (-C). // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out, + tetgenio *addin, tetgenio *bgmin) +{ + tetgenmesh m; + clock_t tv[12], ts[5]; // Timing informations (defined in time.h) + REAL cps = (REAL) CLOCKS_PER_SEC; + + tv[0] = clock(); + + m.b = b; + m.in = in; + m.addin = addin; + + if (b->metric && bgmin && (bgmin->numberofpoints > 0)) { + m.bgm = new tetgenmesh(); // Create an empty background mesh. + m.bgm->b = b; + m.bgm->in = bgmin; + } + + m.initializepools(); + m.transfernodes(); + + exactinit(b->verbose, b->noexact, b->nostaticfilter, + m.xmax - m.xmin, m.ymax - m.ymin, m.zmax - m.zmin); + + tv[1] = clock(); + + if (b->refine) { // -r + m.reconstructmesh(); + } else { // -p + m.incrementaldelaunay(ts[0]); + } + + tv[2] = clock(); + + if (!b->quiet) { + if (b->refine) { + printf("Mesh reconstruction seconds: %g\n", ((REAL)(tv[2]-tv[1])) / cps); + } else { + printf("Delaunay seconds: %g\n", ((REAL)(tv[2]-tv[1])) / cps); + if (b->verbose) { + printf(" Point sorting seconds: %g\n", ((REAL)(ts[0]-tv[1])) / cps); + } + } + } + + if (b->plc && !b->refine) { // -p + m.meshsurface(); + + ts[0] = clock(); + + if (!b->quiet) { + printf("Surface mesh seconds: %g\n", ((REAL)(ts[0]-tv[2])) / cps); + } + + if (b->diagnose) { // -d + m.detectinterfaces(); + + ts[1] = clock(); + + if (!b->quiet) { + printf("Self-intersection seconds: %g\n", ((REAL)(ts[1]-ts[0])) / cps); + } + + // Only output when self-intersecting faces exist. + if (m.subfaces->items > 0l) { + m.outnodes(out); + m.outsubfaces(out); + } + + return; + } + } + + tv[3] = clock(); + + if ((b->metric) && (m.bgm != NULL)) { // -m + m.bgm->initializepools(); + m.bgm->transfernodes(); + m.bgm->reconstructmesh(); + + ts[0] = clock(); + + if (!b->quiet) { + printf("Background mesh reconstruct seconds: %g\n", + ((REAL)(ts[0] - tv[3])) / cps); + } + + if (b->metric) { // -m + m.interpolatemeshsize(); + + ts[1] = clock(); + + if (!b->quiet) { + printf("Size interpolating seconds: %g\n",((REAL)(ts[1]-ts[0])) / cps); + } + } + } + + tv[4] = clock(); + + if (b->plc && !b->refine) { // -p + if (b->nobisect) { // -Y + m.recoverboundary(ts[0]); + } else { + m.constraineddelaunay(ts[0]); + } + + ts[1] = clock(); + + if (!b->quiet) { + if (b->nobisect) { + printf("Boundary recovery "); + } else { + printf("Constrained Delaunay "); + } + printf("seconds: %g\n", ((REAL)(ts[1] - tv[4])) / cps); + if (b->verbose) { + printf(" Segment recovery seconds: %g\n",((REAL)(ts[0]-tv[4]))/ cps); + printf(" Facet recovery seconds: %g\n", ((REAL)(ts[1]-ts[0])) / cps); + } + } + + m.carveholes(); + + ts[2] = clock(); + + if (!b->quiet) { + printf("Exterior tets removal seconds: %g\n",((REAL)(ts[2]-ts[1]))/cps); + } + + if (b->nobisect) { // -Y + if (m.subvertstack->objects > 0l) { + m.suppresssteinerpoints(); + + ts[3] = clock(); + + if (!b->quiet) { + printf("Steiner suppression seconds: %g\n", + ((REAL)(ts[3]-ts[2]))/cps); + } + } + } + } + + tv[5] = clock(); + + if (b->coarsen) { // -R + m.meshcoarsening(); + } + + tv[6] = clock(); + + if (!b->quiet) { + if (b->coarsen) { + printf("Mesh coarsening seconds: %g\n", ((REAL)(tv[6] - tv[5])) / cps); + } + } + + if ((b->plc && b->nobisect) || b->coarsen) { + m.recoverdelaunay(); + } + + tv[7] = clock(); + + if (!b->quiet) { + if ((b->plc && b->nobisect) || b->coarsen) { + printf("Delaunay recovery seconds: %g\n", ((REAL)(tv[7] - tv[6]))/cps); + } + } + + if ((b->plc || b->refine) && b->insertaddpoints) { // -i + if ((addin != NULL) && (addin->numberofpoints > 0)) { + m.insertconstrainedpoints(addin); + } + } + + tv[8] = clock(); + + if (!b->quiet) { + if ((b->plc || b->refine) && b->insertaddpoints) { // -i + if ((addin != NULL) && (addin->numberofpoints > 0)) { + printf("Constrained points seconds: %g\n", ((REAL)(tv[8]-tv[7]))/cps); + } + } + } + + if (b->quality) { + m.delaunayrefinement(); + } + + tv[9] = clock(); + + if (!b->quiet) { + if (b->quality) { + printf("Refinement seconds: %g\n", ((REAL)(tv[9] - tv[8])) / cps); + } + } + + if ((b->plc || b->refine) && (b->optlevel > 0)) { + m.optimizemesh(); + } + + tv[10] = clock(); + + if (!b->quiet) { + if ((b->plc || b->refine) && (b->optlevel > 0)) { + printf("Optimization seconds: %g\n", ((REAL)(tv[10] - tv[9])) / cps); + } + } + + if (!b->nojettison && ((m.dupverts > 0) || (m.unuverts > 0) + || (b->refine && (in->numberofcorners == 10)))) { + m.jettisonnodes(); + } + + if ((b->order == 2) && !b->convex) { + m.highorder(); + } + + if (!b->quiet) { + printf("\n"); + } + + if (out != (tetgenio *) NULL) { + out->firstnumber = in->firstnumber; + out->mesh_dim = in->mesh_dim; + } + + if (b->nonodewritten || b->noiterationnum) { + if (!b->quiet) { + printf("NOT writing a .node file.\n"); + } + } else { + m.outnodes(out); + } + + if (b->noelewritten) { + if (!b->quiet) { + printf("NOT writing an .ele file.\n"); + } + } else { + if (m.tetrahedrons->items > 0l) { + m.outelements(out); + } + } + + if (b->nofacewritten) { + if (!b->quiet) { + printf("NOT writing an .face file.\n"); + } + } else { + if (b->facesout) { + if (m.tetrahedrons->items > 0l) { + m.outfaces(out); // Output all faces. + } + } else { + if (b->plc || b->refine) { + if (m.subfaces->items > 0l) { + m.outsubfaces(out); // Output boundary faces. + } + } else { + if (m.tetrahedrons->items > 0l) { + m.outhullfaces(out); // Output convex hull faces. + } + } + } + } + + + if (b->nofacewritten) { + if (!b->quiet) { + printf("NOT writing an .edge file.\n"); + } + } else { + if (b->edgesout) { // -e + m.outedges(out); // output all mesh edges. + } else { + if (b->plc || b->refine) { + m.outsubsegments(out); // output subsegments. + } + } + } + + if ((b->plc || b->refine) && b->metric) { // -m + m.outmetrics(out); + } + + if (!out && b->plc && + ((b->object == tetgenbehavior::OFF) || + (b->object == tetgenbehavior::PLY) || + (b->object == tetgenbehavior::STL))) { + m.outsmesh(b->outfilename); + } + + if (!out && b->meditview) { + m.outmesh2medit(b->outfilename); + } + + + if (!out && b->vtkview) { + m.outmesh2vtk(b->outfilename); + } + + if (b->neighout) { + m.outneighbors(out); + } + + if ((!(b->plc || b->refine)) && b->voroout) { + m.outvoronoi(out); + } + + + tv[11] = clock(); + + if (!b->quiet) { + printf("\nOutput seconds: %g\n", ((REAL)(tv[11] - tv[10])) / cps); + printf("Total running seconds: %g\n", ((REAL)(tv[11] - tv[0])) / cps); + } + + if (b->docheck) { + m.checkmesh(0); + if (b->plc || b->refine) { + m.checkshells(); + m.checksegments(); + } + if (b->docheck > 1) { + m.checkdelaunay(); + } + } + + if (!b->quiet) { + m.statistics(); + } +} + +#ifndef TETLIBRARY + +/////////////////////////////////////////////////////////////////////////////// +// // +// main() The command line interface of TetGen. // +// // +/////////////////////////////////////////////////////////////////////////////// + +int main(int argc, char *argv[]) + +#else // with TETLIBRARY + +/////////////////////////////////////////////////////////////////////////////// +// // +// tetrahedralize() The library interface of TetGen. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetrahedralize(char *switches, tetgenio *in, tetgenio *out, + tetgenio *addin, tetgenio *bgmin) + +#endif // not TETLIBRARY + +{ + tetgenbehavior b; + +#ifndef TETLIBRARY + + tetgenio in, addin, bgmin; + + if (!b.parse_commandline(argc, argv)) { + terminatetetgen(NULL, 10); + } + + // Read input files. + if (b.refine) { // -r + if (!in.load_tetmesh(b.infilename, (int) b.object)) { + terminatetetgen(NULL, 10); + } + } else { // -p + if (!in.load_plc(b.infilename, (int) b.object)) { + terminatetetgen(NULL, 10); + } + } + if (b.insertaddpoints) { // -i + // Try to read a .a.node file. + addin.load_node(b.addinfilename); + } + if (b.metric) { // -m + // Try to read a background mesh in files .b.node, .b.ele. + bgmin.load_tetmesh(b.bgmeshfilename, (int) b.object); + } + + tetrahedralize(&b, &in, NULL, &addin, &bgmin); + + return 0; + +#else // with TETLIBRARY + + if (!b.parse_commandline(switches)) { + terminatetetgen(NULL, 10); + } + tetrahedralize(&b, in, out, addin, bgmin); + +#endif // not TETLIBRARY +} + +//// //// +//// //// +//// main_cxx ///////////////////////////////////////////////////////////////// + diff --git a/thirdparty/tetgen/tetgen.h b/thirdparty/tetgen/tetgen.h new file mode 100644 index 00000000..59f8259f --- /dev/null +++ b/thirdparty/tetgen/tetgen.h @@ -0,0 +1,3334 @@ +/////////////////////////////////////////////////////////////////////////////// +// // +// TetGen // +// // +// A Quality Tetrahedral Mesh Generator and A 3D Delaunay Triangulator // +// // +// Version 1.5 // +// November 4, 2013 // +// // +// TetGen is freely available through the website: http://www.tetgen.org. // +// It may be copied, modified, and redistributed for non-commercial use. // +// Please consult the file LICENSE for the detailed copyright notices. // +// // +/////////////////////////////////////////////////////////////////////////////// + + +#ifndef tetgenH +#define tetgenH +#define TETLIBRARY +// To compile TetGen as a library instead of an executable program, define +// the TETLIBRARY symbol. + +// #define TETLIBRARY + +// Uncomment the following line to disable assert macros. These macros were +// inserted in the code where I hoped to catch bugs. They may slow down the +// speed of TetGen. + +// #define NDEBUG + +// TetGen default uses the double precision (64 bit) for a real number. +// Alternatively, one can use the single precision (32 bit) 'float' if the +// memory is limited. + +#define REAL double // #define REAL float + +// Maximum number of characters in a file name (including the null). + +#define FILENAMESIZE 1024 + +// Maximum number of chars in a line read from a file (including the null). + +#define INPUTLINESIZE 2048 + +// TetGen only uses the C standard library. + +#include +#include +#include +#include +#include +#include + +// The types 'intptr_t' and 'uintptr_t' are signed and unsigned integer types, +// respectively. They are guaranteed to be the same width as a pointer. +// They are defined in by the C99 Standard. However, Microsoft +// Visual C++ 2003 -- 2008 (Visual C++ 7.1 - 9) doesn't ship with this header +// file. In such case, we can define them by ourself. +// Update (learned from Stack Overflow): Visual Studio 2010 and Visual C++ 2010 +// Express both have stdint.h + +// The following piece of code was provided by Steven Johnson (MIT). Define the +// symbol _MSC_VER if you are using Microsoft Visual C++. Moreover, define +// the _WIN64 symbol if you are running TetGen on Win64 systems. + +#ifdef _MSC_VER // Microsoft Visual C++ +# ifdef _WIN64 + typedef __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +# else // not _WIN64 + typedef int intptr_t; + typedef unsigned int uintptr_t; +# endif +#else // not Visual C++ +# include +#endif + +/////////////////////////////////////////////////////////////////////////////// +// // +// tetgenio // +// // +// A structure for transferring data into and out of TetGen's mesh structure,// +// 'tetgenmesh' (declared below). // +// // +// The input of TetGen is either a 3D point set, or a 3D piecewise linear // +// complex (PLC), or a tetrahedral mesh. Depending on the input object and // +// the specified options, the output of TetGen is either a Delaunay (or wei- // +// ghted Delaunay) tetrahedralization, or a constrained (Delaunay) tetrahed- // +// ralization, or a quality tetrahedral mesh. // +// // +// A piecewise linear complex (PLC) represents a 3D polyhedral domain with // +// possibly internal boundaries(subdomains). It is introduced in [Miller et // +// al, 1996]. Basically it is a set of "cells", i.e., vertices, edges, poly- // +// gons, and polyhedra, and the intersection of any two of its cells is the // +// union of other cells of it. // +// // +// TetGen uses a set of files to describe the inputs and outputs. Each file // +// is identified from its file extension (.node, .ele, .face, .edge, etc). // +// // +// The 'tetgenio' structure is a collection of arrays of data, i.e., points, // +// facets, tetrahedra, and so forth. It contains functions to read and write // +// (input and output) files of TetGen as well as other supported mesh files. // +// // +// Once an object of tetgenio is declared, no array is created. One has to // +// allocate enough memory for them. On deletion of this object, the memory // +// occupied by these arrays needs to be freed. The routine deinitialize() // +// will be automatically called. It frees the memory for an array if it is // +// not a NULL. Note that it assumes that the memory is allocated by the C++ // +// "new" operator. Otherwise, the user is responsible to free them and all // +// pointers must be NULL before the call of the destructor. // +// // +/////////////////////////////////////////////////////////////////////////////// + +class tetgenio { + +public: + + // A "polygon" describes a simple polygon (no holes). It is not necessarily + // convex. Each polygon contains a number of corners (points) and the same + // number of sides (edges). The points of the polygon must be given in + // either counterclockwise or clockwise order and they form a ring, so + // every two consecutive points forms an edge of the polygon. + typedef struct { + int *vertexlist; + int numberofvertices; + } polygon; + + // A "facet" describes a polygonal region possibly with holes, edges, and + // points floating in it. Each facet consists of a list of polygons and + // a list of hole points (which lie strictly inside holes). + typedef struct { + polygon *polygonlist; + int numberofpolygons; + REAL *holelist; + int numberofholes; + } facet; + + // A "voroedge" is an edge of the Voronoi diagram. It corresponds to a + // Delaunay face. Each voroedge is either a line segment connecting + // two Voronoi vertices or a ray starting from a Voronoi vertex to an + // "infinite vertex". 'v1' and 'v2' are two indices pointing to the + // list of Voronoi vertices. 'v1' must be non-negative, while 'v2' may + // be -1 if it is a ray, in this case, the unit normal of this ray is + // given in 'vnormal'. + typedef struct { + int v1, v2; + REAL vnormal[3]; + } voroedge; + + // A "vorofacet" is an facet of the Voronoi diagram. It corresponds to a + // Delaunay edge. Each Voronoi facet is a convex polygon formed by a + // list of Voronoi edges, it may not be closed. 'c1' and 'c2' are two + // indices pointing into the list of Voronoi cells, i.e., the two cells + // share this facet. 'elist' is an array of indices pointing into the + // list of Voronoi edges, 'elist[0]' saves the number of Voronoi edges + // (including rays) of this facet. + typedef struct { + int c1, c2; + int *elist; + } vorofacet; + + + // Additional parameters associated with an input (or mesh) vertex. + // These informations are provided by CAD libraries. + typedef struct { + REAL uv[2]; + int tag; + int type; // 0, 1, or 2. + } pointparam; + + // Callback functions for meshing PSCs. + typedef REAL (* GetVertexParamOnEdge)(void*, int, int); + typedef void (* GetSteinerOnEdge)(void*, int, REAL, REAL*); + typedef void (* GetVertexParamOnFace)(void*, int, int, REAL*); + typedef void (* GetEdgeSteinerParamOnFace)(void*, int, REAL, int, REAL*); + typedef void (* GetSteinerOnFace)(void*, int, REAL*, REAL*); + + // A callback function for mesh refinement. + typedef bool (* TetSizeFunc)(REAL*, REAL*, REAL*, REAL*, REAL*, REAL); + + // Items are numbered starting from 'firstnumber' (0 or 1), default is 0. + int firstnumber; + + // Dimension of the mesh (2 or 3), default is 3. + int mesh_dim; + + // Does the lines in .node file contain index or not, default is 1. + int useindex; + + // 'pointlist': An array of point coordinates. The first point's x + // coordinate is at index [0] and its y coordinate at index [1], its + // z coordinate is at index [2], followed by the coordinates of the + // remaining points. Each point occupies three REALs. + // 'pointattributelist': An array of point attributes. Each point's + // attributes occupy 'numberofpointattributes' REALs. + // 'pointmtrlist': An array of metric tensors at points. Each point's + // tensor occupies 'numberofpointmtr' REALs. + // 'pointmarkerlist': An array of point markers; one integer per point. + REAL *pointlist; + REAL *pointattributelist; + REAL *pointmtrlist; + int *pointmarkerlist; + pointparam *pointparamlist; + int numberofpoints; + int numberofpointattributes; + int numberofpointmtrs; + + // 'tetrahedronlist': An array of tetrahedron corners. The first + // tetrahedron's first corner is at index [0], followed by its other + // corners, followed by six nodes on the edges of the tetrahedron if the + // second order option (-o2) is applied. Each tetrahedron occupies + // 'numberofcorners' ints. The second order nodes are ouput only. + // 'tetrahedronattributelist': An array of tetrahedron attributes. Each + // tetrahedron's attributes occupy 'numberoftetrahedronattributes' REALs. + // 'tetrahedronvolumelist': An array of constraints, i.e. tetrahedron's + // volume; one REAL per element. Input only. + // 'neighborlist': An array of tetrahedron neighbors; 4 ints per element. + // Output only. + int *tetrahedronlist; + REAL *tetrahedronattributelist; + REAL *tetrahedronvolumelist; + int *neighborlist; + int numberoftetrahedra; + int numberofcorners; + int numberoftetrahedronattributes; + + // 'facetlist': An array of facets. Each entry is a structure of facet. + // 'facetmarkerlist': An array of facet markers; one int per facet. + facet *facetlist; + int *facetmarkerlist; + int numberoffacets; + + // 'holelist': An array of holes (in volume). Each hole is given by a + // seed (point) which lies strictly inside it. The first seed's x, y and z + // coordinates are at indices [0], [1] and [2], followed by the + // remaining seeds. Three REALs per hole. + REAL *holelist; + int numberofholes; + + // 'regionlist': An array of regions (subdomains). Each region is given by + // a seed (point) which lies strictly inside it. The first seed's x, y and + // z coordinates are at indices [0], [1] and [2], followed by the regional + // attribute at index [3], followed by the maximum volume at index [4]. + // Five REALs per region. + // Note that each regional attribute is used only if you select the 'A' + // switch, and each volume constraint is used only if you select the + // 'a' switch (with no number following). + REAL *regionlist; + int numberofregions; + + // 'facetconstraintlist': An array of facet constraints. Each constraint + // specifies a maximum area bound on the subfaces of that facet. The + // first facet constraint is given by a facet marker at index [0] and its + // maximum area bound at index [1], followed by the remaining facet con- + // straints. Two REALs per facet constraint. Note: the facet marker is + // actually an integer. + REAL *facetconstraintlist; + int numberoffacetconstraints; + + // 'segmentconstraintlist': An array of segment constraints. Each constraint + // specifies a maximum length bound on the subsegments of that segment. + // The first constraint is given by the two endpoints of the segment at + // index [0] and [1], and the maximum length bound at index [2], followed + // by the remaining segment constraints. Three REALs per constraint. + // Note the segment endpoints are actually integers. + REAL *segmentconstraintlist; + int numberofsegmentconstraints; + + + // 'trifacelist': An array of face (triangle) corners. The first face's + // three corners are at indices [0], [1] and [2], followed by the remaining + // faces. Three ints per face. + // 'trifacemarkerlist': An array of face markers; one int per face. + // 'o2facelist': An array of second order nodes (on the edges) of the face. + // It is output only if the second order option (-o2) is applied. The + // first face's three second order nodes are at [0], [1], and [2], + // followed by the remaining faces. Three ints per face. + // 'adjtetlist': An array of adjacent tetrahedra to the faces. The first + // face's two adjacent tetrahedra are at indices [0] and [1], followed by + // the remaining faces. A '-1' indicates outside (no adj. tet). This list + // is output when '-nn' switch is used. Output only. + int *trifacelist; + int *trifacemarkerlist; + int *o2facelist; + int *adjtetlist; + int numberoftrifaces; + + // 'edgelist': An array of edge endpoints. The first edge's endpoints + // are at indices [0] and [1], followed by the remaining edges. + // Two ints per edge. + // 'edgemarkerlist': An array of edge markers; one int per edge. + // 'o2edgelist': An array of midpoints of edges. It is output only if the + // second order option (-o2) is applied. One int per edge. + // 'edgeadjtetlist': An array of adjacent tetrahedra to the edges. One + // tetrahedron (an integer) per edge. + int *edgelist; + int *edgemarkerlist; + int *o2edgelist; + int *edgeadjtetlist; + int numberofedges; + + // 'vpointlist': An array of Voronoi vertex coordinates (like pointlist). + // 'vedgelist': An array of Voronoi edges. Each entry is a 'voroedge'. + // 'vfacetlist': An array of Voronoi facets. Each entry is a 'vorofacet'. + // 'vcelllist': An array of Voronoi cells. Each entry is an array of + // indices pointing into 'vfacetlist'. The 0th entry is used to store + // the length of this array. + REAL *vpointlist; + voroedge *vedgelist; + vorofacet *vfacetlist; + int **vcelllist; + int numberofvpoints; + int numberofvedges; + int numberofvfacets; + int numberofvcells; + + // Variable (and callback functions) for meshing PSCs. + void *geomhandle; + GetVertexParamOnEdge getvertexparamonedge; + GetSteinerOnEdge getsteineronedge; + GetVertexParamOnFace getvertexparamonface; + GetEdgeSteinerParamOnFace getedgesteinerparamonface; + GetSteinerOnFace getsteineronface; + + // A callback function. + TetSizeFunc tetunsuitable; + + // Input & output routines. + bool load_node_call(FILE* infile, int markers, int uvflag, char*); + bool load_node(char*); + bool load_edge(char*); + bool load_face(char*); + bool load_tet(char*); + bool load_vol(char*); + bool load_var(char*); + bool load_mtr(char*); + bool load_pbc(char*); + bool load_poly(char*); + bool load_off(char*); + bool load_ply(char*); + bool load_stl(char*); + bool load_vtk(char*); + bool load_medit(char*, int); + bool load_plc(char*, int); + bool load_tetmesh(char*, int); + void save_nodes(char*); + void save_elements(char*); + void save_faces(char*); + void save_edges(char*); + void save_neighbors(char*); + void save_poly(char*); + void save_faces2smesh(char*); + + // Read line and parse string functions. + char *readline(char* string, FILE* infile, int *linenumber); + char *findnextfield(char* string); + char *readnumberline(char* string, FILE* infile, char* infilename); + char *findnextnumber(char* string); + + static void init(polygon* p) { + p->vertexlist = (int *) NULL; + p->numberofvertices = 0; + } + + static void init(facet* f) { + f->polygonlist = (polygon *) NULL; + f->numberofpolygons = 0; + f->holelist = (REAL *) NULL; + f->numberofholes = 0; + } + + // Initialize routine. + void initialize() + { + firstnumber = 0; + mesh_dim = 3; + useindex = 1; + + pointlist = (REAL *) NULL; + pointattributelist = (REAL *) NULL; + pointmtrlist = (REAL *) NULL; + pointmarkerlist = (int *) NULL; + pointparamlist = (pointparam *) NULL; + numberofpoints = 0; + numberofpointattributes = 0; + numberofpointmtrs = 0; + + tetrahedronlist = (int *) NULL; + tetrahedronattributelist = (REAL *) NULL; + tetrahedronvolumelist = (REAL *) NULL; + neighborlist = (int *) NULL; + numberoftetrahedra = 0; + numberofcorners = 4; + numberoftetrahedronattributes = 0; + + trifacelist = (int *) NULL; + trifacemarkerlist = (int *) NULL; + o2facelist = (int *) NULL; + adjtetlist = (int *) NULL; + numberoftrifaces = 0; + + edgelist = (int *) NULL; + edgemarkerlist = (int *) NULL; + o2edgelist = (int *) NULL; + edgeadjtetlist = (int *) NULL; + numberofedges = 0; + + facetlist = (facet *) NULL; + facetmarkerlist = (int *) NULL; + numberoffacets = 0; + + holelist = (REAL *) NULL; + numberofholes = 0; + + regionlist = (REAL *) NULL; + numberofregions = 0; + + facetconstraintlist = (REAL *) NULL; + numberoffacetconstraints = 0; + segmentconstraintlist = (REAL *) NULL; + numberofsegmentconstraints = 0; + + + vpointlist = (REAL *) NULL; + vedgelist = (voroedge *) NULL; + vfacetlist = (vorofacet *) NULL; + vcelllist = (int **) NULL; + numberofvpoints = 0; + numberofvedges = 0; + numberofvfacets = 0; + numberofvcells = 0; + + tetunsuitable = NULL; + + geomhandle = NULL; + getvertexparamonedge = NULL; + getsteineronedge = NULL; + getvertexparamonface = NULL; + getedgesteinerparamonface = NULL; + getsteineronface = NULL; + } + + // Free the memory allocated in 'tetgenio'. Note that it assumes that the + // memory was allocated by the "new" operator (C++). + void deinitialize() + { + int i, j; + + if (pointlist != (REAL *) NULL) { + delete [] pointlist; + } + if (pointattributelist != (REAL *) NULL) { + delete [] pointattributelist; + } + if (pointmtrlist != (REAL *) NULL) { + delete [] pointmtrlist; + } + if (pointmarkerlist != (int *) NULL) { + delete [] pointmarkerlist; + } + if (pointparamlist != (pointparam *) NULL) { + delete [] pointparamlist; + } + + if (tetrahedronlist != (int *) NULL) { + delete [] tetrahedronlist; + } + if (tetrahedronattributelist != (REAL *) NULL) { + delete [] tetrahedronattributelist; + } + if (tetrahedronvolumelist != (REAL *) NULL) { + delete [] tetrahedronvolumelist; + } + if (neighborlist != (int *) NULL) { + delete [] neighborlist; + } + + if (trifacelist != (int *) NULL) { + delete [] trifacelist; + } + if (trifacemarkerlist != (int *) NULL) { + delete [] trifacemarkerlist; + } + if (o2facelist != (int *) NULL) { + delete [] o2facelist; + } + if (adjtetlist != (int *) NULL) { + delete [] adjtetlist; + } + + if (edgelist != (int *) NULL) { + delete [] edgelist; + } + if (edgemarkerlist != (int *) NULL) { + delete [] edgemarkerlist; + } + if (o2edgelist != (int *) NULL) { + delete [] o2edgelist; + } + if (edgeadjtetlist != (int *) NULL) { + delete [] edgeadjtetlist; + } + + if (facetlist != (facet *) NULL) { + facet *f; + polygon *p; + for (i = 0; i < numberoffacets; i++) { + f = &facetlist[i]; + for (j = 0; j < f->numberofpolygons; j++) { + p = &f->polygonlist[j]; + delete [] p->vertexlist; + } + delete [] f->polygonlist; + if (f->holelist != (REAL *) NULL) { + delete [] f->holelist; + } + } + delete [] facetlist; + } + if (facetmarkerlist != (int *) NULL) { + delete [] facetmarkerlist; + } + + if (holelist != (REAL *) NULL) { + delete [] holelist; + } + if (regionlist != (REAL *) NULL) { + delete [] regionlist; + } + if (facetconstraintlist != (REAL *) NULL) { + delete [] facetconstraintlist; + } + if (segmentconstraintlist != (REAL *) NULL) { + delete [] segmentconstraintlist; + } + if (vpointlist != (REAL *) NULL) { + delete [] vpointlist; + } + if (vedgelist != (voroedge *) NULL) { + delete [] vedgelist; + } + if (vfacetlist != (vorofacet *) NULL) { + for (i = 0; i < numberofvfacets; i++) { + delete [] vfacetlist[i].elist; + } + delete [] vfacetlist; + } + if (vcelllist != (int **) NULL) { + for (i = 0; i < numberofvcells; i++) { + delete [] vcelllist[i]; + } + delete [] vcelllist; + } + } + + // Constructor & destructor. + tetgenio() {initialize();} + ~tetgenio() {deinitialize();} + +}; // class tetgenio + +/////////////////////////////////////////////////////////////////////////////// +// // +// tetgenbehavior // +// // +// A structure for maintaining the switches and parameters used by TetGen's // +// mesh data structure and algorithms. // +// // +// All switches and parameters are initialized with default values. They can // +// be set by the command line arguments (a list of strings) of TetGen. // +// // +// NOTE: Some of the switches are incompatible. While some may depend on // +// other switches. The routine parse_commandline() sets the switches from // +// the command line (a list of strings) and checks the consistency of the // +// applied switches. // +// // +/////////////////////////////////////////////////////////////////////////////// + +class tetgenbehavior { + +public: + + // Switches of TetGen. + int plc; // '-p', 0. + int psc; // '-s', 0. + int refine; // '-r', 0. + int quality; // '-q', 0. + int nobisect; // '-Y', 0. + int coarsen; // '-R', 0. + int weighted; // '-w', 0. + int brio_hilbert; // '-b', 1. + int incrflip; // '-l', 0. + int flipinsert; // '-L', 0. + int metric; // '-m', 0. + int varvolume; // '-a', 0. + int fixedvolume; // '-a', 0. + int regionattrib; // '-A', 0. + int conforming; // '-D', 0. + int insertaddpoints; // '-i', 0. + int diagnose; // '-d', 0. + int convex; // '-c', 0. + int nomergefacet; // '-M', 0. + int nomergevertex; // '-M', 0. + int noexact; // '-X', 0. + int nostaticfilter; // '-X', 0. + int zeroindex; // '-z', 0. + int facesout; // '-f', 0. + int edgesout; // '-e', 0. + int neighout; // '-n', 0. + int voroout; // '-v', 0. + int meditview; // '-g', 0. + int vtkview; // '-k', 0. + int nobound; // '-B', 0. + int nonodewritten; // '-N', 0. + int noelewritten; // '-E', 0. + int nofacewritten; // '-F', 0. + int noiterationnum; // '-I', 0. + int nojettison; // '-J', 0. + int reversetetori; // '-R', 0. + int docheck; // '-C', 0. + int quiet; // '-Q', 0. + int verbose; // '-V', 0. + + // Parameters of TetGen. + int vertexperblock; // '-x', 4092. + int tetrahedraperblock; // '-x', 8188. + int shellfaceperblock; // '-x', 2044. + int nobisect_param; // '-Y', 2. + int addsteiner_algo; // '-Y/', 1. + int coarsen_param; // '-R', 0. + int weighted_param; // '-w', 0. + int fliplinklevel; // -1. + int flipstarsize; // -1. + int fliplinklevelinc; // 1. + int reflevel; // '-D', 3. + int optlevel; // '-O', 2. + int optscheme; // '-O', 7. + int delmaxfliplevel; // 1. + int order; // '-o', 1. + int steinerleft; // '-S', 0. + int no_sort; // 0. + int hilbert_order; // '-b///', 52. + int hilbert_limit; // '-b//' 8. + int brio_threshold; // '-b' 64. + REAL brio_ratio; // '-b/' 0.125. + REAL facet_ang_tol; // '-p', 179.9. + REAL maxvolume; // '-a', -1.0. + REAL minratio; // '-q', 0.0. + REAL mindihedral; // '-q', 5.0. + REAL optmaxdihedral; // 165.0. + REAL optminsmtdihed; // 179.0. + REAL optminslidihed; // 179.0. + REAL epsilon; // '-T', 1.0e-8. + REAL minedgelength; // 0.0. + REAL coarsen_percent; // -R1/#, 1.0. + + // Strings of command line arguments and input/output file names. + char commandline[1024]; + char infilename[1024]; + char outfilename[1024]; + char addinfilename[1024]; + char bgmeshfilename[1024]; + + // The input object of TetGen. They are recognized by either the input + // file extensions or by the specified options. + // Currently the following objects are supported: + // - NODES, a list of nodes (.node); + // - POLY, a piecewise linear complex (.poly or .smesh); + // - OFF, a polyhedron (.off, Geomview's file format); + // - PLY, a polyhedron (.ply, file format from gatech, only ASCII); + // - STL, a surface mesh (.stl, stereolithography format); + // - MEDIT, a surface mesh (.mesh, Medit's file format); + // - MESH, a tetrahedral mesh (.ele). + // If no extension is available, the imposed command line switch + // (-p or -r) implies the object. + enum objecttype {NODES, POLY, OFF, PLY, STL, MEDIT, VTK, MESH} object; + + + void syntax(); + void usage(); + + // Command line parse routine. + bool parse_commandline(int argc, char **argv); + bool parse_commandline(char *switches) { + return parse_commandline(0, &switches); + } + + // Initialize all variables. + tetgenbehavior() + { + plc = 0; + psc = 0; + refine = 0; + quality = 0; + nobisect = 0; + coarsen = 0; + metric = 0; + weighted = 0; + brio_hilbert = 1; + incrflip = 0; + flipinsert = 0; + varvolume = 0; + fixedvolume = 0; + noexact = 0; + nostaticfilter = 0; + insertaddpoints = 0; + regionattrib = 0; + conforming = 0; + diagnose = 0; + convex = 0; + zeroindex = 0; + facesout = 0; + edgesout = 0; + neighout = 0; + voroout = 0; + meditview = 0; + vtkview = 0; + nobound = 0; + nonodewritten = 0; + noelewritten = 0; + nofacewritten = 0; + noiterationnum = 0; + nomergefacet = 0; + nomergevertex = 0; + nojettison = 0; + reversetetori = 0; + docheck = 0; + quiet = 0; + verbose = 0; + + vertexperblock = 4092; + tetrahedraperblock = 8188; + shellfaceperblock = 4092; + nobisect_param = 2; + addsteiner_algo = 1; + coarsen_param = 0; + weighted_param = 0; + fliplinklevel = -1; // No limit on linklevel. + flipstarsize = -1; // No limit on flip star size. + fliplinklevelinc = 1; + reflevel = 3; + optscheme = 7; // 1 & 2 & 4, // min_max_dihedral. + optlevel = 2; + delmaxfliplevel = 1; + order = 1; + steinerleft = -1; + no_sort = 0; + hilbert_order = 52; //-1; + hilbert_limit = 8; + brio_threshold = 64; + brio_ratio = 0.125; + facet_ang_tol = 179.9; + maxvolume = -1.0; + minratio = 2.0; + mindihedral = 0.0; // 5.0; + optmaxdihedral = 165.00; // without -q, default is 179.0 + optminsmtdihed = 179.00; // without -q, default is 179.999 + optminslidihed = 179.00; // without -q, default is 179.999 + epsilon = 1.0e-8; + minedgelength = 0.0; + coarsen_percent = 1.0; + object = NODES; + + commandline[0] = '\0'; + infilename[0] = '\0'; + outfilename[0] = '\0'; + addinfilename[0] = '\0'; + bgmeshfilename[0] = '\0'; + + } + +}; // class tetgenbehavior + +/////////////////////////////////////////////////////////////////////////////// +// // +// Robust Geometric predicates // +// // +// Geometric predicates are simple tests of spatial relations of a set of d- // +// dimensional points, such as the orientation test and the point-in-sphere // +// test. Each of these tests is performed by evaluating the sign of a deter- // +// minant of a matrix whose entries are the coordinates of these points. If // +// the computation is performed by using the floating-point numbers, e.g., // +// the single or double precision numbers in C/C++, roundoff error may cause // +// an incorrect result. This may either lead to a wrong result or eventually // +// lead to a failure of the program. Computing the predicates exactly will // +// avoid the error and make the program robust. // +// // +// The following routines are the robust geometric predicates for 3D orient- // +// ation test and point-in-sphere test. They were implemented by Shewchuk. // +// The source code are generously provided by him in the public domain, // +// http://www.cs.cmu.edu/~quake/robust.html. predicates.cxx is a C++ version // +// of the original C code. // +// // +// The original predicates of Shewchuk only use "dynamic filters", i.e., it // +// computes the error at run time step by step. TetGen first adds a "static // +// filter" in each predicate. It estimates the maximal possible error in all // +// cases. So it can safely and quickly answer many easy cases. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void exactinit(int, int, int, REAL, REAL, REAL); +REAL orient3d(REAL *pa, REAL *pb, REAL *pc, REAL *pd); +REAL insphere(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe); +REAL orient4d(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe, + REAL ah, REAL bh, REAL ch, REAL dh, REAL eh); + +/////////////////////////////////////////////////////////////////////////////// +// // +// tetgenmesh // +// // +// A structure for creating and updating tetrahedral meshes. // +// // +/////////////////////////////////////////////////////////////////////////////// + +class tetgenmesh { + +public: + +/////////////////////////////////////////////////////////////////////////////// +// // +// Mesh data structure // +// // +// A tetrahedral mesh T of a 3D piecewise linear complex (PLC) X is a 3D // +// simplicial complex whose underlying space is equal to the space of X. T // +// contains a 2D subcomplex S which is a triangular mesh of the boundary of // +// X. S contains a 1D subcomplex L which is a linear mesh of the boundary of // +// S. Faces and edges in S and L are respectively called subfaces and segme- // +// nts to distinguish them from others in T. // +// // +// TetGen stores the tetrahedra and vertices of T. The basic structure of a // +// tetrahedron contains pointers to its vertices and adjacent tetrahedra. A // +// vertex stores its x-, y-, and z-coordinates, and a pointer to a tetrahed- // +// ron containing it. Both tetrahedra and vertices may contain user data. // +// // +// Each face of T belongs to either two tetrahedra or one tetrahedron. In // +// the latter case, the face is an exterior boundary face of T. TetGen adds // +// fictitious tetrahedra (one-to-one) at such faces, and connects them to an // +// "infinite vertex" (which has no geometric coordinates). One can imagine // +// such a vertex lies in 4D space and is visible by all exterior boundary // +// faces. The extended set of tetrahedra (including the infinite vertex) is // +// a tetrahedralization of a 3-pseudomanifold without boundary. It has the // +// property that every face is shared by exactly two tetrahedra. // +// // +// The current version of TetGen stores explicitly the subfaces and segments // +// (which are in surface mesh S and the linear mesh L), respectively. Extra // +// pointers are allocated in tetrahedra and subfaces to point each others. // +// // +/////////////////////////////////////////////////////////////////////////////// + + // The tetrahedron data structure. It includes the following fields: + // - a list of four adjoining tetrahedra; + // - a list of four vertices; + // - a pointer to a list of four subfaces (optional, for -p switch); + // - a pointer to a list of six segments (optional, for -p switch); + // - a list of user-defined floating-point attributes (optional); + // - a volume constraint (optional, for -a switch); + // - an integer of element marker (and flags); + // The structure of a tetrahedron is an array of pointers. Its actual size + // (the length of the array) is determined at runtime. + + typedef REAL **tetrahedron; + + // The subface data structure. It includes the following fields: + // - a list of three adjoining subfaces; + // - a list of three vertices; + // - a list of three adjoining segments; + // - two adjoining tetrahedra; + // - an area constraint (optional, for -q switch); + // - an integer for boundary marker; + // - an integer for type, flags, etc. + + typedef REAL **shellface; + + // The point data structure. It includes the following fields: + // - x, y and z coordinates; + // - a list of user-defined point attributes (optional); + // - u, v coordinates (optional, for -s switch); + // - a metric tensor (optional, for -q or -m switch); + // - a pointer to an adjacent tetrahedron; + // - a pointer to a parent (or a duplicate) point; + // - a pointer to an adjacent subface or segment (optional, -p switch); + // - a pointer to a tet in background mesh (optional, for -m switch); + // - an integer for boundary marker (point index); + // - an integer for point type (and flags). + // - an integer for geometry tag (optional, for -s switch). + // The structure of a point is an array of REALs. Its acutal size is + // determined at the runtime. + + typedef REAL *point; + +/////////////////////////////////////////////////////////////////////////////// +// // +// Handles // +// // +// Navigation and manipulation in a tetrahedralization are accomplished by // +// operating on structures referred as ``handles". A handle is a pair (t,v), // +// where t is a pointer to a tetrahedron, and v is a 4-bit integer, in the // +// range from 0 to 11. v is called the ``version'' of a tetrahedron, it rep- // +// resents a directed edge of a specific face of the tetrahedron. // +// // +// There are 12 even permutations of the four vertices, each of them corres- // +// ponds to a directed edge (a version) of the tetrahedron. The 12 versions // +// can be grouped into 4 distinct ``edge rings'' in 4 ``oriented faces'' of // +// this tetrahedron. One can encode each version (a directed edge) into a // +// 4-bit integer such that the two upper bits encode the index (from 0 to 2) // +// of this edge in the edge ring, and the two lower bits encode the index ( // +// from 0 to 3) of the oriented face which contains this edge. // +// // +// The four vertices of a tetrahedron are indexed from 0 to 3 (according to // +// their storage in the data structure). Give each face the same index as // +// the node opposite it in the tetrahedron. Denote the edge connecting face // +// i to face j as i/j. We number the twelve versions as follows: // +// // +// | edge 0 edge 1 edge 2 // +// --------|-------------------------------- // +// face 0 | 0 (0/1) 4 (0/3) 8 (0/2) // +// face 1 | 1 (1/2) 5 (1/3) 9 (1/0) // +// face 2 | 2 (2/3) 6 (2/1) 10 (2/0) // +// face 3 | 3 (3/0) 7 (3/1) 11 (3/2) // +// // +// Similarly, navigation and manipulation in a (boundary) triangulation are // +// done by using handles of triangles. Each handle is a pair (s, v), where s // +// is a pointer to a triangle, and v is a version in the range from 0 to 5. // +// Each version corresponds to a directed edge of this triangle. // +// // +// Number the three vertices of a triangle from 0 to 2 (according to their // +// storage in the data structure). Give each edge the same index as the node // +// opposite it in the triangle. The six versions of a triangle are: // +// // +// | edge 0 edge 1 edge 2 // +// ---------------|-------------------------- // +// ccw orieation | 0 2 4 // +// cw orieation | 1 3 5 // +// // +// In the following, a 'triface' is a handle of tetrahedron, and a 'face' is // +// a handle of a triangle. // +// // +/////////////////////////////////////////////////////////////////////////////// + + class triface { + public: + tetrahedron *tet; + int ver; // Range from 0 to 11. + triface() : tet(0), ver(0) {} + triface& operator=(const triface& t) { + tet = t.tet; ver = t.ver; + return *this; + } + }; + + class face { + public: + shellface *sh; + int shver; // Range from 0 to 5. + face() : sh(0), shver(0) {} + face& operator=(const face& s) { + sh = s.sh; shver = s.shver; + return *this; + } + }; + +/////////////////////////////////////////////////////////////////////////////// +// // +// Arraypool // +// // +// A dynamic linear array. (It is written by J. Shewchuk) // +// // +// Each arraypool contains an array of pointers to a number of blocks. Each // +// block contains the same fixed number of objects. Each index of the array // +// addresses a particular object in the pool. The most significant bits add- // +// ress the index of the block containing the object. The less significant // +// bits address this object within the block. // +// // +// 'objectbytes' is the size of one object in blocks; 'log2objectsperblock' // +// is the base-2 logarithm of 'objectsperblock'; 'objects' counts the number // +// of allocated objects; 'totalmemory' is the total memory in bytes. // +// // +/////////////////////////////////////////////////////////////////////////////// + + class arraypool { + + public: + + int objectbytes; + int objectsperblock; + int log2objectsperblock; + int objectsperblockmark; + int toparraylen; + char **toparray; + long objects; + unsigned long totalmemory; + + void restart(); + void poolinit(int sizeofobject, int log2objperblk); + char* getblock(int objectindex); + void* lookup(int objectindex); + int newindex(void **newptr); + + arraypool(int sizeofobject, int log2objperblk); + ~arraypool(); + }; + +// fastlookup() -- A fast, unsafe operation. Return the pointer to the object +// with a given index. Note: The object's block must have been allocated, +// i.e., by the function newindex(). + +#define fastlookup(pool, index) \ + (void *) ((pool)->toparray[(index) >> (pool)->log2objectsperblock] + \ + ((index) & (pool)->objectsperblockmark) * (pool)->objectbytes) + +/////////////////////////////////////////////////////////////////////////////// +// // +// Memorypool // +// // +// A structure for memory allocation. (It is written by J. Shewchuk) // +// // +// firstblock is the first block of items. nowblock is the block from which // +// items are currently being allocated. nextitem points to the next slab // +// of free memory for an item. deaditemstack is the head of a linked list // +// (stack) of deallocated items that can be recycled. unallocateditems is // +// the number of items that remain to be allocated from nowblock. // +// // +// Traversal is the process of walking through the entire list of items, and // +// is separate from allocation. Note that a traversal will visit items on // +// the "deaditemstack" stack as well as live items. pathblock points to // +// the block currently being traversed. pathitem points to the next item // +// to be traversed. pathitemsleft is the number of items that remain to // +// be traversed in pathblock. // +// // +/////////////////////////////////////////////////////////////////////////////// + + class memorypool { + + public: + + void **firstblock, **nowblock; + void *nextitem; + void *deaditemstack; + void **pathblock; + void *pathitem; + int alignbytes; + int itembytes, itemwords; + int itemsperblock; + long items, maxitems; + int unallocateditems; + int pathitemsleft; + + memorypool(); + memorypool(int, int, int, int); + ~memorypool(); + + void poolinit(int, int, int, int); + void restart(); + void *alloc(); + void dealloc(void*); + void traversalinit(); + void *traverse(); + }; + +/////////////////////////////////////////////////////////////////////////////// +// // +// badface // +// // +// Despite of its name, a 'badface' can be used to represent one of the // +// following objects: // +// - a face of a tetrahedron which is (possibly) non-Delaunay; // +// - an encroached subsegment or subface; // +// - a bad-quality tetrahedron, i.e, has too large radius-edge ratio; // +// - a sliver, i.e., has good radius-edge ratio but nearly zero volume; // +// - a recently flipped face (saved for undoing the flip later). // +// // +/////////////////////////////////////////////////////////////////////////////// + + class badface { + public: + triface tt; + face ss; + REAL key, cent[6]; // circumcenter or cos(dihedral angles) at 6 edges. + point forg, fdest, fapex, foppo, noppo; + badface *nextitem; + badface() : key(0), forg(0), fdest(0), fapex(0), foppo(0), noppo(0), + nextitem(0) {} + }; + +/////////////////////////////////////////////////////////////////////////////// +// // +// insertvertexflags // +// // +// A collection of flags that pass to the routine insertvertex(). // +// // +/////////////////////////////////////////////////////////////////////////////// + + class insertvertexflags { + + public: + + int iloc; // input/output. + int bowywat, lawson; + int splitbdflag, validflag, respectbdflag; + int rejflag, chkencflag, cdtflag; + int assignmeshsize; + int sloc, sbowywat; + + // Used by Delaunay refinement. + int refineflag; // 0, 1, 2, 3 + triface refinetet; + face refinesh; + int smlenflag; // for useinsertradius. + REAL smlen; // for useinsertradius. + point parentpt; + + insertvertexflags() { + iloc = bowywat = lawson = 0; + splitbdflag = validflag = respectbdflag = 0; + rejflag = chkencflag = cdtflag = 0; + assignmeshsize = 0; + sloc = sbowywat = 0; + + refineflag = 0; + refinetet.tet = NULL; + refinesh.sh = NULL; + smlenflag = 0; + smlen = 0.0; + } + }; + +/////////////////////////////////////////////////////////////////////////////// +// // +// flipconstraints // +// // +// A structure of a collection of data (options and parameters) which pass // +// to the edge flip function flipnm(). // +// // +/////////////////////////////////////////////////////////////////////////////// + + class flipconstraints { + + public: + + // Elementary flip flags. + int enqflag; // (= flipflag) + int chkencflag; + + // Control flags + int unflip; // Undo the performed flips. + int collectnewtets; // Collect the new tets created by flips. + int collectencsegflag; + + // Optimization flags. + int remove_ndelaunay_edge; // Remove a non-Delaunay edge. + REAL bak_tetprism_vol; // The value to be minimized. + REAL tetprism_vol_sum; + int remove_large_angle; // Remove a large dihedral angle at edge. + REAL cosdihed_in; // The input cosine of the dihedral angle (> 0). + REAL cosdihed_out; // The improved cosine of the dihedral angle. + + // Boundary recovery flags. + int checkflipeligibility; + point seg[2]; // A constraining edge to be recovered. + point fac[3]; // A constraining face to be recovered. + point remvert; // A vertex to be removed. + + + flipconstraints() { + enqflag = 0; + chkencflag = 0; + + unflip = 0; + collectnewtets = 0; + collectencsegflag = 0; + + remove_ndelaunay_edge = 0; + bak_tetprism_vol = 0.0; + tetprism_vol_sum = 0.0; + remove_large_angle = 0; + cosdihed_in = 0.0; + cosdihed_out = 0.0; + + checkflipeligibility = 0; + seg[0] = NULL; + fac[0] = NULL; + remvert = NULL; + } + }; + +/////////////////////////////////////////////////////////////////////////////// +// // +// optparameters // +// // +// Optimization options and parameters. // +// // +/////////////////////////////////////////////////////////////////////////////// + + class optparameters { + + public: + + // The one of goals of optimization. + int max_min_volume; // Maximize the minimum volume. + int max_min_aspectratio; // Maximize the minimum aspect ratio. + int min_max_dihedangle; // Minimize the maximum dihedral angle. + + // The initial and improved value. + REAL initval, imprval; + + int numofsearchdirs; + REAL searchstep; + int maxiter; // Maximum smoothing iterations (disabled by -1). + int smthiter; // Performed iterations. + + + optparameters() { + max_min_volume = 0; + max_min_aspectratio = 0; + min_max_dihedangle = 0; + + initval = imprval = 0.0; + + numofsearchdirs = 10; + searchstep = 0.01; + maxiter = -1; // Unlimited smoothing iterations. + smthiter = 0; + + } + }; + + +/////////////////////////////////////////////////////////////////////////////// +// // +// Labels (enumeration declarations) used by TetGen. // +// // +/////////////////////////////////////////////////////////////////////////////// + + // Labels that signify the type of a vertex. + enum verttype {UNUSEDVERTEX, DUPLICATEDVERTEX, RIDGEVERTEX, ACUTEVERTEX, + FACETVERTEX, VOLVERTEX, FREESEGVERTEX, FREEFACETVERTEX, + FREEVOLVERTEX, NREGULARVERTEX, DEADVERTEX}; + + // Labels that signify the result of triangle-triangle intersection test. + enum interresult {DISJOINT, INTERSECT, SHAREVERT, SHAREEDGE, SHAREFACE, + TOUCHEDGE, TOUCHFACE, ACROSSVERT, ACROSSEDGE, ACROSSFACE, + COLLISIONFACE, ACROSSSEG, ACROSSSUB}; + + // Labels that signify the result of point location. + enum locateresult {UNKNOWN, OUTSIDE, INTETRAHEDRON, ONFACE, ONEDGE, ONVERTEX, + ENCVERTEX, ENCSEGMENT, ENCSUBFACE, NEARVERTEX, NONREGULAR, + INSTAR, BADELEMENT}; + +/////////////////////////////////////////////////////////////////////////////// +// // +// Variables of TetGen // +// // +/////////////////////////////////////////////////////////////////////////////// + + // Pointer to the input data (a set of nodes, a PLC, or a mesh). + tetgenio *in, *addin; + + // Pointer to the switches and parameters. + tetgenbehavior *b; + + // Pointer to a background mesh (contains size specification map). + tetgenmesh *bgm; + + // Memorypools to store mesh elements (points, tetrahedra, subfaces, and + // segments) and extra pointers between tetrahedra, subfaces, and segments. + memorypool *tetrahedrons, *subfaces, *subsegs, *points; + memorypool *tet2subpool, *tet2segpool; + + // Memorypools to store bad-quality (or encroached) elements. + memorypool *badtetrahedrons, *badsubfacs, *badsubsegs; + + // A memorypool to store faces to be flipped. + memorypool *flippool; + arraypool *unflipqueue; + badface *flipstack; + + // Arrays used for point insertion (the Bowyer-Watson algorithm). + arraypool *cavetetlist, *cavebdrylist, *caveoldtetlist; + arraypool *cavetetshlist, *cavetetseglist, *cavetetvertlist; + arraypool *caveencshlist, *caveencseglist; + arraypool *caveshlist, *caveshbdlist, *cavesegshlist; + + // Stacks used for CDT construction and boundary recovery. + arraypool *subsegstack, *subfacstack, *subvertstack; + + // Arrays of encroached segments and subfaces (for mesh refinement). + arraypool *encseglist, *encshlist; + + // The map between facets to their vertices (for mesh refinement). + int *idx2facetlist; + point *facetverticeslist; + + // The map between segments to their endpoints (for mesh refinement). + point *segmentendpointslist; + + // The infinite vertex. + point dummypoint; + // The recently visited tetrahedron, subface. + triface recenttet; + face recentsh; + + // PI is the ratio of a circle's circumference to its diameter. + static REAL PI; + + // Array (size = numberoftetrahedra * 6) for storing high-order nodes of + // tetrahedra (only used when -o2 switch is selected). + point *highordertable; + + // Various variables. + int numpointattrib; // Number of point attributes. + int numelemattrib; // Number of tetrahedron attributes. + int sizeoftensor; // Number of REALs per metric tensor. + int pointmtrindex; // Index to find the metric tensor of a point. + int pointparamindex; // Index to find the u,v coordinates of a point. + int point2simindex; // Index to find a simplex adjacent to a point. + int pointmarkindex; // Index to find boundary marker of a point. + int elemattribindex; // Index to find attributes of a tetrahedron. + int volumeboundindex; // Index to find volume bound of a tetrahedron. + int elemmarkerindex; // Index to find marker of a tetrahedron. + int shmarkindex; // Index to find boundary marker of a subface. + int areaboundindex; // Index to find area bound of a subface. + int checksubsegflag; // Are there segments in the tetrahedralization yet? + int checksubfaceflag; // Are there subfaces in the tetrahedralization yet? + int checkconstraints; // Are there variant (node, seg, facet) constraints? + int nonconvex; // Is current mesh non-convex? + int autofliplinklevel; // The increase of link levels, default is 1. + int useinsertradius; // Save the insertion radius for Steiner points. + long samples; // Number of random samples for point location. + unsigned long randomseed; // Current random number seed. + REAL cosmaxdihed, cosmindihed; // The cosine values of max/min dihedral. + REAL cossmtdihed; // The cosine value of a bad dihedral to be smoothed. + REAL cosslidihed; // The cosine value of the max dihedral of a sliver. + REAL minfaceang, minfacetdihed; // The minimum input (dihedral) angles. + REAL tetprism_vol_sum; // The total volume of tetrahedral-prisms (in 4D). + REAL longest; // The longest possible edge length. + REAL xmax, xmin, ymax, ymin, zmax, zmin; // Bounding box of points. + + // Counters. + long insegments; // Number of input segments. + long hullsize; // Number of exterior boundary faces. + long meshedges; // Number of mesh edges. + long meshhulledges; // Number of boundary mesh edges. + long steinerleft; // Number of Steiner points not yet used. + long dupverts; // Are there duplicated vertices? + long unuverts; // Are there unused vertices? + long nonregularcount; // Are there non-regular vertices? + long st_segref_count, st_facref_count, st_volref_count; // Steiner points. + long fillregioncount, cavitycount, cavityexpcount; + long flip14count, flip26count, flipn2ncount; + long flip23count, flip32count, flip44count, flip41count; + long flip31count, flip22count; + unsigned long totalworkmemory; // Total memory used by working arrays. + + +/////////////////////////////////////////////////////////////////////////////// +// // +// Mesh manipulation primitives // +// // +/////////////////////////////////////////////////////////////////////////////// + + // Fast lookup tables for mesh manipulation primitives. + static int bondtbl[12][12], fsymtbl[12][12]; + static int esymtbl[12], enexttbl[12], eprevtbl[12]; + static int enextesymtbl[12], eprevesymtbl[12]; + static int eorgoppotbl[12], edestoppotbl[12]; + static int facepivot1[12], facepivot2[12][12]; + static int orgpivot[12], destpivot[12], apexpivot[12], oppopivot[12]; + static int tsbondtbl[12][6], stbondtbl[12][6]; + static int tspivottbl[12][6], stpivottbl[12][6]; + static int ver2edge[12], edge2ver[6], epivot[12]; + static int sorgpivot [6], sdestpivot[6], sapexpivot[6]; + static int snextpivot[6]; + + void inittables(); + + // Primitives for tetrahedra. + inline tetrahedron encode(triface& t); + inline tetrahedron encode2(tetrahedron* ptr, int ver); + inline void decode(tetrahedron ptr, triface& t); + inline void bond(triface& t1, triface& t2); + inline void dissolve(triface& t); + inline void esym(triface& t1, triface& t2); + inline void esymself(triface& t); + inline void enext(triface& t1, triface& t2); + inline void enextself(triface& t); + inline void eprev(triface& t1, triface& t2); + inline void eprevself(triface& t); + inline void enextesym(triface& t1, triface& t2); + inline void enextesymself(triface& t); + inline void eprevesym(triface& t1, triface& t2); + inline void eprevesymself(triface& t); + inline void eorgoppo(triface& t1, triface& t2); + inline void eorgoppoself(triface& t); + inline void edestoppo(triface& t1, triface& t2); + inline void edestoppoself(triface& t); + inline void fsym(triface& t1, triface& t2); + inline void fsymself(triface& t); + inline void fnext(triface& t1, triface& t2); + inline void fnextself(triface& t); + inline point org (triface& t); + inline point dest(triface& t); + inline point apex(triface& t); + inline point oppo(triface& t); + inline void setorg (triface& t, point p); + inline void setdest(triface& t, point p); + inline void setapex(triface& t, point p); + inline void setoppo(triface& t, point p); + inline REAL elemattribute(tetrahedron* ptr, int attnum); + inline void setelemattribute(tetrahedron* ptr, int attnum, REAL value); + inline REAL volumebound(tetrahedron* ptr); + inline void setvolumebound(tetrahedron* ptr, REAL value); + inline int elemindex(tetrahedron* ptr); + inline void setelemindex(tetrahedron* ptr, int value); + inline int elemmarker(tetrahedron* ptr); + inline void setelemmarker(tetrahedron* ptr, int value); + inline void infect(triface& t); + inline void uninfect(triface& t); + inline bool infected(triface& t); + inline void marktest(triface& t); + inline void unmarktest(triface& t); + inline bool marktested(triface& t); + inline void markface(triface& t); + inline void unmarkface(triface& t); + inline bool facemarked(triface& t); + inline void markedge(triface& t); + inline void unmarkedge(triface& t); + inline bool edgemarked(triface& t); + inline void marktest2(triface& t); + inline void unmarktest2(triface& t); + inline bool marktest2ed(triface& t); + inline int elemcounter(triface& t); + inline void setelemcounter(triface& t, int value); + inline void increaseelemcounter(triface& t); + inline void decreaseelemcounter(triface& t); + inline bool ishulltet(triface& t); + inline bool isdeadtet(triface& t); + + // Primitives for subfaces and subsegments. + inline void sdecode(shellface sptr, face& s); + inline shellface sencode(face& s); + inline shellface sencode2(shellface *sh, int shver); + inline void spivot(face& s1, face& s2); + inline void spivotself(face& s); + inline void sbond(face& s1, face& s2); + inline void sbond1(face& s1, face& s2); + inline void sdissolve(face& s); + inline point sorg(face& s); + inline point sdest(face& s); + inline point sapex(face& s); + inline void setsorg(face& s, point pointptr); + inline void setsdest(face& s, point pointptr); + inline void setsapex(face& s, point pointptr); + inline void sesym(face& s1, face& s2); + inline void sesymself(face& s); + inline void senext(face& s1, face& s2); + inline void senextself(face& s); + inline void senext2(face& s1, face& s2); + inline void senext2self(face& s); + inline REAL areabound(face& s); + inline void setareabound(face& s, REAL value); + inline int shellmark(face& s); + inline void setshellmark(face& s, int value); + inline void sinfect(face& s); + inline void suninfect(face& s); + inline bool sinfected(face& s); + inline void smarktest(face& s); + inline void sunmarktest(face& s); + inline bool smarktested(face& s); + inline void smarktest2(face& s); + inline void sunmarktest2(face& s); + inline bool smarktest2ed(face& s); + inline void smarktest3(face& s); + inline void sunmarktest3(face& s); + inline bool smarktest3ed(face& s); + inline void setfacetindex(face& f, int value); + inline int getfacetindex(face& f); + + // Primitives for interacting tetrahedra and subfaces. + inline void tsbond(triface& t, face& s); + inline void tsdissolve(triface& t); + inline void stdissolve(face& s); + inline void tspivot(triface& t, face& s); + inline void stpivot(face& s, triface& t); + + // Primitives for interacting tetrahedra and segments. + inline void tssbond1(triface& t, face& seg); + inline void sstbond1(face& s, triface& t); + inline void tssdissolve1(triface& t); + inline void sstdissolve1(face& s); + inline void tsspivot1(triface& t, face& s); + inline void sstpivot1(face& s, triface& t); + + // Primitives for interacting subfaces and segments. + inline void ssbond(face& s, face& edge); + inline void ssbond1(face& s, face& edge); + inline void ssdissolve(face& s); + inline void sspivot(face& s, face& edge); + + // Primitives for points. + inline int pointmark(point pt); + inline void setpointmark(point pt, int value); + inline enum verttype pointtype(point pt); + inline void setpointtype(point pt, enum verttype value); + inline int pointgeomtag(point pt); + inline void setpointgeomtag(point pt, int value); + inline REAL pointgeomuv(point pt, int i); + inline void setpointgeomuv(point pt, int i, REAL value); + inline void pinfect(point pt); + inline void puninfect(point pt); + inline bool pinfected(point pt); + inline void pmarktest(point pt); + inline void punmarktest(point pt); + inline bool pmarktested(point pt); + inline void pmarktest2(point pt); + inline void punmarktest2(point pt); + inline bool pmarktest2ed(point pt); + inline void pmarktest3(point pt); + inline void punmarktest3(point pt); + inline bool pmarktest3ed(point pt); + inline tetrahedron point2tet(point pt); + inline void setpoint2tet(point pt, tetrahedron value); + inline shellface point2sh(point pt); + inline void setpoint2sh(point pt, shellface value); + inline point point2ppt(point pt); + inline void setpoint2ppt(point pt, point value); + inline tetrahedron point2bgmtet(point pt); + inline void setpoint2bgmtet(point pt, tetrahedron value); + inline void setpointinsradius(point pt, REAL value); + inline REAL getpointinsradius(point pt); + + // Advanced primitives. + inline void point2tetorg(point pt, triface& t); + inline void point2shorg(point pa, face& s); + inline point farsorg(face& seg); + inline point farsdest(face& seg); + +/////////////////////////////////////////////////////////////////////////////// +// // +// Memory managment // +// // +/////////////////////////////////////////////////////////////////////////////// + + void tetrahedrondealloc(tetrahedron*); + tetrahedron *tetrahedrontraverse(); + tetrahedron *alltetrahedrontraverse(); + void shellfacedealloc(memorypool*, shellface*); + shellface *shellfacetraverse(memorypool*); + void pointdealloc(point); + point pointtraverse(); + + void makeindex2pointmap(point*&); + void makepoint2submap(memorypool*, int*&, face*&); + void maketetrahedron(triface*); + void makeshellface(memorypool*, face*); + void makepoint(point*, enum verttype); + + void initializepools(); + +/////////////////////////////////////////////////////////////////////////////// +// // +// Advanced geometric predicates and calculations // +// // +// TetGen uses a simplified symbolic perturbation scheme from Edelsbrunner, // +// et al [*]. Hence the point-in-sphere test never returns a zero. The idea // +// is to perturb the weights of vertices in the fourth dimension. TetGen // +// uses the indices of the vertices decide the amount of perturbation. It is // +// implemented in the routine insphere_s(). +// // +// The routine tri_edge_test() determines whether or not a triangle and an // +// edge intersect in 3D. If they intersect, their intersection type is also // +// reported. This test is a combination of n 3D orientation tests (n is bet- // +// ween 3 and 9). It uses the robust orient3d() test to make the branch dec- // +// isions. The routine tri_tri_test() determines whether or not two triang- // +// les intersect in 3D. It also uses the robust orient3d() test. // +// // +// There are a number of routines to calculate geometrical quantities, e.g., // +// circumcenters, angles, dihedral angles, face normals, face areas, etc. // +// They are so far done by the default floating-point arithmetics which are // +// non-robust. They should be improved in the future. // +// // +/////////////////////////////////////////////////////////////////////////////// + + // Symbolic perturbations (robust) + REAL insphere_s(REAL*, REAL*, REAL*, REAL*, REAL*); + REAL orient4d_s(REAL*, REAL*, REAL*, REAL*, REAL*, + REAL, REAL, REAL, REAL, REAL); + + // Triangle-edge intersection test (robust) + int tri_edge_2d(point, point, point, point, point, point, int, int*, int*); + int tri_edge_tail(point, point, point, point, point, point, REAL, REAL, int, + int*, int*); + int tri_edge_test(point, point, point, point, point, point, int, int*, int*); + + // Triangle-triangle intersection test (robust) + int tri_edge_inter_tail(point, point, point, point, point, REAL, REAL); + int tri_tri_inter(point, point, point, point, point, point); + + // Linear algebra functions + inline REAL dot(REAL* v1, REAL* v2); + inline void cross(REAL* v1, REAL* v2, REAL* n); + bool lu_decmp(REAL lu[4][4], int n, int* ps, REAL* d, int N); + void lu_solve(REAL lu[4][4], int n, int* ps, REAL* b, int N); + + // An embedded 2-dimensional geometric predicate (non-robust) + REAL incircle3d(point pa, point pb, point pc, point pd); + + // Geometric calculations (non-robust) + REAL orient3dfast(REAL *pa, REAL *pb, REAL *pc, REAL *pd); + inline REAL norm2(REAL x, REAL y, REAL z); + inline REAL distance(REAL* p1, REAL* p2); + void facenormal(point pa, point pb, point pc, REAL *n, int pivot, REAL *lav); + REAL shortdistance(REAL* p, REAL* e1, REAL* e2); + REAL triarea(REAL* pa, REAL* pb, REAL* pc); + REAL interiorangle(REAL* o, REAL* p1, REAL* p2, REAL* n); + void projpt2edge(REAL* p, REAL* e1, REAL* e2, REAL* prj); + void projpt2face(REAL* p, REAL* f1, REAL* f2, REAL* f3, REAL* prj); + REAL facedihedral(REAL* pa, REAL* pb, REAL* pc1, REAL* pc2); + bool tetalldihedral(point, point, point, point, REAL*, REAL*, REAL*); + void tetallnormal(point, point, point, point, REAL N[4][3], REAL* volume); + REAL tetaspectratio(point, point, point, point); + bool circumsphere(REAL*, REAL*, REAL*, REAL*, REAL* cent, REAL* radius); + bool orthosphere(REAL*,REAL*,REAL*,REAL*,REAL,REAL,REAL,REAL,REAL*,REAL*); + void planelineint(REAL*, REAL*, REAL*, REAL*, REAL*, REAL*, REAL*); + int linelineint(REAL*, REAL*, REAL*, REAL*, REAL*, REAL*, REAL*, REAL*); + REAL tetprismvol(REAL* pa, REAL* pb, REAL* pc, REAL* pd); + bool calculateabovepoint(arraypool*, point*, point*, point*); + void calculateabovepoint4(point, point, point, point); + +/////////////////////////////////////////////////////////////////////////////// +// // +// Local mesh transformations // +// // +// A local transformation replaces a small set of tetrahedra with another // +// set of tetrahedra which fills the same space and the same boundaries. // +// In 3D, the most simplest local transformations are the elementary flips // +// performed within the convex hull of five vertices: 2-to-3, 3-to-2, 1-to-4,// +// and 4-to-1 flips, where the numbers indicate the number of tetrahedra // +// before and after each flip. The 1-to-4 and 4-to-1 flip involve inserting // +// or deleting a vertex, respectively. // +// There are complex local transformations which can be decomposed as a // +// combination of elementary flips. For example,a 4-to-4 flip which replaces // +// two coplanar edges can be regarded by a 2-to-3 flip and a 3-to-2 flip. // +// Note that the first 2-to-3 flip will temporarily create a degenerate tet- // +// rahedron which is removed immediately by the followed 3-to-2 flip. More // +// generally, a n-to-m flip, where n > 3, m = (n - 2) * 2, which removes an // +// edge can be done by first performing a sequence of (n - 3) 2-to-3 flips // +// followed by a 3-to-2 flip. // +// // +// The routines flip23(), flip32(), and flip41() perform the three element- // +// ray flips. The flip14() is available inside the routine insertpoint(). // +// // +// The routines flipnm() and flipnm_post() implement a generalized edge flip // +// algorithm which uses a combination of elementary flips. // +// // +// The routine insertpoint() implements a variant of Bowyer-Watson's cavity // +// algorithm to insert a vertex. It works for arbitrary tetrahedralization, // +// either Delaunay, or constrained Delaunay, or non-Delaunay. // +// // +/////////////////////////////////////////////////////////////////////////////// + + // The elementary flips. + void flip23(triface*, int, flipconstraints* fc); + void flip32(triface*, int, flipconstraints* fc); + void flip41(triface*, int, flipconstraints* fc); + + // A generalized edge flip. + int flipnm(triface*, int n, int level, int, flipconstraints* fc); + int flipnm_post(triface*, int n, int nn, int, flipconstraints* fc); + + // Point insertion. + int insertpoint(point, triface*, face*, face*, insertvertexflags*); + void insertpoint_abort(face*, insertvertexflags*); + +/////////////////////////////////////////////////////////////////////////////// +// // +// Delaunay tetrahedralization // +// // +// The routine incrementaldelaunay() implemented two incremental algorithms // +// for constructing Delaunay tetrahedralizations (DTs): the Bowyer-Watson // +// (B-W) algorithm and the incremental flip algorithm of Edelsbrunner and // +// Shah, "Incremental topological flipping works for regular triangulation," // +// Algorithmica, 15:233-241, 1996. // +// // +// The routine incrementalflip() implements the flip algorithm of [Edelsbru- // +// nner and Shah, 1996]. It flips a queue of locally non-Delaunay faces (in // +// an arbitrary order). The success is guaranteed when the Delaunay tetrah- // +// edralization is constructed incrementally by adding one vertex at a time. // +// // +// The routine locate() finds a tetrahedron contains a new point in current // +// DT. It uses a simple stochastic walk algorithm: starting from an arbitr- // +// ary tetrahedron in DT, it finds the destination by visit one tetrahedron // +// at a time, randomly chooses a tetrahedron if there are more than one // +// choices. This algorithm terminates due to Edelsbrunner's acyclic theorem. // +// Choose a good starting tetrahedron is crucial to the speed of the walk. // +// TetGen originally uses the "jump-and-walk" algorithm of Muecke, E.P., // +// Saias, I., and Zhu, B. "Fast Randomized Point Location Without Preproces- // +// sing." In Proceedings of the 12th ACM Symposium on Computational Geometry,// +// 274-283, 1996. It first randomly samples several tetrahedra in the DT // +// and then choosing the closet one to start walking. // +// The above algorithm slows download dramatically as the number of points // +// grows -- reported in Amenta, N., Choi, S. and Rote, G., "Incremental // +// construction con {BRIO}," In Proceedings of 19th ACM Symposium on // +// Computational Geometry, 211-219, 2003. On the other hand, Liu and // +// Snoeyink showed that the point location can be made in constant time if // +// the points are pre-sorted so that the nearby points in space have nearby // +// indices, then adding the points in this order. They sorted the points // +// along the 3D Hilbert curve. // +// // +// The routine hilbert_sort3() sorts a set of 3D points along the 3D Hilbert // +// curve. It recursively splits a point set according to the Hilbert indices // +// mapped to the subboxes of the bounding box of the point set. // +// The Hilbert indices is calculated by Butz's algorithm in 1971. A nice // +// exposition of this algorithm can be found in the paper of Hamilton, C., // +// "Compact Hilbert Indices", Technical Report CS-2006-07, Computer Science, // +// Dalhousie University, 2006 (the Section 2). My implementation also refer- // +// enced Steven Witham's implementation of "Hilbert walk" (hopefully, it is // +// still available at: http://www.tiac.net/~sw/2008/10/Hilbert/). // +// // +// TetGen sorts the points using the method in the paper of Boissonnat,J.-D.,// +// Devillers, O. and Hornus, S. "Incremental Construction of the Delaunay // +// Triangulation and the Delaunay Graph in Medium Dimension," In Proceedings // +// of the 25th ACM Symposium on Computational Geometry, 2009. // +// It first randomly sorts the points into subgroups using the Biased Rand-// +// omized Insertion Ordering (BRIO) of Amenta et al 2003, then sorts the // +// points in each subgroup along the 3D Hilbert curve. Inserting points in // +// this order ensures a randomized "sprinkling" of the points over the // +// domain, while sorting of each subset ensures locality. // +// // +/////////////////////////////////////////////////////////////////////////////// + + void transfernodes(); + + // Point sorting. + int transgc[8][3][8], tsb1mod3[8]; + void hilbert_init(int n); + int hilbert_split(point* vertexarray, int arraysize, int gc0, int gc1, + REAL, REAL, REAL, REAL, REAL, REAL); + void hilbert_sort3(point* vertexarray, int arraysize, int e, int d, + REAL, REAL, REAL, REAL, REAL, REAL, int depth); + void brio_multiscale_sort(point*,int,int threshold,REAL ratio,int* depth); + + // Point location. + unsigned long randomnation(unsigned int choices); + void randomsample(point searchpt, triface *searchtet); + enum locateresult locate(point searchpt, triface *searchtet); + + // Incremental flips. + void flippush(badface*&, triface*); + int incrementalflip(point newpt, int, flipconstraints *fc); + + // Incremental Delaunay construction. + void initialdelaunay(point pa, point pb, point pc, point pd); + void incrementaldelaunay(clock_t&); + +/////////////////////////////////////////////////////////////////////////////// +// // +// Surface triangulation // +// // +/////////////////////////////////////////////////////////////////////////////// + + void flipshpush(face*); + void flip22(face*, int, int); + void flip31(face*, int); + long lawsonflip(); + int sinsertvertex(point newpt, face*, face*, int iloc, int bowywat, int); + int sremovevertex(point delpt, face*, face*, int lawson); + + enum locateresult slocate(point, face*, int, int, int); + enum interresult sscoutsegment(face*, point); + void scarveholes(int, REAL*); + void triangulate(int, arraypool*, arraypool*, int, REAL*); + + void unifysubfaces(face*, face*); + void unifysegments(); + void mergefacets(); + void identifypscedges(point*); + void meshsurface(); + + void interecursive(shellface** subfacearray, int arraysize, int axis, + REAL, REAL, REAL, REAL, REAL, REAL, int* internum); + void detectinterfaces(); + +/////////////////////////////////////////////////////////////////////////////// +// // +// Constrained Delaunay tetrahedralization // +// // +// A constrained Delaunay tetrahedralization (CDT) is a variation of a Dela- // +// unay tetrahedralization (DT) that is constrained to respect the boundary // +// of a 3D PLC (domain). In a CDT of a 3D PLC, every vertex or edge of the // +// PLC is also a vertex or an edge of the CDT, every polygon of the PLC is a // +// union of triangles of the CDT. A crucial difference between a CDT and a // +// DT is that triangles in the PLC's polygons are not required to be locally // +// Delaunay, which frees the CDT to better respect the PLC's polygons. CDTs // +// have optimal properties similar to those of DTs. // +// // +// Steiner Points and Steiner CDTs. It is known that even a simple 3D polyh- // +// edron may not have a tetrahedralization which only uses its own vertices. // +// Some extra points, so-called "Steiner points" are needed in order to form // +// a tetrahedralization of such polyhedron. It is true for tetrahedralizing // +// a 3D PLC as well. A Steiner CDT of a 3D PLC is a CDT containing Steiner // +// points. The CDT algorithms of TetGen in general create Steiner CDTs. // +// Almost all of the Steiner points are added in the edges of the PLC. They // +// guarantee the existence of a CDT of the modified PLC. // +// // +// The routine constraineddelaunay() starts from a DT of the vertices of a // +// PLC and creates a (Steiner) CDT of the PLC (including Steiner points). It // +// is constructed by two steps, (1) segment recovery and (2) facet (polygon) // +// recovery. Each step is accomplished by its own algorithm. // +// // +// The routine delaunizesegments() implements the segment recovery algorithm // +// of Si, H. and Gaertner, K. "Meshing Piecewise Linear Complexes by Constr- // +// ained Delaunay Tetrahedralizations," In Proceedings of the 14th Internat- // +// ional Meshing Roundtable, 147--163, 2005. It adds Steiner points into // +// non-Delaunay segments until all subsegments appear together in a DT. The // +// running time of this algorithm is proportional to the number of added // +// Steiner points. // +// // +// There are two incremental facet recovery algorithms: the cavity re-trian- // +// gulation algorithm of Si, H. and Gaertner, K. "3D Boundary Recovery by // +// Constrained Delaunay Tetrahedralization," International Journal for Numer-// +// ical Methods in Engineering, 85:1341-1364, 2011, and the flip algorithm // +// of Shewchuk, J. "Updating and Constructing Constrained Delaunay and // +// Constrained Regular Triangulations by Flips." In Proceedings of the 19th // +// ACM Symposium on Computational Geometry, 86-95, 2003. // +// // +// It is guaranteed in theory, no Steiner point is needed in both algorithms // +// However, a facet with non-coplanar vertices might cause the additions of // +// Steiner points. It is discussed in the paper of Si, H., and Shewchuk, J.,// +// "Incrementally Constructing and Updating Constrained Delaunay // +// Tetrahedralizations with Finite Precision Coordinates." In Proceedings of // +// the 21th International Meshing Roundtable, 2012. // +// // +// Our implementation of the facet recovery algorithms recover a "missing // +// region" at a time. Each missing region is a subset of connected interiors // +// of a polygon. The routine formcavity() creates the cavity of crossing // +// tetrahedra of the missing region. // +// // +// The cavity re-triangulation algorithm is implemented by three subroutines,// +// delaunizecavity(), fillcavity(), and carvecavity(). Since it may fail due // +// to non-coplanar vertices, the subroutine restorecavity() is used to rest- // +// ore the original cavity. // +// // +// The routine flipinsertfacet() implements the flip algorithm. The subrout- // +// ine flipcertify() is used to maintain the priority queue of flips. // +// // +// The routine refineregion() is called when the facet recovery algorithm // +// fail to recover a missing region. It inserts Steiner points to refine the // +// missing region. In order to avoid inserting Steiner points very close to // +// existing segments. The classical encroachment rules of the Delaunay // +// refinement algorithm are used to choose the Steiner points. // +// // +// The routine constrainedfacets() does the facet recovery by using either // +// the cavity re-triangulation algorithm (default) or the flip algorithm. It // +// results a CDT of the (modified) PLC (including Steiner points). // +// // +/////////////////////////////////////////////////////////////////////////////// + + void makesegmentendpointsmap(); + + enum interresult finddirection(triface* searchtet, point endpt); + enum interresult scoutsegment(point, point, triface*, point*, arraypool*); + int getsteinerptonsegment(face* seg, point refpt, point steinpt); + void delaunizesegments(); + + enum interresult scoutsubface(face* searchsh, triface* searchtet); + void formregion(face*, arraypool*, arraypool*, arraypool*); + int scoutcrossedge(triface& crosstet, arraypool*, arraypool*); + bool formcavity(triface*, arraypool*, arraypool*, arraypool*, arraypool*, + arraypool*, arraypool*); + + // Facet recovery by cavity re-triangulation [Si and Gaertner 2011]. + void delaunizecavity(arraypool*, arraypool*, arraypool*, arraypool*, + arraypool*, arraypool*); + bool fillcavity(arraypool*, arraypool*, arraypool*, arraypool*, + arraypool*, arraypool*, triface* crossedge); + void carvecavity(arraypool*, arraypool*, arraypool*); + void restorecavity(arraypool*, arraypool*, arraypool*, arraypool*); + + // Facet recovery by flips [Shewchuk 2003]. + void flipcertify(triface *chkface, badface **pqueue, point, point, point); + void flipinsertfacet(arraypool*, arraypool*, arraypool*, arraypool*); + + bool fillregion(arraypool* missingshs, arraypool*, arraypool* newshs); + + int insertpoint_cdt(point, triface*, face*, face*, insertvertexflags*, + arraypool*, arraypool*, arraypool*, arraypool*, + arraypool*, arraypool*); + void refineregion(face&, arraypool*, arraypool*, arraypool*, arraypool*, + arraypool*, arraypool*); + + void constrainedfacets(); + + void constraineddelaunay(clock_t&); + +/////////////////////////////////////////////////////////////////////////////// +// // +// Constrained tetrahedralizations. // +// // +/////////////////////////////////////////////////////////////////////////////// + + int checkflipeligibility(int fliptype, point, point, point, point, point, + int level, int edgepivot, flipconstraints* fc); + + int removeedgebyflips(triface*, flipconstraints*); + int removefacebyflips(triface*, flipconstraints*); + + int recoveredgebyflips(point, point, triface*, int fullsearch); + int add_steinerpt_in_schoenhardtpoly(triface*, int, int chkencflag); + int add_steinerpt_in_segment(face*, int searchlevel); + int addsteiner4recoversegment(face*, int); + int recoversegments(arraypool*, int fullsearch, int steinerflag); + + int recoverfacebyflips(point, point, point, face*, triface*); + int recoversubfaces(arraypool*, int steinerflag); + + int getvertexstar(int, point searchpt, arraypool*, arraypool*, arraypool*); + int getedge(point, point, triface*); + int reduceedgesatvertex(point startpt, arraypool* endptlist); + int removevertexbyflips(point steinerpt); + + int suppressbdrysteinerpoint(point steinerpt); + int suppresssteinerpoints(); + + void recoverboundary(clock_t&); + +/////////////////////////////////////////////////////////////////////////////// +// // +// Mesh reconstruction // +// // +/////////////////////////////////////////////////////////////////////////////// + + void carveholes(); + + void reconstructmesh(); + + int scoutpoint(point, triface*, int randflag); + REAL getpointmeshsize(point, triface*, int iloc); + void interpolatemeshsize(); + + void insertconstrainedpoints(point *insertarray, int arylen, int rejflag); + void insertconstrainedpoints(tetgenio *addio); + + void collectremovepoints(arraypool *remptlist); + void meshcoarsening(); + +/////////////////////////////////////////////////////////////////////////////// +// // +// Mesh refinement // +// // +// The purpose of mesh refinement is to obtain a tetrahedral mesh with well- // +// -shaped tetrahedra and appropriate mesh size. It is necessary to insert // +// new Steiner points to achieve this property. The questions are (1) how to // +// choose the Steiner points? and (2) how to insert them? // +// // +// Delaunay refinement is a technique first developed by Chew [1989] and // +// Ruppert [1993, 1995] to generate quality triangular meshes in the plane. // +// It provides guarantee on the smallest angle of the triangles. Rupper's // +// algorithm guarantees that the mesh is size-optimal (to within a constant // +// factor) among all meshes with the same quality. // +// Shewchuk generalized Ruppert's algorithm into 3D in his PhD thesis // +// [Shewchuk 1997]. A short version of his algorithm appears in "Tetrahedral // +// Mesh Generation by Delaunay Refinement," In Proceedings of the 14th ACM // +// Symposium on Computational Geometry, 86-95, 1998. It guarantees that all // +// tetrahedra of the output mesh have a "radius-edge ratio" (equivalent to // +// the minimal face angle) bounded. However, it does not remove slivers, a // +// type of very flat tetrahedra which can have no small face angles but have // +// very small (and large) dihedral angles. Moreover, it may not terminate if // +// the input PLC contains "sharp features", e.g., two edges (or two facets) // +// meet at an acute angle (or dihedral angle). // +// // +// TetGen uses the basic Delaunay refinement scheme to insert Steiner points.// +// While it always maintains a constrained Delaunay mesh. The algorithm is // +// described in Si, H., "Adaptive Constrained Delaunay Mesh Generation," // +// International Journal for Numerical Methods in Engineering, 75:856-880. // +// This algorithm always terminates and sharp features are easily preserved. // +// The mesh has good quality (same as Shewchuk's Delaunay refinement algori- // +// thm) in the bulk of the mesh domain. Moreover, it supports the generation // +// of adaptive mesh according to a (isotropic) mesh sizing function. // +// // +/////////////////////////////////////////////////////////////////////////////// + + void makefacetverticesmap(); + int segsegadjacent(face *, face *); + int segfacetadjacent(face *checkseg, face *checksh); + int facetfacetadjacent(face *, face *); + + int checkseg4encroach(point pa, point pb, point checkpt); + int checkseg4split(face *chkseg, point&, int&); + int splitsegment(face *splitseg, point encpt, REAL, point, point, int, int); + void repairencsegs(int chkencflag); + + void enqueuesubface(memorypool*, face*); + int checkfac4encroach(point, point, point, point checkpt, REAL*, REAL*); + int checkfac4split(face *chkfac, point& encpt, int& qflag, REAL *ccent); + int splitsubface(face *splitfac, point, point, int qflag, REAL *ccent, int); + void repairencfacs(int chkencflag); + + void enqueuetetrahedron(triface*); + int checktet4split(triface *chktet, int& qflag, REAL *ccent); + int splittetrahedron(triface* splittet,int qflag,REAL *ccent, int); + void repairbadtets(int chkencflag); + + void delaunayrefinement(); + +/////////////////////////////////////////////////////////////////////////////// +// // +// Mesh optimization // +// // +/////////////////////////////////////////////////////////////////////////////// + + long lawsonflip3d(flipconstraints *fc); + void recoverdelaunay(); + + int gettetrahedron(point, point, point, point, triface *); + long improvequalitybyflips(); + + int smoothpoint(point smtpt, arraypool*, int ccw, optparameters *opm); + long improvequalitybysmoothing(optparameters *opm); + + int splitsliver(triface *, REAL, int); + long removeslivers(int); + + void optimizemesh(); + +/////////////////////////////////////////////////////////////////////////////// +// // +// Mesh check and statistics // +// // +/////////////////////////////////////////////////////////////////////////////// + + // Mesh validations. + int checkmesh(int topoflag); + int checkshells(); + int checksegments(); + int checkdelaunay(); + int checkregular(int); + int checkconforming(int); + + // Mesh statistics. + void printfcomma(unsigned long n); + void qualitystatistics(); + void memorystatistics(); + void statistics(); + +/////////////////////////////////////////////////////////////////////////////// +// // +// Mesh output // +// // +/////////////////////////////////////////////////////////////////////////////// + + void jettisonnodes(); + void highorder(); + void numberedges(); + void outnodes(tetgenio*); + void outmetrics(tetgenio*); + void outelements(tetgenio*); + void outfaces(tetgenio*); + void outhullfaces(tetgenio*); + void outsubfaces(tetgenio*); + void outedges(tetgenio*); + void outsubsegments(tetgenio*); + void outneighbors(tetgenio*); + void outvoronoi(tetgenio*); + void outsmesh(char*); + void outmesh2medit(char*); + void outmesh2vtk(char*); + + + +/////////////////////////////////////////////////////////////////////////////// +// // +// Constructor & destructor // +// // +/////////////////////////////////////////////////////////////////////////////// + + tetgenmesh() + { + in = addin = NULL; + b = NULL; + bgm = NULL; + + tetrahedrons = subfaces = subsegs = points = NULL; + badtetrahedrons = badsubfacs = badsubsegs = NULL; + tet2segpool = tet2subpool = NULL; + flippool = NULL; + + dummypoint = NULL; + flipstack = NULL; + unflipqueue = NULL; + + cavetetlist = cavebdrylist = caveoldtetlist = NULL; + cavetetshlist = cavetetseglist = cavetetvertlist = NULL; + caveencshlist = caveencseglist = NULL; + caveshlist = caveshbdlist = cavesegshlist = NULL; + + subsegstack = subfacstack = subvertstack = NULL; + encseglist = encshlist = NULL; + idx2facetlist = NULL; + facetverticeslist = NULL; + segmentendpointslist = NULL; + + highordertable = NULL; + + numpointattrib = numelemattrib = 0; + sizeoftensor = 0; + pointmtrindex = 0; + pointparamindex = 0; + pointmarkindex = 0; + point2simindex = 0; + elemattribindex = 0; + volumeboundindex = 0; + shmarkindex = 0; + areaboundindex = 0; + checksubsegflag = 0; + checksubfaceflag = 0; + checkconstraints = 0; + nonconvex = 0; + autofliplinklevel = 1; + useinsertradius = 0; + samples = 0l; + randomseed = 1l; + minfaceang = minfacetdihed = PI; + tetprism_vol_sum = 0.0; + longest = 0.0; + xmax = xmin = ymax = ymin = zmax = zmin = 0.0; + + insegments = 0l; + hullsize = 0l; + meshedges = meshhulledges = 0l; + steinerleft = -1; + dupverts = 0l; + unuverts = 0l; + nonregularcount = 0l; + st_segref_count = st_facref_count = st_volref_count = 0l; + fillregioncount = cavitycount = cavityexpcount = 0l; + flip14count = flip26count = flipn2ncount = 0l; + flip23count = flip32count = flip44count = flip41count = 0l; + flip22count = flip31count = 0l; + totalworkmemory = 0l; + + + } // tetgenmesh() + + void freememory() + { + if (bgm != NULL) { + delete bgm; + } + + if (points != (memorypool *) NULL) { + delete points; + delete [] dummypoint; + } + + if (tetrahedrons != (memorypool *) NULL) { + delete tetrahedrons; + } + + if (subfaces != (memorypool *) NULL) { + delete subfaces; + delete subsegs; + } + + if (tet2segpool != NULL) { + delete tet2segpool; + delete tet2subpool; + } + + if (flippool != NULL) { + delete flippool; + delete unflipqueue; + } + + if (cavetetlist != NULL) { + delete cavetetlist; + delete cavebdrylist; + delete caveoldtetlist; + delete cavetetvertlist; + } + + if (caveshlist != NULL) { + delete caveshlist; + delete caveshbdlist; + delete cavesegshlist; + delete cavetetshlist; + delete cavetetseglist; + delete caveencshlist; + delete caveencseglist; + } + + if (subsegstack != NULL) { + delete subsegstack; + delete subfacstack; + delete subvertstack; + } + + if (idx2facetlist != NULL) { + delete [] idx2facetlist; + delete [] facetverticeslist; + } + + if (segmentendpointslist != NULL) { + delete [] segmentendpointslist; + } + + if (highordertable != NULL) { + delete [] highordertable; + } + } + + ~tetgenmesh() + { + freememory(); + } // ~tetgenmesh() + +}; // End of class tetgenmesh. + +/////////////////////////////////////////////////////////////////////////////// +// // +// tetrahedralize() Interface for using TetGen's library to generate // +// Delaunay tetrahedralizations, constrained Delaunay // +// tetrahedralizations, quality tetrahedral meshes. // +// // +// 'in' is an object of 'tetgenio' which contains a PLC you want to tetrahed-// +// ralize or a previously generated tetrahedral mesh you want to refine. It // +// must not be a NULL. 'out' is another object of 'tetgenio' for storing the // +// generated tetrahedral mesh. It can be a NULL. If so, the output will be // +// saved to file(s). If 'bgmin' != NULL, it contains a background mesh which // +// defines a mesh size function. // +// // +/////////////////////////////////////////////////////////////////////////////// + +void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out, + tetgenio *addin = NULL, tetgenio *bgmin = NULL); + +#ifdef TETLIBRARY +void tetrahedralize(char *switches, tetgenio *in, tetgenio *out, + tetgenio *addin = NULL, tetgenio *bgmin = NULL); +#endif // #ifdef TETLIBRARY + +/////////////////////////////////////////////////////////////////////////////// +// // +// terminatetetgen() Terminate TetGen with a given exit code. // +// // +/////////////////////////////////////////////////////////////////////////////// + +inline void terminatetetgen(tetgenmesh *m, int x) +{ + // Release the allocated memory. + if (m) { + m->freememory(); + } +#ifdef TETLIBRARY + throw x; +#else + switch (x) { + case 1: // Out of memory. + printf("Error: Out of memory.\n"); + break; + case 2: // Encounter an internal error. + printf("Please report this bug to Hang.Si@wias-berlin.de. Include\n"); + printf(" the message above, your input data set, and the exact\n"); + printf(" command line you used to run this program, thank you.\n"); + break; + case 3: + printf("A self-intersection was detected. Program stopped.\n"); + printf("Hint: use -d option to detect all self-intersections.\n"); + break; + case 4: + printf("A very small input feature size was detected. Program stopped.\n"); + printf("Hint: use -T option to set a smaller tolerance.\n"); + break; + case 5: + printf("Two very close input facets were detected. Program stopped.\n"); + printf("Hint: use -Y option to avoid adding Steiner points in boundary.\n"); + break; + case 10: + printf("An input error was detected. Program stopped.\n"); + break; + } // switch (x) + exit(x); +#endif // #ifdef TETLIBRARY +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// Primitives for tetrahedra // +// // +/////////////////////////////////////////////////////////////////////////////// + +// encode() compress a handle into a single pointer. It relies on the +// assumption that all addresses of tetrahedra are aligned to sixteen- +// byte boundaries, so that the last four significant bits are zero. + +inline tetgenmesh::tetrahedron tetgenmesh::encode(triface& t) { + return (tetrahedron) ((uintptr_t) (t).tet | (uintptr_t) (t).ver); +} + +inline tetgenmesh::tetrahedron tetgenmesh::encode2(tetrahedron* ptr, int ver) { + return (tetrahedron) ((uintptr_t) (ptr) | (uintptr_t) (ver)); +} + +// decode() converts a pointer to a handle. The version is extracted from +// the four least significant bits of the pointer. + +inline void tetgenmesh::decode(tetrahedron ptr, triface& t) { + (t).ver = (int) ((uintptr_t) (ptr) & (uintptr_t) 15); + (t).tet = (tetrahedron *) ((uintptr_t) (ptr) ^ (uintptr_t) (t).ver); +} + +// bond() connects two tetrahedra together. (t1,v1) and (t2,v2) must +// refer to the same face and the same edge. + +inline void tetgenmesh::bond(triface& t1, triface& t2) { + t1.tet[t1.ver & 3] = encode2(t2.tet, bondtbl[t1.ver][t2.ver]); + t2.tet[t2.ver & 3] = encode2(t1.tet, bondtbl[t2.ver][t1.ver]); +} + + +// dissolve() a bond (from one side). + +inline void tetgenmesh::dissolve(triface& t) { + t.tet[t.ver & 3] = NULL; +} + +// enext() finds the next edge (counterclockwise) in the same face. + +inline void tetgenmesh::enext(triface& t1, triface& t2) { + t2.tet = t1.tet; + t2.ver = enexttbl[t1.ver]; +} + +inline void tetgenmesh::enextself(triface& t) { + t.ver = enexttbl[t.ver]; +} + +// eprev() finds the next edge (clockwise) in the same face. + +inline void tetgenmesh::eprev(triface& t1, triface& t2) { + t2.tet = t1.tet; + t2.ver = eprevtbl[t1.ver]; +} + +inline void tetgenmesh::eprevself(triface& t) { + t.ver = eprevtbl[t.ver]; +} + +// esym() finds the reversed edge. It is in the other face of the +// same tetrahedron. + +inline void tetgenmesh::esym(triface& t1, triface& t2) { + (t2).tet = (t1).tet; + (t2).ver = esymtbl[(t1).ver]; +} + +inline void tetgenmesh::esymself(triface& t) { + (t).ver = esymtbl[(t).ver]; +} + +// enextesym() finds the reversed edge of the next edge. It is in the other +// face of the same tetrahedron. It is the combination esym() * enext(). + +inline void tetgenmesh::enextesym(triface& t1, triface& t2) { + t2.tet = t1.tet; + t2.ver = enextesymtbl[t1.ver]; +} + +inline void tetgenmesh::enextesymself(triface& t) { + t.ver = enextesymtbl[t.ver]; +} + +// eprevesym() finds the reversed edge of the previous edge. + +inline void tetgenmesh::eprevesym(triface& t1, triface& t2) { + t2.tet = t1.tet; + t2.ver = eprevesymtbl[t1.ver]; +} + +inline void tetgenmesh::eprevesymself(triface& t) { + t.ver = eprevesymtbl[t.ver]; +} + +// eorgoppo() Finds the opposite face of the origin of the current edge. +// Return the opposite edge of the current edge. + +inline void tetgenmesh::eorgoppo(triface& t1, triface& t2) { + t2.tet = t1.tet; + t2.ver = eorgoppotbl[t1.ver]; +} + +inline void tetgenmesh::eorgoppoself(triface& t) { + t.ver = eorgoppotbl[t.ver]; +} + +// edestoppo() Finds the opposite face of the destination of the current +// edge. Return the opposite edge of the current edge. + +inline void tetgenmesh::edestoppo(triface& t1, triface& t2) { + t2.tet = t1.tet; + t2.ver = edestoppotbl[t1.ver]; +} + +inline void tetgenmesh::edestoppoself(triface& t) { + t.ver = edestoppotbl[t.ver]; +} + +// fsym() finds the adjacent tetrahedron at the same face and the same edge. + +inline void tetgenmesh::fsym(triface& t1, triface& t2) { + decode((t1).tet[(t1).ver & 3], t2); + t2.ver = fsymtbl[t1.ver][t2.ver]; +} + + +#define fsymself(t) \ + t1ver = (t).ver; \ + decode((t).tet[(t).ver & 3], (t));\ + (t).ver = fsymtbl[t1ver][(t).ver] + +// fnext() finds the next face while rotating about an edge according to +// a right-hand rule. The face is in the adjacent tetrahedron. It is +// the combination: fsym() * esym(). + +inline void tetgenmesh::fnext(triface& t1, triface& t2) { + decode(t1.tet[facepivot1[t1.ver]], t2); + t2.ver = facepivot2[t1.ver][t2.ver]; +} + + +#define fnextself(t) \ + t1ver = (t).ver; \ + decode((t).tet[facepivot1[(t).ver]], (t)); \ + (t).ver = facepivot2[t1ver][(t).ver] + + +// The following primtives get or set the origin, destination, face apex, +// or face opposite of an ordered tetrahedron. + +inline tetgenmesh::point tetgenmesh::org(triface& t) { + return (point) (t).tet[orgpivot[(t).ver]]; +} + +inline tetgenmesh::point tetgenmesh:: dest(triface& t) { + return (point) (t).tet[destpivot[(t).ver]]; +} + +inline tetgenmesh::point tetgenmesh:: apex(triface& t) { + return (point) (t).tet[apexpivot[(t).ver]]; +} + +inline tetgenmesh::point tetgenmesh:: oppo(triface& t) { + return (point) (t).tet[oppopivot[(t).ver]]; +} + +inline void tetgenmesh:: setorg(triface& t, point p) { + (t).tet[orgpivot[(t).ver]] = (tetrahedron) (p); +} + +inline void tetgenmesh:: setdest(triface& t, point p) { + (t).tet[destpivot[(t).ver]] = (tetrahedron) (p); +} + +inline void tetgenmesh:: setapex(triface& t, point p) { + (t).tet[apexpivot[(t).ver]] = (tetrahedron) (p); +} + +inline void tetgenmesh:: setoppo(triface& t, point p) { + (t).tet[oppopivot[(t).ver]] = (tetrahedron) (p); +} + +#define setvertices(t, torg, tdest, tapex, toppo) \ + (t).tet[orgpivot[(t).ver]] = (tetrahedron) (torg);\ + (t).tet[destpivot[(t).ver]] = (tetrahedron) (tdest); \ + (t).tet[apexpivot[(t).ver]] = (tetrahedron) (tapex); \ + (t).tet[oppopivot[(t).ver]] = (tetrahedron) (toppo) + +// Check or set a tetrahedron's attributes. + +inline REAL tetgenmesh::elemattribute(tetrahedron* ptr, int attnum) { + return ((REAL *) (ptr))[elemattribindex + attnum]; +} + +inline void tetgenmesh::setelemattribute(tetrahedron* ptr, int attnum, + REAL value) { + ((REAL *) (ptr))[elemattribindex + attnum] = value; +} + +// Check or set a tetrahedron's maximum volume bound. + +inline REAL tetgenmesh::volumebound(tetrahedron* ptr) { + return ((REAL *) (ptr))[volumeboundindex]; +} + +inline void tetgenmesh::setvolumebound(tetrahedron* ptr, REAL value) { + ((REAL *) (ptr))[volumeboundindex] = value; +} + +// Get or set a tetrahedron's index (only used for output). +// These two routines use the reserved slot ptr[10]. + +inline int tetgenmesh::elemindex(tetrahedron* ptr) { + int *iptr = (int *) &(ptr[10]); + return iptr[0]; +} + +inline void tetgenmesh::setelemindex(tetrahedron* ptr, int value) { + int *iptr = (int *) &(ptr[10]); + iptr[0] = value; +} + +// Get or set a tetrahedron's marker. +// Set 'value = 0' cleans all the face/edge flags. + +inline int tetgenmesh::elemmarker(tetrahedron* ptr) { + return ((int *) (ptr))[elemmarkerindex]; +} + +inline void tetgenmesh::setelemmarker(tetrahedron* ptr, int value) { + ((int *) (ptr))[elemmarkerindex] = value; +} + +// infect(), infected(), uninfect() -- primitives to flag or unflag a +// tetrahedron. The last bit of the element marker is flagged (1) +// or unflagged (0). + +inline void tetgenmesh::infect(triface& t) { + ((int *) (t.tet))[elemmarkerindex] |= 1; +} + +inline void tetgenmesh::uninfect(triface& t) { + ((int *) (t.tet))[elemmarkerindex] &= ~1; +} + +inline bool tetgenmesh::infected(triface& t) { + return (((int *) (t.tet))[elemmarkerindex] & 1) != 0; +} + +// marktest(), marktested(), unmarktest() -- primitives to flag or unflag a +// tetrahedron. Use the second lowerest bit of the element marker. + +inline void tetgenmesh::marktest(triface& t) { + ((int *) (t.tet))[elemmarkerindex] |= 2; +} + +inline void tetgenmesh::unmarktest(triface& t) { + ((int *) (t.tet))[elemmarkerindex] &= ~2; +} + +inline bool tetgenmesh::marktested(triface& t) { + return (((int *) (t.tet))[elemmarkerindex] & 2) != 0; +} + +// markface(), unmarkface(), facemarked() -- primitives to flag or unflag a +// face of a tetrahedron. From the last 3rd to 6th bits are used for +// face markers, e.g., the last third bit corresponds to loc = 0. + +inline void tetgenmesh::markface(triface& t) { + ((int *) (t.tet))[elemmarkerindex] |= (4 << (t.ver & 3)); +} + +inline void tetgenmesh::unmarkface(triface& t) { + ((int *) (t.tet))[elemmarkerindex] &= ~(4 << (t.ver & 3)); +} + +inline bool tetgenmesh::facemarked(triface& t) { + return (((int *) (t.tet))[elemmarkerindex] & (4 << (t.ver & 3))) != 0; +} + +// markedge(), unmarkedge(), edgemarked() -- primitives to flag or unflag an +// edge of a tetrahedron. From the last 7th to 12th bits are used for +// edge markers, e.g., the last 7th bit corresponds to the 0th edge, etc. +// Remark: The last 7th bit is marked by 2^6 = 64. + +inline void tetgenmesh::markedge(triface& t) { + ((int *) (t.tet))[elemmarkerindex] |= (int) (64 << ver2edge[(t).ver]); +} + +inline void tetgenmesh::unmarkedge(triface& t) { + ((int *) (t.tet))[elemmarkerindex] &= ~(int) (64 << ver2edge[(t).ver]); +} + +inline bool tetgenmesh::edgemarked(triface& t) { + return (((int *) (t.tet))[elemmarkerindex] & + (int) (64 << ver2edge[(t).ver])) != 0; +} + +// marktest2(), unmarktest2(), marktest2ed() -- primitives to flag and unflag +// a tetrahedron. The 13th bit (2^12 = 4096) is used for this flag. + +inline void tetgenmesh::marktest2(triface& t) { + ((int *) (t.tet))[elemmarkerindex] |= (int) (4096); +} + +inline void tetgenmesh::unmarktest2(triface& t) { + ((int *) (t.tet))[elemmarkerindex] &= ~(int) (4096); +} + +inline bool tetgenmesh::marktest2ed(triface& t) { + return (((int *) (t.tet))[elemmarkerindex] & (int) (4096)) != 0; +} + +// elemcounter(), setelemcounter() -- primitives to read or ser a (small) +// integer counter in this tet. It is saved from the 16th bit. On 32 bit +// system, the range of the counter is [0, 2^15 = 32768]. + +inline int tetgenmesh::elemcounter(triface& t) { + return (((int *) (t.tet))[elemmarkerindex]) >> 16; +} + +inline void tetgenmesh::setelemcounter(triface& t, int value) { + int c = ((int *) (t.tet))[elemmarkerindex]; + // Clear the old counter while keep the other flags. + c &= 65535; // sum_{i=0^15} 2^i + c |= (value << 16); + ((int *) (t.tet))[elemmarkerindex] = c; +} + +inline void tetgenmesh::increaseelemcounter(triface& t) { + int c = elemcounter(t); + setelemcounter(t, c + 1); +} + +inline void tetgenmesh::decreaseelemcounter(triface& t) { + int c = elemcounter(t); + setelemcounter(t, c - 1); +} + +// ishulltet() tests if t is a hull tetrahedron. + +inline bool tetgenmesh::ishulltet(triface& t) { + return (point) (t).tet[7] == dummypoint; +} + +// isdeadtet() tests if t is a tetrahedron is dead. + +inline bool tetgenmesh::isdeadtet(triface& t) { + return ((t.tet == NULL) || (t.tet[4] == NULL)); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// Primitives for subfaces and subsegments // +// // +/////////////////////////////////////////////////////////////////////////////// + +// Each subface contains three pointers to its neighboring subfaces, with +// edge versions. To save memory, both information are kept in a single +// pointer. To make this possible, all subfaces are aligned to eight-byte +// boundaries, so that the last three bits of each pointer are zeros. An +// edge version (in the range 0 to 5) is compressed into the last three +// bits of each pointer by 'sencode()'. 'sdecode()' decodes a pointer, +// extracting an edge version and a pointer to the beginning of a subface. + +inline void tetgenmesh::sdecode(shellface sptr, face& s) { + s.shver = (int) ((uintptr_t) (sptr) & (uintptr_t) 7); + s.sh = (shellface *) ((uintptr_t) (sptr) ^ (uintptr_t) (s.shver)); +} + +inline tetgenmesh::shellface tetgenmesh::sencode(face& s) { + return (shellface) ((uintptr_t) s.sh | (uintptr_t) s.shver); +} + +inline tetgenmesh::shellface tetgenmesh::sencode2(shellface *sh, int shver) { + return (shellface) ((uintptr_t) sh | (uintptr_t) shver); +} + +// sbond() bonds two subfaces (s1) and (s2) together. s1 and s2 must refer +// to the same edge. No requirement is needed on their orientations. + +inline void tetgenmesh::sbond(face& s1, face& s2) +{ + s1.sh[s1.shver >> 1] = sencode(s2); + s2.sh[s2.shver >> 1] = sencode(s1); +} + +// sbond1() bonds s1 <== s2, i.e., after bonding, s1 is pointing to s2, +// but s2 is not pointing to s1. s1 and s2 must refer to the same edge. +// No requirement is needed on their orientations. + +inline void tetgenmesh::sbond1(face& s1, face& s2) +{ + s1.sh[s1.shver >> 1] = sencode(s2); +} + +// Dissolve a subface bond (from one side). Note that the other subface +// will still think it's connected to this subface. + +inline void tetgenmesh::sdissolve(face& s) +{ + s.sh[s.shver >> 1] = NULL; +} + +// spivot() finds the adjacent subface (s2) for a given subface (s1). +// s1 and s2 share at the same edge. + +inline void tetgenmesh::spivot(face& s1, face& s2) +{ + shellface sptr = s1.sh[s1.shver >> 1]; + sdecode(sptr, s2); +} + +inline void tetgenmesh::spivotself(face& s) +{ + shellface sptr = s.sh[s.shver >> 1]; + sdecode(sptr, s); +} + +// These primitives determine or set the origin, destination, or apex +// of a subface with respect to the edge version. + +inline tetgenmesh::point tetgenmesh::sorg(face& s) +{ + return (point) s.sh[sorgpivot[s.shver]]; +} + +inline tetgenmesh::point tetgenmesh::sdest(face& s) +{ + return (point) s.sh[sdestpivot[s.shver]]; +} + +inline tetgenmesh::point tetgenmesh::sapex(face& s) +{ + return (point) s.sh[sapexpivot[s.shver]]; +} + +inline void tetgenmesh::setsorg(face& s, point pointptr) +{ + s.sh[sorgpivot[s.shver]] = (shellface) pointptr; +} + +inline void tetgenmesh::setsdest(face& s, point pointptr) +{ + s.sh[sdestpivot[s.shver]] = (shellface) pointptr; +} + +inline void tetgenmesh::setsapex(face& s, point pointptr) +{ + s.sh[sapexpivot[s.shver]] = (shellface) pointptr; +} + +#define setshvertices(s, pa, pb, pc)\ + setsorg(s, pa);\ + setsdest(s, pb);\ + setsapex(s, pc) + +// sesym() reserves the direction of the lead edge. + +inline void tetgenmesh::sesym(face& s1, face& s2) +{ + s2.sh = s1.sh; + s2.shver = (s1.shver ^ 1); // Inverse the last bit. +} + +inline void tetgenmesh::sesymself(face& s) +{ + s.shver ^= 1; +} + +// senext() finds the next edge (counterclockwise) in the same orientation +// of this face. + +inline void tetgenmesh::senext(face& s1, face& s2) +{ + s2.sh = s1.sh; + s2.shver = snextpivot[s1.shver]; +} + +inline void tetgenmesh::senextself(face& s) +{ + s.shver = snextpivot[s.shver]; +} + +inline void tetgenmesh::senext2(face& s1, face& s2) +{ + s2.sh = s1.sh; + s2.shver = snextpivot[snextpivot[s1.shver]]; +} + +inline void tetgenmesh::senext2self(face& s) +{ + s.shver = snextpivot[snextpivot[s.shver]]; +} + + +// Check or set a subface's maximum area bound. + +inline REAL tetgenmesh::areabound(face& s) +{ + return ((REAL *) (s.sh))[areaboundindex]; +} + +inline void tetgenmesh::setareabound(face& s, REAL value) +{ + ((REAL *) (s.sh))[areaboundindex] = value; +} + +// These two primitives read or set a shell marker. Shell markers are used +// to hold user boundary information. + +inline int tetgenmesh::shellmark(face& s) +{ + return ((int *) (s.sh))[shmarkindex]; +} + +inline void tetgenmesh::setshellmark(face& s, int value) +{ + ((int *) (s.sh))[shmarkindex] = value; +} + + + +// sinfect(), sinfected(), suninfect() -- primitives to flag or unflag a +// subface. The last bit of ((int *) ((s).sh))[shmarkindex+1] is flagged. + +inline void tetgenmesh::sinfect(face& s) +{ + ((int *) ((s).sh))[shmarkindex+1] = + (((int *) ((s).sh))[shmarkindex+1] | (int) 1); +} + +inline void tetgenmesh::suninfect(face& s) +{ + ((int *) ((s).sh))[shmarkindex+1] = + (((int *) ((s).sh))[shmarkindex+1] & ~(int) 1); +} + +// Test a subface for viral infection. + +inline bool tetgenmesh::sinfected(face& s) +{ + return (((int *) ((s).sh))[shmarkindex+1] & (int) 1) != 0; +} + +// smarktest(), smarktested(), sunmarktest() -- primitives to flag or unflag +// a subface. The last 2nd bit of the integer is flagged. + +inline void tetgenmesh::smarktest(face& s) +{ + ((int *) ((s).sh))[shmarkindex+1] = + (((int *)((s).sh))[shmarkindex+1] | (int) 2); +} + +inline void tetgenmesh::sunmarktest(face& s) +{ + ((int *) ((s).sh))[shmarkindex+1] = + (((int *)((s).sh))[shmarkindex+1] & ~(int)2); +} + +inline bool tetgenmesh::smarktested(face& s) +{ + return ((((int *) ((s).sh))[shmarkindex+1] & (int) 2) != 0); +} + +// smarktest2(), smarktest2ed(), sunmarktest2() -- primitives to flag or +// unflag a subface. The last 3rd bit of the integer is flagged. + +inline void tetgenmesh::smarktest2(face& s) +{ + ((int *) ((s).sh))[shmarkindex+1] = + (((int *)((s).sh))[shmarkindex+1] | (int) 4); +} + +inline void tetgenmesh::sunmarktest2(face& s) +{ + ((int *) ((s).sh))[shmarkindex+1] = + (((int *)((s).sh))[shmarkindex+1] & ~(int)4); +} + +inline bool tetgenmesh::smarktest2ed(face& s) +{ + return ((((int *) ((s).sh))[shmarkindex+1] & (int) 4) != 0); +} + +// The last 4th bit of ((int *) ((s).sh))[shmarkindex+1] is flagged. + +inline void tetgenmesh::smarktest3(face& s) +{ + ((int *) ((s).sh))[shmarkindex+1] = + (((int *)((s).sh))[shmarkindex+1] | (int) 8); +} + +inline void tetgenmesh::sunmarktest3(face& s) +{ + ((int *) ((s).sh))[shmarkindex+1] = + (((int *)((s).sh))[shmarkindex+1] & ~(int)8); +} + +inline bool tetgenmesh::smarktest3ed(face& s) +{ + return ((((int *) ((s).sh))[shmarkindex+1] & (int) 8) != 0); +} + + +// Each facet has a unique index (automatically indexed). Starting from '0'. +// We save this index in the same field of the shell type. + +inline void tetgenmesh::setfacetindex(face& s, int value) +{ + ((int *) (s.sh))[shmarkindex + 2] = value; +} + +inline int tetgenmesh::getfacetindex(face& s) +{ + return ((int *) (s.sh))[shmarkindex + 2]; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// Primitives for interacting between tetrahedra and subfaces // +// // +/////////////////////////////////////////////////////////////////////////////// + +// tsbond() bond a tetrahedron (t) and a subface (s) together. +// Note that t and s must be the same face and the same edge. Moreover, +// t and s have the same orientation. +// Since the edge number in t and in s can be any number in {0,1,2}. We bond +// the edge in s which corresponds to t's 0th edge, and vice versa. + +inline void tetgenmesh::tsbond(triface& t, face& s) +{ + if ((t).tet[9] == NULL) { + // Allocate space for this tet. + (t).tet[9] = (tetrahedron) tet2subpool->alloc(); + // Initialize. + for (int i = 0; i < 4; i++) { + ((shellface *) (t).tet[9])[i] = NULL; + } + } + // Bond t <== s. + ((shellface *) (t).tet[9])[(t).ver & 3] = + sencode2((s).sh, tsbondtbl[t.ver][s.shver]); + // Bond s <== t. + s.sh[9 + ((s).shver & 1)] = + (shellface) encode2((t).tet, stbondtbl[t.ver][s.shver]); +} + +// tspivot() finds a subface (s) abutting on the given tetrahdera (t). +// Return s.sh = NULL if there is no subface at t. Otherwise, return +// the subface s, and s and t must be at the same edge wth the same +// orientation. + +inline void tetgenmesh::tspivot(triface& t, face& s) +{ + if ((t).tet[9] == NULL) { + (s).sh = NULL; + return; + } + // Get the attached subface s. + sdecode(((shellface *) (t).tet[9])[(t).ver & 3], (s)); + (s).shver = tspivottbl[t.ver][s.shver]; +} + +// Quickly check if the handle (t, v) is a subface. +#define issubface(t) \ + ((t).tet[9] && ((t).tet[9])[(t).ver & 3]) + +// stpivot() finds a tetrahedron (t) abutting a given subface (s). +// Return the t (if it exists) with the same edge and the same +// orientation of s. + +inline void tetgenmesh::stpivot(face& s, triface& t) +{ + decode((tetrahedron) s.sh[9 + (s.shver & 1)], t); + if ((t).tet == NULL) { + return; + } + (t).ver = stpivottbl[t.ver][s.shver]; +} + +// Quickly check if this subface is attached to a tetrahedron. + +#define isshtet(s) \ + ((s).sh[9 + ((s).shver & 1)]) + +// tsdissolve() dissolve a bond (from the tetrahedron side). + +inline void tetgenmesh::tsdissolve(triface& t) +{ + if ((t).tet[9] != NULL) { + ((shellface *) (t).tet[9])[(t).ver & 3] = NULL; + } +} + +// stdissolve() dissolve a bond (from the subface side). + +inline void tetgenmesh::stdissolve(face& s) +{ + (s).sh[9] = NULL; + (s).sh[10] = NULL; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// Primitives for interacting between subfaces and segments // +// // +/////////////////////////////////////////////////////////////////////////////// + +// ssbond() bond a subface to a subsegment. + +inline void tetgenmesh::ssbond(face& s, face& edge) +{ + s.sh[6 + (s.shver >> 1)] = sencode(edge); + edge.sh[0] = sencode(s); +} + +inline void tetgenmesh::ssbond1(face& s, face& edge) +{ + s.sh[6 + (s.shver >> 1)] = sencode(edge); + //edge.sh[0] = sencode(s); +} + +// ssdisolve() dissolve a bond (from the subface side) + +inline void tetgenmesh::ssdissolve(face& s) +{ + s.sh[6 + (s.shver >> 1)] = NULL; +} + +// sspivot() finds a subsegment abutting a subface. + +inline void tetgenmesh::sspivot(face& s, face& edge) +{ + sdecode((shellface) s.sh[6 + (s.shver >> 1)], edge); +} + +// Quickly check if the edge is a subsegment. + +#define isshsubseg(s) \ + ((s).sh[6 + ((s).shver >> 1)]) + +/////////////////////////////////////////////////////////////////////////////// +// // +// Primitives for interacting between tetrahedra and segments // +// // +/////////////////////////////////////////////////////////////////////////////// + +inline void tetgenmesh::tssbond1(triface& t, face& s) +{ + if ((t).tet[8] == NULL) { + // Allocate space for this tet. + (t).tet[8] = (tetrahedron) tet2segpool->alloc(); + // Initialization. + for (int i = 0; i < 6; i++) { + ((shellface *) (t).tet[8])[i] = NULL; + } + } + ((shellface *) (t).tet[8])[ver2edge[(t).ver]] = sencode((s)); +} + +inline void tetgenmesh::sstbond1(face& s, triface& t) +{ + ((tetrahedron *) (s).sh)[9] = encode(t); +} + +inline void tetgenmesh::tssdissolve1(triface& t) +{ + if ((t).tet[8] != NULL) { + ((shellface *) (t).tet[8])[ver2edge[(t).ver]] = NULL; + } +} + +inline void tetgenmesh::sstdissolve1(face& s) +{ + ((tetrahedron *) (s).sh)[9] = NULL; +} + +inline void tetgenmesh::tsspivot1(triface& t, face& s) +{ + if ((t).tet[8] != NULL) { + sdecode(((shellface *) (t).tet[8])[ver2edge[(t).ver]], s); + } else { + (s).sh = NULL; + } +} + +// Quickly check whether 't' is a segment or not. + +#define issubseg(t) \ + ((t).tet[8] && ((t).tet[8])[ver2edge[(t).ver]]) + +inline void tetgenmesh::sstpivot1(face& s, triface& t) +{ + decode((tetrahedron) s.sh[9], t); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// Primitives for points // +// // +/////////////////////////////////////////////////////////////////////////////// + +inline int tetgenmesh::pointmark(point pt) { + return ((int *) (pt))[pointmarkindex]; +} + +inline void tetgenmesh::setpointmark(point pt, int value) { + ((int *) (pt))[pointmarkindex] = value; +} + + +// These two primitives set and read the type of the point. + +inline enum tetgenmesh::verttype tetgenmesh::pointtype(point pt) { + return (enum verttype) (((int *) (pt))[pointmarkindex + 1] >> (int) 8); +} + +inline void tetgenmesh::setpointtype(point pt, enum verttype value) { + ((int *) (pt))[pointmarkindex + 1] = + ((int) value << 8) + (((int *) (pt))[pointmarkindex + 1] & (int) 255); +} + +// Read and set the geometry tag of the point (used by -s option). + +inline int tetgenmesh::pointgeomtag(point pt) { + return ((int *) (pt))[pointmarkindex + 2]; +} + +inline void tetgenmesh::setpointgeomtag(point pt, int value) { + ((int *) (pt))[pointmarkindex + 2] = value; +} + +// Read and set the u,v coordinates of the point (used by -s option). + +inline REAL tetgenmesh::pointgeomuv(point pt, int i) { + return pt[pointparamindex + i]; +} + +inline void tetgenmesh::setpointgeomuv(point pt, int i, REAL value) { + pt[pointparamindex + i] = value; +} + +// pinfect(), puninfect(), pinfected() -- primitives to flag or unflag +// a point. The last bit of the integer '[pointindex+1]' is flagged. + +inline void tetgenmesh::pinfect(point pt) { + ((int *) (pt))[pointmarkindex + 1] |= (int) 1; +} + +inline void tetgenmesh::puninfect(point pt) { + ((int *) (pt))[pointmarkindex + 1] &= ~(int) 1; +} + +inline bool tetgenmesh::pinfected(point pt) { + return (((int *) (pt))[pointmarkindex + 1] & (int) 1) != 0; +} + +// pmarktest(), punmarktest(), pmarktested() -- more primitives to +// flag or unflag a point. + +inline void tetgenmesh::pmarktest(point pt) { + ((int *) (pt))[pointmarkindex + 1] |= (int) 2; +} + +inline void tetgenmesh::punmarktest(point pt) { + ((int *) (pt))[pointmarkindex + 1] &= ~(int) 2; +} + +inline bool tetgenmesh::pmarktested(point pt) { + return (((int *) (pt))[pointmarkindex + 1] & (int) 2) != 0; +} + +inline void tetgenmesh::pmarktest2(point pt) { + ((int *) (pt))[pointmarkindex + 1] |= (int) 4; +} + +inline void tetgenmesh::punmarktest2(point pt) { + ((int *) (pt))[pointmarkindex + 1] &= ~(int) 4; +} + +inline bool tetgenmesh::pmarktest2ed(point pt) { + return (((int *) (pt))[pointmarkindex + 1] & (int) 4) != 0; +} + +inline void tetgenmesh::pmarktest3(point pt) { + ((int *) (pt))[pointmarkindex + 1] |= (int) 8; +} + +inline void tetgenmesh::punmarktest3(point pt) { + ((int *) (pt))[pointmarkindex + 1] &= ~(int) 8; +} + +inline bool tetgenmesh::pmarktest3ed(point pt) { + return (((int *) (pt))[pointmarkindex + 1] & (int) 8) != 0; +} + +// These following primitives set and read a pointer to a tetrahedron +// a subface/subsegment, a point, or a tet of background mesh. + +inline tetgenmesh::tetrahedron tetgenmesh::point2tet(point pt) { + return ((tetrahedron *) (pt))[point2simindex]; +} + +inline void tetgenmesh::setpoint2tet(point pt, tetrahedron value) { + ((tetrahedron *) (pt))[point2simindex] = value; +} + +inline tetgenmesh::point tetgenmesh::point2ppt(point pt) { + return (point) ((tetrahedron *) (pt))[point2simindex + 1]; +} + +inline void tetgenmesh::setpoint2ppt(point pt, point value) { + ((tetrahedron *) (pt))[point2simindex + 1] = (tetrahedron) value; +} + +inline tetgenmesh::shellface tetgenmesh::point2sh(point pt) { + return (shellface) ((tetrahedron *) (pt))[point2simindex + 2]; +} + +inline void tetgenmesh::setpoint2sh(point pt, shellface value) { + ((tetrahedron *) (pt))[point2simindex + 2] = (tetrahedron) value; +} + + +inline tetgenmesh::tetrahedron tetgenmesh::point2bgmtet(point pt) { + return ((tetrahedron *) (pt))[point2simindex + 3]; +} + +inline void tetgenmesh::setpoint2bgmtet(point pt, tetrahedron value) { + ((tetrahedron *) (pt))[point2simindex + 3] = value; +} + + +// The primitives for saving and getting the insertion radius. +inline void tetgenmesh::setpointinsradius(point pt, REAL value) +{ + pt[pointmtrindex + sizeoftensor - 1] = value; +} + +inline REAL tetgenmesh::getpointinsradius(point pt) +{ + return pt[pointmtrindex + sizeoftensor - 1]; +} + +// point2tetorg() Get the tetrahedron whose origin is the point. + +inline void tetgenmesh::point2tetorg(point pa, triface& searchtet) +{ + decode(point2tet(pa), searchtet); + if ((point) searchtet.tet[4] == pa) { + searchtet.ver = 11; + } else if ((point) searchtet.tet[5] == pa) { + searchtet.ver = 3; + } else if ((point) searchtet.tet[6] == pa) { + searchtet.ver = 7; + } else { + assert((point) searchtet.tet[7] == pa); // SELF_CHECK + searchtet.ver = 0; + } +} + +// point2shorg() Get the subface/segment whose origin is the point. + +inline void tetgenmesh::point2shorg(point pa, face& searchsh) +{ + sdecode(point2sh(pa), searchsh); + if ((point) searchsh.sh[3] == pa) { + searchsh.shver = 0; + } else if ((point) searchsh.sh[4] == pa) { + searchsh.shver = (searchsh.sh[5] != NULL ? 2 : 1); + } else { + assert((point) searchsh.sh[5] == pa); // SELF_CHECK + searchsh.shver = 4; + } +} + +// farsorg() Return the origin of the subsegment. +// farsdest() Return the destination of the subsegment. + +inline tetgenmesh::point tetgenmesh::farsorg(face& s) +{ + face travesh, neighsh; + + travesh = s; + while (1) { + senext2(travesh, neighsh); + spivotself(neighsh); + if (neighsh.sh == NULL) break; + if (sorg(neighsh) != sorg(travesh)) sesymself(neighsh); + senext2(neighsh, travesh); + } + return sorg(travesh); +} + +inline tetgenmesh::point tetgenmesh::farsdest(face& s) +{ + face travesh, neighsh; + + travesh = s; + while (1) { + senext(travesh, neighsh); + spivotself(neighsh); + if (neighsh.sh == NULL) break; + if (sdest(neighsh) != sdest(travesh)) sesymself(neighsh); + senext(neighsh, travesh); + } + return sdest(travesh); +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// Linear algebra operators. // +// // +/////////////////////////////////////////////////////////////////////////////// + +// dot() returns the dot product: v1 dot v2. +inline REAL tetgenmesh::dot(REAL* v1, REAL* v2) +{ + return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]; +} + +// cross() computes the cross product: n = v1 cross v2. +inline void tetgenmesh::cross(REAL* v1, REAL* v2, REAL* n) +{ + n[0] = v1[1] * v2[2] - v2[1] * v1[2]; + n[1] = -(v1[0] * v2[2] - v2[0] * v1[2]); + n[2] = v1[0] * v2[1] - v2[0] * v1[1]; +} + +// distance() computes the Euclidean distance between two points. +inline REAL tetgenmesh::distance(REAL* p1, REAL* p2) +{ + return sqrt((p2[0] - p1[0]) * (p2[0] - p1[0]) + + (p2[1] - p1[1]) * (p2[1] - p1[1]) + + (p2[2] - p1[2]) * (p2[2] - p1[2])); +} + +inline REAL tetgenmesh::norm2(REAL x, REAL y, REAL z) +{ + return (x) * (x) + (y) * (y) + (z) * (z); +} + + +#endif // #ifndef tetgenH + From ec8c04e2600e804a4dce7bc5c2a16f3118bd0d4a Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Thu, 17 Mar 2016 23:19:11 +0100 Subject: [PATCH 355/402] some small fixes. Signed-off-by: Etienne Schmitt --- cgogn/io/mesh_generation/CMakeLists.txt | 12 ++++++++++-- .../io/mesh_generation/examples/CMakeLists.txt | 17 +++++++++-------- .../examples/map3_from_surface.cpp | 5 +---- thirdparty/tetgen/CMakeLists.txt | 2 +- thirdparty/tetgen/tetgen.cxx | 4 ++-- thirdparty/tetgen/tetgen.h | 8 +++++--- 6 files changed, 28 insertions(+), 20 deletions(-) diff --git a/cgogn/io/mesh_generation/CMakeLists.txt b/cgogn/io/mesh_generation/CMakeLists.txt index 0adb430e..f087e8f7 100644 --- a/cgogn/io/mesh_generation/CMakeLists.txt +++ b/cgogn/io/mesh_generation/CMakeLists.txt @@ -6,6 +6,8 @@ project(cgogn_io_mesh_generation LANGUAGES CXX ) +set(LIBRARIES "") + set(HEADER_FILES tetgen_io.h ) @@ -14,7 +16,11 @@ set(SOURCE_FILES tetgen_io.cpp ) -if (CGAL_FOUND) +if (CGOGN_WITH_CGAL_EXAMPLES) + find_package(MPFR REQUIRED) + find_package(GMP REQUIRED) + find_package(Boost QUIET REQUIRED COMPONENTS thread) + set( HEADER_FILES ${HEADER_FILES} c3t3_io.h @@ -24,6 +30,8 @@ if (CGAL_FOUND) ${SOURCE_FILES} c3t3_io.cpp ) + + set(LIBRARIES "${LIBRARIES};${Boost_LIBRARIES};${GMP_LIBRARIES};${MPFR_LIBRARIES};CGAL;CGAL_ImageIO") endif() @@ -33,7 +41,7 @@ target_include_directories(${PROJECT_NAME} PUBLIC $ $ ) -target_link_libraries(${PROJECT_NAME} cgogn_core cgogn_io tet) +target_link_libraries(${PROJECT_NAME} cgogn_core cgogn_io tet ${LIBRARIES}) add_subdirectory(examples) diff --git a/cgogn/io/mesh_generation/examples/CMakeLists.txt b/cgogn/io/mesh_generation/examples/CMakeLists.txt index 08558b35..f8ca64ce 100644 --- a/cgogn/io/mesh_generation/examples/CMakeLists.txt +++ b/cgogn/io/mesh_generation/examples/CMakeLists.txt @@ -4,6 +4,10 @@ project(cgogn_io_mesh_gen_examples LANGUAGES CXX ) +set(CGOGN_TEST_PREFIX "test_") +set(CGOGN_TEST_IMAGES_PATH "${CMAKE_SOURCE_DIR}/data/images/") +add_definitions("-DCGOGN_TEST_IMAGES_PATH=${CGOGN_TEST_IMAGES_PATH}") + set(HEADER_FILES program_options.h map3_from_image.h @@ -14,19 +18,16 @@ set(SOURCE_FILES program_options.cpp ) + if (CGOGN_WITH_CGAL_EXAMPLES) - find_package(MPFR REQUIRED) - find_package(GMP REQUIRED) - find_package(Boost QUIET REQUIRED COMPONENTS thread program_options) + find_package(Boost QUIET REQUIRED COMPONENTS program_options) + - set(CGOGN_TEST_PREFIX "test_") - set(CGOGN_TEST_IMAGES_PATH "${CMAKE_SOURCE_DIR}/data/images/") - add_definitions("-DCGOGN_TEST_IMAGES_PATH=${CGOGN_TEST_IMAGES_PATH}") add_executable(map3_from_image ${HEADER_FILES} ${SOURCE_FILES}) - target_link_libraries(map3_from_image cgogn_core cgogn_io_mesh_generation ${Boost_LIBRARIES} ${GMP_LIBRARIES} ${MPFR_LIBRARIES} CGAL CGAL_ImageIO) + target_link_libraries(map3_from_image cgogn_core cgogn_io_mesh_generation ) endif() add_executable(map3_from_surface map3_from_surface.cpp) -target_link_libraries(map3_from_surface cgogn_core cgogn_io cgogn_io_mesh_generation tet CGAL gmp) +target_link_libraries(map3_from_surface cgogn_core cgogn_io cgogn_io_mesh_generation) diff --git a/cgogn/io/mesh_generation/examples/map3_from_surface.cpp b/cgogn/io/mesh_generation/examples/map3_from_surface.cpp index f473dda6..d8f20098 100644 --- a/cgogn/io/mesh_generation/examples/map3_from_surface.cpp +++ b/cgogn/io/mesh_generation/examples/map3_from_surface.cpp @@ -60,13 +60,10 @@ int main(int argc, char** argv) Map3 map3; { tetgenio tetgen_output; - char *arg = new char[tetgen_arg.length() + 1]; - strcpy(arg, tetgen_arg.c_str()); - tetrahedralize(arg, tetgen_input.get(), &tetgen_output) ; + tetrahedralize(tetgen_arg.c_str(), tetgen_input.get(), &tetgen_output) ; cgogn::io::TetgenVolumeImport tetgen_import(&tetgen_output); tetgen_import.import_file(""); tetgen_import.create_map(map3); - delete[] arg; } diff --git a/thirdparty/tetgen/CMakeLists.txt b/thirdparty/tetgen/CMakeLists.txt index a805e504..b8d7a952 100644 --- a/thirdparty/tetgen/CMakeLists.txt +++ b/thirdparty/tetgen/CMakeLists.txt @@ -12,4 +12,4 @@ add_library(tet SHARED tetgen.cxx predicates.cxx) #Set properties on a target. #We use this here to set -DTETLIBRARY for when compiling the #library -set_target_properties(tet PROPERTIES "COMPILE_DEFINITIONS" TETLIBRARY) +#set_target_properties(tet PROPERTIES "COMPILE_DEFINITIONS" TETLIBRARY) diff --git a/thirdparty/tetgen/tetgen.cxx b/thirdparty/tetgen/tetgen.cxx index 30765c7f..175653a9 100644 --- a/thirdparty/tetgen/tetgen.cxx +++ b/thirdparty/tetgen/tetgen.cxx @@ -3002,7 +3002,7 @@ void tetgenbehavior::usage() // // /////////////////////////////////////////////////////////////////////////////// -bool tetgenbehavior::parse_commandline(int argc, char **argv) +bool tetgenbehavior::parse_commandline(int argc, const char **argv) { int startindex; int increment; @@ -31189,7 +31189,7 @@ int main(int argc, char *argv[]) // // /////////////////////////////////////////////////////////////////////////////// -void tetrahedralize(char *switches, tetgenio *in, tetgenio *out, +void tetrahedralize(const char *switches, tetgenio *in, tetgenio *out, tetgenio *addin, tetgenio *bgmin) #endif // not TETLIBRARY diff --git a/thirdparty/tetgen/tetgen.h b/thirdparty/tetgen/tetgen.h index 59f8259f..16c4b664 100644 --- a/thirdparty/tetgen/tetgen.h +++ b/thirdparty/tetgen/tetgen.h @@ -16,7 +16,9 @@ #ifndef tetgenH #define tetgenH + #define TETLIBRARY + // To compile TetGen as a library instead of an executable program, define // the TETLIBRARY symbol. @@ -680,8 +682,8 @@ class tetgenbehavior { void usage(); // Command line parse routine. - bool parse_commandline(int argc, char **argv); - bool parse_commandline(char *switches) { + bool parse_commandline(int argc, const char **argv); + bool parse_commandline(const char *switches) { return parse_commandline(0, &switches); } @@ -2234,7 +2236,7 @@ void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out, tetgenio *addin = NULL, tetgenio *bgmin = NULL); #ifdef TETLIBRARY -void tetrahedralize(char *switches, tetgenio *in, tetgenio *out, +void tetrahedralize(const char *switches, tetgenio *in, tetgenio *out, tetgenio *addin = NULL, tetgenio *bgmin = NULL); #endif // #ifdef TETLIBRARY From 0062eac7f60b05ea070cab8ceea3f9eea5e2ffa5 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Fri, 18 Mar 2016 14:10:39 +0100 Subject: [PATCH 356/402] real balls in drawer --- cgogn/rendering/drawer.cpp | 145 +++++++++++++++++---------- cgogn/rendering/drawer.h | 17 ++++ cgogn/rendering/examples/drawing.cpp | 31 +++++- 3 files changed, 135 insertions(+), 58 deletions(-) diff --git a/cgogn/rendering/drawer.cpp b/cgogn/rendering/drawer.cpp index 62d137f5..110454d0 100644 --- a/cgogn/rendering/drawer.cpp +++ b/cgogn/rendering/drawer.cpp @@ -39,11 +39,13 @@ namespace rendering ShaderColorPerVertex* Drawer::shader_cpv_ = nullptr; ShaderBoldLine* Drawer::shader_bl_ = nullptr; ShaderRoundPoint* Drawer::shader_rp_ = nullptr; +ShaderPointSprite* Drawer::shader_ps_ = nullptr; int Drawer::nb_instances_ = 0; Drawer::Drawer(QOpenGLFunctions_3_3_Core* ogl33): current_size_(1.0f), current_aa_(true), + current_ball_(true), ogl33_(ogl33) { nb_instances_++; @@ -70,6 +72,13 @@ Drawer::Drawer(QOpenGLFunctions_3_3_Core* ogl33): shader_rp_->release(); shader_rp_->set_vao(vao_rp_,vbo_pos_,vbo_col_); + if (!shader_ps_) + shader_ps_ = new ShaderPointSprite(true); + vao_ps_ = shader_ps_->add_vao(); + shader_ps_->bind(); + shader_ps_->release(); + shader_ps_->set_vao(vao_ps_,vbo_pos_,vbo_col_); + } @@ -79,10 +88,11 @@ Drawer::~Drawer() delete vbo_col_; nb_instances_--; - if (nb_instances_ ==0) + if (nb_instances_ == 0) { // delete shaders when last drawer is deleted // ensure context still enable when delete shaders + delete shader_ps_; delete shader_rp_; delete shader_bl_; delete shader_cpv_; @@ -94,6 +104,8 @@ void Drawer::new_list() data_pos_.clear(); data_col_.clear(); begins_point_.clear(); + begins_round_point_.clear(); + begins_balls_.clear(); begins_line_.clear(); begins_bold_line_.clear(); begins_face_.clear(); @@ -104,7 +116,12 @@ void Drawer::begin(GLenum mode) switch (mode) { case GL_POINTS: - if (current_size_ > 2.0) + if (current_ball_) + { + begins_balls_.push_back(PrimParam(data_pos_.size(), mode, current_size_,false)); + current_begin_ = &begins_balls_; + } + else if (current_size_ > 2.0) { begins_round_point_.push_back(PrimParam(data_pos_.size(), mode, current_size_,current_aa_)); current_begin_ = &begins_round_point_; @@ -194,82 +211,102 @@ void Drawer::call_list(const QMatrix4x4& projection, const QMatrix4x4& modelview { //classic rendering - shader_cpv_->bind(); - shader_cpv_->set_matrices(projection,modelview); - shader_cpv_->bind_vao(vao_cpv_); - - for (auto& pp : begins_point_) + if (!begins_point_.empty() && !begins_line_.empty() && !begins_face_.empty()) { - ogl33_->glPointSize(pp.width); - ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); - } + shader_cpv_->bind(); + shader_cpv_->set_matrices(projection,modelview); + shader_cpv_->bind_vao(vao_cpv_); - for (auto& pp : begins_line_) - { - ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); - } + for (auto& pp : begins_point_) + { + ogl33_->glPointSize(pp.width); + ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); + } - for (auto& pp : begins_face_) - { - ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); - } + for (auto& pp : begins_line_) + { + ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); + } - shader_cpv_->release_vao(vao_cpv_); - shader_cpv_->release(); + for (auto& pp : begins_face_) + { + ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); + } + shader_cpv_->release_vao(vao_cpv_); + shader_cpv_->release(); + } - // round points + // balls + if (!begins_balls_.empty()) + { + shader_ps_->bind(); + shader_ps_->set_matrices(projection,modelview); + shader_ps_->bind_vao(vao_ps_); - shader_rp_->bind(); - shader_rp_->set_matrices(projection,modelview); - shader_rp_->bind_vao(vao_bl_); + for (auto& pp : begins_balls_) + { + shader_ps_->set_size(pp.width); + ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); + } + shader_ps_->release_vao(vao_ps_); + shader_ps_->release(); + } - for (auto& pp : begins_round_point_) + // round points + if (!begins_round_point_.empty()) { - if (pp.aa) + shader_rp_->bind(); + shader_rp_->set_matrices(projection,modelview); + shader_rp_->bind_vao(vao_rp_); + + for (auto& pp : begins_round_point_) { - ogl33_->glEnable(GL_BLEND); - ogl33_->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } + if (pp.aa) + { + ogl33_->glEnable(GL_BLEND); + ogl33_->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } - shader_rp_->set_width(pp.width); - ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); + shader_rp_->set_width(pp.width); + ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); - if (pp.aa) - ogl33_->glDisable(GL_BLEND); + if (pp.aa) + ogl33_->glDisable(GL_BLEND); + } + shader_rp_->release_vao(vao_rp_); + shader_rp_->release(); } - shader_rp_->release_vao(vao_bl_); - shader_rp_->release(); - // bold lines - - shader_bl_->bind(); - shader_bl_->set_matrices(projection,modelview); - shader_bl_->bind_vao(vao_bl_); - - for (auto& pp : begins_bold_line_) + if (!begins_bold_line_.empty()) { - shader_bl_->set_width(pp.width); - shader_bl_->set_color(QColor(255,255,0)); + shader_bl_->bind(); + shader_bl_->set_matrices(projection,modelview); + shader_bl_->bind_vao(vao_bl_); - if (pp.aa) + for (auto& pp : begins_bold_line_) { - ogl33_->glEnable(GL_BLEND); - ogl33_->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } + shader_bl_->set_width(pp.width); + shader_bl_->set_color(QColor(255,255,0)); - ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); + if (pp.aa) + { + ogl33_->glEnable(GL_BLEND); + ogl33_->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } - if (pp.aa) - ogl33_->glDisable(GL_BLEND); + ogl33_->glDrawArrays(pp.mode, pp.begin, pp.nb); - } + if (pp.aa) + ogl33_->glDisable(GL_BLEND); - shader_bl_->release_vao(vao_bl_); - shader_bl_->release(); + } + shader_bl_->release_vao(vao_bl_); + shader_bl_->release(); + } } diff --git a/cgogn/rendering/drawer.h b/cgogn/rendering/drawer.h index 660ecf58..de03cffb 100644 --- a/cgogn/rendering/drawer.h +++ b/cgogn/rendering/drawer.h @@ -28,6 +28,8 @@ #include #include #include +#include + #include #include #include @@ -58,6 +60,7 @@ class CGOGN_RENDERING_API Drawer static ShaderColorPerVertex* shader_cpv_; static ShaderBoldLine* shader_bl_; static ShaderRoundPoint* shader_rp_; + static ShaderPointSprite* shader_ps_; static int nb_instances_; VBO* vbo_pos_; @@ -68,6 +71,8 @@ class CGOGN_RENDERING_API Drawer std::vector begins_point_; std::vector begins_round_point_; + std::vector begins_balls_; + std::vector begins_line_; std::vector begins_bold_line_; std::vector begins_face_; @@ -76,9 +81,11 @@ class CGOGN_RENDERING_API Drawer unsigned int vao_cpv_; unsigned int vao_bl_; unsigned int vao_rp_; + unsigned int vao_ps_; float current_size_; bool current_aa_; + bool current_ball_; QOpenGLFunctions_3_3_Core* ogl33_; @@ -178,14 +185,24 @@ class CGOGN_RENDERING_API Drawer { current_aa_ = false; current_size_ = ps; + current_ball_ = false; } inline void point_size_aa(float ps) { current_aa_ = true; current_size_ = ps; + current_ball_ = false; + } + + inline void ball_size(float ps) + { + current_ball_ = true; + current_aa_ = false; + current_size_ = ps; } + /** * usr as glLineWidth */ diff --git a/cgogn/rendering/examples/drawing.cpp b/cgogn/rendering/examples/drawing.cpp index 7d99096e..5a093e23 100644 --- a/cgogn/rendering/examples/drawing.cpp +++ b/cgogn/rendering/examples/drawing.cpp @@ -105,10 +105,10 @@ void Drawing::init() drawer_->line_width_aa(3.0); drawer_->begin(GL_LINES); drawer_->color3f(1.0,1.0,1.0); - drawer_->vertex3fv(Vec3(-1,-1,0)); - drawer_->vertex3fv(Vec3(-1.2,-2,0)); - drawer_->vertex3fv(Vec3(-2,-2,0)); - drawer_->vertex3fv(Vec3(-2.2,1,0)); + drawer_->vertex3fv(Vec3(-1,1,0)); + drawer_->vertex3fv(Vec3(-1.2,0,0)); + drawer_->vertex3fv(Vec3(-2,0,0)); + drawer_->vertex3fv(Vec3(-2.2,3,0)); drawer_->end(); drawer_->begin(GL_TRIANGLES); @@ -129,6 +129,17 @@ void Drawing::init() drawer_->color3fv(C); drawer_->vertex3fv(P); } + drawer_->end(); + + drawer_->ball_size(0.1f); + drawer_->begin(GL_POINTS); + for (float a=0.05f; a < 1.0f; a+= 0.1f) + { + Vec3 P(4.0+std::cos(6.28*a)*1.2,-2.0+ std::sin(6.28*a)*1.2, std::sin(6.28*a)*0.2 ); + Vec3 C(a,0.5,1.0-a); + drawer_->color3fv(C); + drawer_->vertex3fv(P); + } drawer_->end(); drawer_->end_list(); @@ -145,6 +156,18 @@ void Drawing::init() drawer2_->vertex3f(x,y,z); } drawer2_->end(); + + drawer2_->ball_size(0.03); + drawer2_->begin(GL_POINTS); + drawer2_->color3f(1.0,1.0,1.0); + for (float z=-1.0f; z < 1.0f; z+= 0.2f) + for (float y=-2.0f; y < 0.0f; y+= 0.2f) + for (float x=-3.0f; x < -1.0f; x+= 0.2f) + { + drawer2_->vertex3f(x,y,z); + } + drawer2_->end(); + drawer2_->end_list(); } From 2ca6e4071bf2feac04bf4458e2e1b68ec0d5789e Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Fri, 18 Mar 2016 15:02:31 +0100 Subject: [PATCH 357/402] Specialized empty mask --- cgogn/core/cmap/map_base.h | 154 +++++++++++++++++-------------------- cgogn/core/utils/assert.h | 1 - 2 files changed, 70 insertions(+), 85 deletions(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 44eb39ff..8d80828b 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -48,6 +48,8 @@ enum TraversalStrategy FORCE_TOPO_CACHE }; +auto nomask = [](){ return true; }; + template class MapBase : public MapBaseData { @@ -619,46 +621,36 @@ class MapBase : public MapBaseData protected: /*! - * \Brief Methods to iterate over darts with a MASK that filters the traversed darts - * A MASK is an functor that determine if a dart should be traversed or skipped. - * It return false when a dart should be skipped, true in other cases. + * \Brief Methods to iterate over darts with a MASK that filters the traversed darts. + * A MASK is a callable that determine if a dart should be traversed or skipped. + * It returns false when a dart should be skipped, true in other cases. */ template inline Dart begin(const MASK& mask) const { - if (check_func_return_void(MASK)) { - return Dart(this->topology_.begin()); - } - else { - static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); - static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); + static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); + static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); - Dart d = Dart(this->topology_.begin()); - Dart end = Dart(this->topology_.end()); + Dart d = Dart(this->topology_.begin()); + Dart end = Dart(this->topology_.end()); - while (d != end && !mask(d)) - this->topology_.next(d.index); + while (d != end && !mask(d)) + this->topology_.next(d.index); - return d; - } + return d; } template inline void next(Dart& d, const MASK& mask) const { - if (check_func_return_void(MASK)) { - this->topology_.next(d.index); - } - else { - static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); - static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); + static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); + static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); - Dart end = Dart(this->topology_.end()); + Dart end = Dart(this->topology_.end()); - do { - this->topology_.next(d.index); - } while (d != end && !mask(d)); - } + do { + this->topology_.next(d.index); + } while (d != end && !mask(d)); } inline Dart end() const @@ -666,35 +658,30 @@ class MapBase : public MapBaseData return Dart(this->topology_.end()); } + template + inline bool is_masked(Dart d, const MASK& mask) const + { + return mask(d); + } + /*! - * \Brief Specialized methods to iterate over all darts. + * \Brief Specialized methods for the nomask lambda to iterate over all darts. * All darts are traversed without any MASK filtering. */ -// std::function nomask = [] () { return true; }; - -// template <> -// inline Dart begin(const std::function& mask) const -// { -// Dart d = Dart(this->topology_.begin()); - -// return d; -// } - -// template<> -// inline void next(Dart& d, const std::function&) const -// { -// this->topology_.next(d.index); -// } + inline Dart begin(const decltype( nomask )&) const + { + return Dart(this->topology_.begin()); + } -// inline Dart begin() const -// { -// return Dart(this->topology_.begin()); -// } + inline void next(Dart& d, const decltype( nomask )&) const + { + this->topology_.next(d.index); + } -// inline void next(Dart& d) const -// { -// this->topology_.next(d.index); -// } + inline bool is_masked(Dart d, const decltype( nomask )&) const + { + return true; + } public: @@ -703,18 +690,6 @@ class MapBase : public MapBaseData * @tparam FUNC type of the callable * @param f a callable */ - template - inline void foreach_dart_nomask(const FUNC& f) const - { -// static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); - -// for (Dart it = begin(), last = end(); it != last; next(it)) -// f(it); - - foreach_dart(f, [] (Dart) { return true; } ); -// foreach_dart(f, [] (Dart) -> void {} ); - } - template inline void foreach_dart(const FUNC& f) const { @@ -727,6 +702,12 @@ class MapBase : public MapBaseData foreach_dart(f, [this] (Dart d) { return this->is_boundary(d); }); } + template + inline void foreach_dart_nomask(const FUNC& f) const + { + foreach_dart(f, nomask ); + } + template inline void foreach_dart(const FUNC& f, const MASK& mask) const { @@ -751,7 +732,7 @@ class MapBase : public MapBaseData template inline void parallel_foreach_dart_nomask(const FUNC& f) const { - parallel_foreach_dart(f, [] (Dart) { return true;} ); + parallel_foreach_dart(f, nomask ); } template @@ -842,6 +823,12 @@ class MapBase : public MapBaseData foreach_dart_until(f, [this] (Dart d) { return this->is_boundary(d); }); } + template + inline void foreach_dart_until_nomask(const FUNC& f) const + { + foreach_dart_until(f, nomask); + } + template inline void foreach_dart_until(const FUNC& f, const MASK& mask) const { @@ -857,19 +844,6 @@ class MapBase : public MapBaseData } } - template - inline void foreach_dart_until_nomask(const FUNC& f) const - { - static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); - static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); - - for (Dart it = begin(), last = end(); it != last; next(it)) - { - if (!f(it)) - break; - } - } - /** * \brief apply a function on each orbit of the map * @tparam FUNC type of the callable @@ -882,15 +856,15 @@ class MapBase : public MapBaseData } template - inline void foreach_cell_nomask(const FUNC& f) const + inline void foreach_boundary_cell(const FUNC& f) const { - foreach_cell(f, [this] (Dart) { return true; }); + foreach_cell(f, [this] (Dart d) { return this->is_boundary(d); }); } template - inline void foreach_boundary_cell(const FUNC& f) const + inline void foreach_cell_nomask(const FUNC& f) const { - foreach_cell(f, [this] (Dart d) { return this->is_boundary(d); }); + foreach_cell(f, [](Dart) { return true; }); } template @@ -936,6 +910,12 @@ class MapBase : public MapBaseData parallel_foreach_cell(f, [this] (Dart d) { return this->is_boundary(d); }); } + template + inline void parallel_foreach_cell_nomask(const FUNC& f) const + { + parallel_foreach_cell(f, nomask); + } + template inline void parallel_foreach_cell(const FUNC& f, const MASK& mask) const { @@ -985,6 +965,12 @@ class MapBase : public MapBaseData foreach_cell_until(f, [this] (Dart d) { return this->is_boundary(d); }); } + template + inline void foreach_cell_until_nomask(const FUNC& f) const + { + foreach_cell_until(f, nomask); + } + template void foreach_cell_until(const FUNC& f, const MASK& mask) const { @@ -1216,7 +1202,7 @@ class MapBase : public MapBaseData unsigned int it = attr.begin(); const unsigned int end = attr.end(); // find first valid dart in the topo cache - while (it != end && !mask(cache[it])) + while (it != end && !is_masked(cache[it], mask)) { attr.next(it); } @@ -1228,7 +1214,7 @@ class MapBase : public MapBaseData do { attr.next(it); - } while (it != end && !mask(cache[it])); + } while (it != end && !is_masked(cache[it], mask)); } } @@ -1254,7 +1240,7 @@ class MapBase : public MapBaseData unsigned int it = attr.begin(); const unsigned int end = attr.end(); // find first valid dart in the topo cache - while (it != end && !mask(cache[it])) + while (it != end && !is_masked(cache[it], mask)) { attr.next(it); } @@ -1282,7 +1268,7 @@ class MapBase : public MapBaseData do { attr.next(loc_it); - } while (loc_it != local_end && !mask(cache[loc_it])); + } while (loc_it != local_end && !is_masked(cache[loc_it], mask)); } })); it = local_end; diff --git a/cgogn/core/utils/assert.h b/cgogn/core/utils/assert.h index 2054e16c..cb7266af 100644 --- a/cgogn/core/utils/assert.h +++ b/cgogn/core/utils/assert.h @@ -235,7 +235,6 @@ struct function_traits #define check_func_parameter_type(F, T) std::is_same::template arg<0>::type , T>::value #define check_func_ith_parameter_type(F, i, T) std::is_same::template arg::type , T>::value -#define check_func_return_void(F) std::is_void::result_type>::value #define check_func_return_type(F, T) std::is_same::result_type , T>::value #define inside_type(ATTR) typename std::remove_cv< typename std::remove_reference::type >::type From 432714626e38b6bb9e7118858129e53917a2d4dc Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Fri, 18 Mar 2016 15:37:32 +0100 Subject: [PATCH 358/402] clean close_map() --- cgogn/core/cmap/cmap2_builder.h | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/cgogn/core/cmap/cmap2_builder.h b/cgogn/core/cmap/cmap2_builder.h index 145aa04d..ddb41f05 100644 --- a/cgogn/core/cmap/cmap2_builder.h +++ b/cgogn/core/cmap/cmap2_builder.h @@ -139,7 +139,7 @@ class CMap2Builder_T * - a Face attribute is created, if needed, for the face that fill the hole. * - the Vertex, Edge and Volume attributes are copied, if needed, from incident cells. */ - inline void close_hole(Dart d) + inline Face close_hole(Dart d) { const Face f(close_hole_topo(d)); @@ -178,6 +178,8 @@ class CMap2Builder_T map_.template set_embedding(it, idx); }); } + + return f; } /*! @@ -193,23 +195,20 @@ class CMap2Builder_T inline void close_map() { std::vector fix_point_darts; - map_.foreach_dart( - [&] (Dart d) + map_.foreach_dart_nomask( [&] (Dart d) { if (map_.phi2(d) == d) fix_point_darts.push_back(d); - }, - [] (Dart) { return true; } - ); + }); for (Dart d : fix_point_darts) { if (map_.phi2(d) == d) { - close_hole(d); - map_.foreach_dart_of_orbit(Face(map_.phi2(d)), [&] (Dart db) + Face f = close_hole(d); + map_.foreach_dart_of_orbit(f, [&] (Dart e) { - map_.set_boundary(db,true); + map_.set_boundary(e, true); }); } } From 42b18be5e6ea85f82cc7f75ecaa6b7c4827cb84b Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Fri, 18 Mar 2016 16:40:33 +0100 Subject: [PATCH 359/402] it < last --- cgogn/core/cmap/cmap2_builder.h | 7 ++-- cgogn/core/cmap/map_base.h | 64 ++++++++++++++++----------------- 2 files changed, 36 insertions(+), 35 deletions(-) diff --git a/cgogn/core/cmap/cmap2_builder.h b/cgogn/core/cmap/cmap2_builder.h index ddb41f05..8ee807ca 100644 --- a/cgogn/core/cmap/cmap2_builder.h +++ b/cgogn/core/cmap/cmap2_builder.h @@ -194,14 +194,14 @@ class CMap2Builder_T */ inline void close_map() { - std::vector fix_point_darts; + std::vector* fix_point_darts = get_dart_buffers()->get_buffer(); map_.foreach_dart_nomask( [&] (Dart d) { if (map_.phi2(d) == d) - fix_point_darts.push_back(d); + fix_point_darts->push_back(d); }); - for (Dart d : fix_point_darts) + for (Dart d : (*fix_point_darts)) { if (map_.phi2(d) == d) { @@ -212,6 +212,7 @@ class CMap2Builder_T }); } } + get_dart_buffers()->release_buffer(fix_point_darts); } private: diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 8d80828b..2c92a343 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -634,7 +634,7 @@ class MapBase : public MapBaseData Dart d = Dart(this->topology_.begin()); Dart end = Dart(this->topology_.end()); - while (d != end && !mask(d)) + while (d.index < end.index && !mask(d)) this->topology_.next(d.index); return d; @@ -650,7 +650,7 @@ class MapBase : public MapBaseData do { this->topology_.next(d.index); - } while (d != end && !mask(d)); + } while (d.index < end.index && !mask(d)); } inline Dart end() const @@ -713,7 +713,7 @@ class MapBase : public MapBaseData { static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); - for (Dart it = begin(mask), last = end(); it != last; next(it, mask)) + for (Dart it = begin(mask), last = end(); it.index < last.index; next(it, mask)) f(it); } @@ -761,17 +761,17 @@ class MapBase : public MapBaseData Dart it = begin(mask); Dart last = end(); - while (it != last) + while (it.index < last.index) { for (unsigned int i = 0u; i < 2u; ++i) { - for (unsigned int j = 0u; j < nb_threads_pool && it != last; ++j) + for (unsigned int j = 0u; j < nb_threads_pool && it.index < last.index; ++j) { dart_buffers[i].push_back(dbuffs->get_buffer()); cgogn_assert(dart_buffers[i].size() <= nb_threads_pool); std::vector& darts = *dart_buffers[i].back(); darts.reserve(PARALLEL_BUFFER_SIZE); - for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != last; ++k) + for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it.index < last.index; ++k) { darts.push_back(it); next(it, mask); @@ -795,7 +795,7 @@ class MapBase : public MapBaseData dart_buffers[id].clear(); // if we reach the end of the map while filling buffers from the second set we need to clean them too. - if (it == last && i == 1u) + if (it.index >= last.index && i == 1u) { for (auto& fu : futures[1u]) fu.wait(); @@ -837,7 +837,7 @@ class MapBase : public MapBaseData static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); - for (Dart it = begin(mask), last = end(); it != last; next(it, mask)) + for (Dart it = begin(mask), last = end(); it.index < last.index; next(it, mask)) { if (!f(it)) break; @@ -1011,7 +1011,7 @@ class MapBase : public MapBaseData using CellType = typename function_traits::template arg<0>::type; DartMarker dm(*to_concrete()); - for (Dart it = begin(mask), last = end(); it != last; next(it, mask)) + for (Dart it = begin(mask), last = end(); it.index < last.index; next(it, mask)) { if (!dm.is_marked(it)) { @@ -1049,13 +1049,13 @@ class MapBase : public MapBaseData unsigned int i = 0u; // buffer id (0/1) unsigned int j = 0u; // thread id (0..nb_threads_pool) - while (it != last) + while (it.index < last.index) { // fill buffer cells_buffers[i].push_back(dbuffs->template get_cell_buffer()); VecCell& cells = *cells_buffers[i].back(); cells.reserve(PARALLEL_BUFFER_SIZE); - for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != last; ) + for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it.index < last.index; ) { if (!dm.is_marked(it)) { @@ -1104,7 +1104,7 @@ class MapBase : public MapBaseData static const Orbit ORBIT = CellType::ORBIT; CellMarker cm(*to_concrete()); - for (Dart it = begin(mask), last = end(); it != last; next(it, mask)) + for (Dart it = begin(mask), last = end(); it.index < last.index; next(it, mask)) { CellType c(it); if (!cm.is_marked(c)) @@ -1142,13 +1142,13 @@ class MapBase : public MapBaseData unsigned int i = 0u; // buffer id (0/1) unsigned int j = 0u; // thread id (0..nb_threads_pool) - while (it != last) + while (it.index < last.index) { // fill buffer cells_buffers[i].push_back(dbuffs->template get_cell_buffer()); VecCell& cells = *cells_buffers[i].back(); cells.reserve(PARALLEL_BUFFER_SIZE); - for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it != last; ) + for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it.index < last.index; ) { CellType c(it); if (!cm.is_marked(c)) @@ -1200,21 +1200,21 @@ class MapBase : public MapBaseData const auto& attr = this->attributes_[ORBIT]; unsigned int it = attr.begin(); - const unsigned int end = attr.end(); + const unsigned int last = attr.end(); // find first valid dart in the topo cache - while (it != end && !is_masked(cache[it], mask)) + while (it < last && !is_masked(cache[it], mask)) { attr.next(it); } // apply function over valid darts of the cache - while (it != end) + while (it < last) { f(CellType(cache[it])); // next valid dart do { attr.next(it); - } while (it != end && !is_masked(cache[it], mask)); + } while (it < last && !is_masked(cache[it], mask)); } } @@ -1238,9 +1238,9 @@ class MapBase : public MapBaseData const auto& attr = this->attributes_[ORBIT]; unsigned int it = attr.begin(); - const unsigned int end = attr.end(); + const unsigned int last = attr.end(); // find first valid dart in the topo cache - while (it != end && !is_masked(cache[it], mask)) + while (it < last && !is_masked(cache[it], mask)) { attr.next(it); } @@ -1248,16 +1248,16 @@ class MapBase : public MapBaseData unsigned int nbc = PARALLEL_BUFFER_SIZE; // do block of PARALLEL_BUFFER_SIZE only if nb cells is huge else just divide - if ( (static_cast(end - it) < 16*nb_threads_pool*PARALLEL_BUFFER_SIZE ) - && (static_cast(end - it) > nb_threads_pool)) - nbc = static_cast((end - it) / nb_threads_pool); + if ( (static_cast(last - it) < 16*nb_threads_pool*PARALLEL_BUFFER_SIZE ) + && (static_cast(last - it) > nb_threads_pool)) + nbc = static_cast((last - it) / nb_threads_pool); - unsigned int local_end = std::min(it+nbc, end); + unsigned int local_end = std::min(it+nbc, last); unsigned int i = 0; // used buffered futures 0/1 unsigned int j = 0; // thread num - while (it != end) + while (it < last) { futures[i].push_back(thread_pool->enqueue([&cache, &attr, &mask, it, local_end, &f] (unsigned int th_id) { @@ -1272,7 +1272,7 @@ class MapBase : public MapBaseData } })); it = local_end; - local_end = std::min(local_end + nbc, end); + local_end = std::min(local_end + nbc, last); if (++j == nb_threads_pool) // change thread { // again from 0 & change buffer @@ -1298,7 +1298,7 @@ class MapBase : public MapBaseData using CellType = typename function_traits::template arg<0>::type; DartMarker dm(*to_concrete()); - for (Dart it = begin(mask), last = end(); it != last; next(it, mask)) + for (Dart it = begin(mask), last = end(); it.index < last.index; next(it, mask)) { if (!dm.is_marked(it)) { @@ -1317,7 +1317,7 @@ class MapBase : public MapBaseData static const Orbit ORBIT = CellType::ORBIT; CellMarker cm(*to_concrete()); - for (Dart it = begin(mask), last = end(); it != last; next(it, mask)) + for (Dart it = begin(mask), last = end(); it.index < last.index; next(it, mask)) { CellType c(it); if (!cm.is_marked(c)) @@ -1339,16 +1339,16 @@ class MapBase : public MapBaseData const auto& attr = this->attributes_[ORBIT]; unsigned int it = attr.begin(); - const unsigned int end = attr.end(); + const unsigned int last = attr.end(); Dart d = cache[it]; // find first valid dart in the topo cache - while (it != end && !mask.valid(d)) + while (it < last && !mask.valid(d)) { attr.next(it); d = cache[it]; } // apply function over valid darts of the cache - while (it != end) + while (it < last) { if (!f(CellType(d))) break; @@ -1357,7 +1357,7 @@ class MapBase : public MapBaseData { attr.next(it); d = cache[it]; - } while (it != end && !mask.valid(d)); + } while (it < last && !mask.valid(d)); } } }; From dda8a526aee73f690a16cf41aebfd45529afe3fb Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Fri, 18 Mar 2016 16:48:18 +0100 Subject: [PATCH 360/402] fix GLSL compil pb on mac --- cgogn/rendering/shaders/shader_point_sprite.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/cgogn/rendering/shaders/shader_point_sprite.cpp b/cgogn/rendering/shaders/shader_point_sprite.cpp index 9ec7de65..b13bbfef 100644 --- a/cgogn/rendering/shaders/shader_point_sprite.cpp +++ b/cgogn/rendering/shaders/shader_point_sprite.cpp @@ -259,12 +259,26 @@ ShaderPointSprite::ShaderPointSprite(bool color_per_vertex, bool size_per_vertex gs += std::string("#define WITH_COLOR 1\n"); fs += std::string("#define WITH_COLOR 1\n"); } + else + { + vs += std::string("#define WITH_COLOR 0\n"); + gs += std::string("#define WITH_COLOR 0\n"); + fs += std::string("#define WITH_COLOR 0\n"); + } + if (size_per_vertex) { vs += std::string("#define WITH_SIZE 1\n"); gs += std::string("#define WITH_SIZE 1\n"); fs += std::string("#define WITH_SIZE 1\n"); } + else + { + vs += std::string("#define WITH_SIZE 0\n"); + gs += std::string("#define WITH_SIZE 0\n"); + fs += std::string("#define WITH_SIZE 0\n"); + } + vs += std::string(vertex_shader_source2_); gs += std::string(geometry_shader_source2_); fs += std::string(fragment_shader_source2_); From afeb53e15993824fdd8e21e6500c160c224a80db Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Fri, 18 Mar 2016 17:36:26 +0100 Subject: [PATCH 361/402] static_assert and removing is_masked --- cgogn/core/cmap/cmap3_builder.h | 12 +++++------- cgogn/core/cmap/map_base.h | 29 +++++++---------------------- 2 files changed, 12 insertions(+), 29 deletions(-) diff --git a/cgogn/core/cmap/cmap3_builder.h b/cgogn/core/cmap/cmap3_builder.h index 4236af2f..dde7abfb 100644 --- a/cgogn/core/cmap/cmap3_builder.h +++ b/cgogn/core/cmap/cmap3_builder.h @@ -191,21 +191,19 @@ class CMap3Builder_T * Add volumes to the map that close every existing hole. * @return the number of closed holes */ - inline unsigned int close_map() + inline void close_map() { // Search the map for topological holes (fix points of phi3) - std::vector fix_point_darts; + std::vector* fix_point_darts = get_dart_buffers()->get_buffer(); map_.foreach_dart_nomask( [&] (Dart d) { if (map_.phi3(d) == d) - fix_point_darts.push_back(d); + fix_point_darts->push_back(d); }); - unsigned int nb = 0u; - for (Dart d : fix_point_darts) + for (Dart d : (*fix_point_darts)) { if (map_.phi3(d) == d) { - ++nb; close_hole_topo(d); map_.foreach_dart_of_orbit(Volume(map_.phi3(d)), [&] (Dart db) { @@ -275,7 +273,7 @@ class CMap3Builder_T } } } - return nb; + get_dart_buffers()->release_buffer(fix_point_darts); } private: diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 2c92a343..b07ef01a 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -48,7 +48,7 @@ enum TraversalStrategy FORCE_TOPO_CACHE }; -auto nomask = [](){ return true; }; +auto nomask = [](Dart){ return true; }; template class MapBase : public MapBaseData @@ -628,9 +628,6 @@ class MapBase : public MapBaseData template inline Dart begin(const MASK& mask) const { - static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); - static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); - Dart d = Dart(this->topology_.begin()); Dart end = Dart(this->topology_.end()); @@ -643,9 +640,6 @@ class MapBase : public MapBaseData template inline void next(Dart& d, const MASK& mask) const { - static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); - static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); - Dart end = Dart(this->topology_.end()); do { @@ -658,12 +652,6 @@ class MapBase : public MapBaseData return Dart(this->topology_.end()); } - template - inline bool is_masked(Dart d, const MASK& mask) const - { - return mask(d); - } - /*! * \Brief Specialized methods for the nomask lambda to iterate over all darts. * All darts are traversed without any MASK filtering. @@ -678,11 +666,6 @@ class MapBase : public MapBaseData this->topology_.next(d.index); } - inline bool is_masked(Dart d, const decltype( nomask )&) const - { - return true; - } - public: /** @@ -712,6 +695,8 @@ class MapBase : public MapBaseData inline void foreach_dart(const FUNC& f, const MASK& mask) const { static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); + static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); + static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); for (Dart it = begin(mask), last = end(); it.index < last.index; next(it, mask)) f(it); @@ -1202,7 +1187,7 @@ class MapBase : public MapBaseData unsigned int it = attr.begin(); const unsigned int last = attr.end(); // find first valid dart in the topo cache - while (it < last && !is_masked(cache[it], mask)) + while (it < last && !mask(cache[it])) { attr.next(it); } @@ -1214,7 +1199,7 @@ class MapBase : public MapBaseData do { attr.next(it); - } while (it < last && !is_masked(cache[it], mask)); + } while (it < last && !mask(cache[it])); } } @@ -1240,7 +1225,7 @@ class MapBase : public MapBaseData unsigned int it = attr.begin(); const unsigned int last = attr.end(); // find first valid dart in the topo cache - while (it < last && !is_masked(cache[it], mask)) + while (it < last && !mask(cache[it])) { attr.next(it); } @@ -1268,7 +1253,7 @@ class MapBase : public MapBaseData do { attr.next(loc_it); - } while (loc_it != local_end && !is_masked(cache[loc_it], mask)); + } while (loc_it != local_end && !mask(cache[loc_it])); } })); it = local_end; From ee4ee04060b02b1b59f3cfabf42e9ead8e1030de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Fri, 18 Mar 2016 18:10:59 +0100 Subject: [PATCH 362/402] small fixes in tetgen_io MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/mesh_generation/tetgen_io.h | 30 ++++++++++------------------ 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/cgogn/io/mesh_generation/tetgen_io.h b/cgogn/io/mesh_generation/tetgen_io.h index de7d54ef..41d816b7 100644 --- a/cgogn/io/mesh_generation/tetgen_io.h +++ b/cgogn/io/mesh_generation/tetgen_io.h @@ -353,9 +353,6 @@ std::unique_ptr export_tetgen(CMap2& map, const typename C using TetgenReal = REAL; std::unique_ptr output = make_unique(); - // memory initialization - output->initialize(); - // 0-based indexing output->firstnumber = 0; @@ -371,41 +368,34 @@ std::unique_ptr export_tetgen(CMap2& map, const typename C output->pointlist[i++] = vec[0]; output->pointlist[i++] = vec[1]; output->pointlist[i++] = vec[2]; - }, [](Dart) {return true;}); - - - tetgenio::facet* f ; - tetgenio::polygon* p ; + }); output->numberoffacets = map.template nb_cells(); output->facetlist = new tetgenio::facet[output->numberoffacets] ; - //for each facet i = 0u; - map.foreach_cell([&f,&output,&p,&i,&map](Face face) + map.template foreach_cell([&output,&i,&map](Face face) { - f = &(output->facetlist[i]); + tetgenio::facet* f = &(output->facetlist[i]); + tetgenio::init(f); f->numberofpolygons = 1; f->polygonlist = new tetgenio::polygon[f->numberofpolygons]; - p = f->polygonlist; + tetgenio::polygon* p = f->polygonlist; + tetgenio::init(p); p->numberofvertices = map.degree(face); p->vertexlist = new int[p->numberofvertices]; unsigned int j = 0u; - Dart dit = face; - do + map.foreach_incident_vertex(face, [&p,&map,&j](Vertex v) { - p->vertexlist[j] = map.get_embedding(Vertex(dit)); - dit = map.phi1(dit); - ++j; - }while(dit != face.dart); + p->vertexlist[j++] = map.get_embedding(v); + }); f->numberofholes = 0; f->holelist = nullptr; ++i; - }, [](Dart) {return true;}); - + }); return output; } From 01d45fd8309f650e22471254a16e69c0629dfea9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Fri, 18 Mar 2016 18:18:43 +0100 Subject: [PATCH 363/402] fixed compilation issue. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/volume_import.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cgogn/io/volume_import.h b/cgogn/io/volume_import.h index 1f96c2ff..8f8ecdbd 100644 --- a/cgogn/io/volume_import.h +++ b/cgogn/io/volume_import.h @@ -462,8 +462,8 @@ class VolumeImport : public MeshImportGen if (nbBoundaryFaces > 0) { - unsigned int nbH = mbuild.close_map(); - std::cout << CGOGN_FUNC << ": Map closed with " << nbBoundaryFaces << " boundary face(s) and " << nbH << " hole(s)." << std::endl; + mbuild.close_map(); + std::cout << CGOGN_FUNC << ": Map closed with " << nbBoundaryFaces << " boundary face(s)." << std::endl; } if (this->volume_attributes_.get_nb_attributes() > 0) From d075a08344a76885b12f1602f914d69810270592 Mon Sep 17 00:00:00 2001 From: David Cazier/develop Date: Fri, 18 Mar 2016 18:30:09 +0100 Subject: [PATCH 364/402] bug --- cgogn/io/volume_import.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cgogn/io/volume_import.h b/cgogn/io/volume_import.h index 1f96c2ff..9c96ec7d 100644 --- a/cgogn/io/volume_import.h +++ b/cgogn/io/volume_import.h @@ -462,8 +462,7 @@ class VolumeImport : public MeshImportGen if (nbBoundaryFaces > 0) { - unsigned int nbH = mbuild.close_map(); - std::cout << CGOGN_FUNC << ": Map closed with " << nbBoundaryFaces << " boundary face(s) and " << nbH << " hole(s)." << std::endl; + mbuild.close_map(); } if (this->volume_attributes_.get_nb_attributes() > 0) From 948b16854cc946ced427fc006950d8ea2341cbbc Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Fri, 18 Mar 2016 23:37:12 +0100 Subject: [PATCH 365/402] nb_cells correction + boundary cells type check in traversal & nb_cells --- cgogn/core/cmap/cmap2.h | 2 + cgogn/core/cmap/cmap3.h | 2 + cgogn/core/cmap/map_base.h | 79 ++++++++++++++--------- cgogn/core/tests/cmap/cmap2_test.cpp | 4 +- cgogn/geometry/tests/algos/algos_test.cpp | 4 +- 5 files changed, 57 insertions(+), 34 deletions(-) diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 0e295f7f..f2bf842e 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -55,6 +55,8 @@ class CMap2_T : public CMap1_T using Face = typename Inherit::Face; using Volume = Cell; + using Boundary = Face; + template using ChunkArray = typename Inherit::template ChunkArray; template diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 7a3d5ceb..b86bd21d 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -58,6 +58,8 @@ class CMap3_T : public CMap2_T using Face = Cell; using Volume = typename Inherit::Volume; + using Boundary = Volume; + template using ChunkArray = typename Inherit::template ChunkArray; template diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index b07ef01a..ec60ef0b 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -48,7 +48,7 @@ enum TraversalStrategy FORCE_TOPO_CACHE }; -auto nomask = [](Dart){ return true; }; +auto nomask = [] (Dart) { return true; }; template class MapBase : public MapBaseData @@ -314,8 +314,7 @@ class MapBase : public MapBaseData inline void release_mark_attribute(ChunkArray* ca) { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - cgogn_message_assert(this->template is_embedded(), - "Invalid parameter: orbit not embedded"); + cgogn_message_assert(this->template is_embedded(), "Invalid parameter: orbit not embedded"); this->mark_attributes_[ORBIT][this->get_current_thread_index()].push_back(ca); } @@ -341,16 +340,10 @@ class MapBase : public MapBaseData this->embeddings_[ORBIT] = ca; // initialize all darts indices to EMBNULL for this ORBIT - foreach_dart( - [this, ca] (Dart d) { (*ca)[d.index] = EMBNULL; }, - [] (Dart) { return true; } - ); + foreach_dart_nomask([this, ca] (Dart d) { (*ca)[d.index] = EMBNULL; }); // initialize the indices of the existing orbits - foreach_cell( - [this] (Cell c) { new_orbit_embedding(c); }, - [] (Dart) { return true; } - ); + foreach_cell_nomask([this] (Cell c) { new_orbit_embedding(c); }); cgogn_assert(check_map_integrity()); } @@ -380,14 +373,13 @@ class MapBase : public MapBaseData AttributeHandler counter = add_attribute("__tmp_counter"); for (unsigned int& i : counter) i = 0; - foreach_cell( + foreach_cell_nomask( [this, &counter] (Cell c) { if (counter[c] > 0) this->new_orbit_embedding(c); counter[c]++; - }, - [] (Dart) { return true; } + } ); remove_attribute(counter); @@ -419,7 +411,7 @@ class MapBase : public MapBaseData counter[i] = 0; // Check that the indexation of cells is correct - foreach_cell_until_dart_marking( + foreach_cell_until_nomask( [&] (CellType c) { unsigned int idx = this->get_embedding(c); @@ -449,8 +441,7 @@ class MapBase : public MapBaseData }); return result; - }, - [] (Dart) { return true; } + } ); // check that all cells present in the attribute handler are used if (result) @@ -523,9 +514,8 @@ class MapBase : public MapBaseData static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); cgogn_message_assert(is_topo_cache_enabled(), "Trying to update a disabled global topo cache"); - foreach_cell( - [this] (Cell c) { (*this->global_topo_cache_[ORBIT])[this->get_embedding(c)] = c.dart; }, - [] (Dart) { return true; } + foreach_cell_nomask( + [this] (Cell c) { (*this->global_topo_cache_[ORBIT])[this->get_embedding(c)] = c.dart; } ); } @@ -582,17 +572,39 @@ class MapBase : public MapBaseData */ template unsigned int nb_cells() const + { + unsigned int result = 0; + foreach_cell([&result] (Cell) { ++result; }); + return result; + } + + unsigned int nb_boundary_cells() const + { + unsigned int result = 0; + foreach_boundary_cell([&result] (typename ConcreteMap::Boundary) { ++result; }); + return result; + } + + template + unsigned int nb_cells_nomask() const { if (this->template is_embedded()) return this->attributes_[ORBIT].size(); else { unsigned int result = 0; - foreach_cell([&result] (Cell) { ++result; }); + foreach_cell_nomask([&result] (Cell) { ++result; }); return result; } } + template + unsigned int nb_cells(const MASK& mask) const + { + unsigned int result = 0; + foreach_cell([&result] (Cell) { ++result; }, mask); + } + /** * \brief return the number of darts in the given cell */ @@ -631,7 +643,7 @@ class MapBase : public MapBaseData Dart d = Dart(this->topology_.begin()); Dart end = Dart(this->topology_.end()); - while (d.index < end.index && !mask(d)) + while (d != end && !mask(d)) this->topology_.next(d.index); return d; @@ -644,7 +656,7 @@ class MapBase : public MapBaseData do { this->topology_.next(d.index); - } while (d.index < end.index && !mask(d)); + } while (d != end && !mask(d)); } inline Dart end() const @@ -656,12 +668,12 @@ class MapBase : public MapBaseData * \Brief Specialized methods for the nomask lambda to iterate over all darts. * All darts are traversed without any MASK filtering. */ - inline Dart begin(const decltype( nomask )&) const + inline Dart begin(const decltype(nomask)&) const { return Dart(this->topology_.begin()); } - inline void next(Dart& d, const decltype( nomask )&) const + inline void next(Dart& d, const decltype(nomask)&) const { this->topology_.next(d.index); } @@ -688,7 +700,7 @@ class MapBase : public MapBaseData template inline void foreach_dart_nomask(const FUNC& f) const { - foreach_dart(f, nomask ); + foreach_dart(f, nomask); } template @@ -717,7 +729,7 @@ class MapBase : public MapBaseData template inline void parallel_foreach_dart_nomask(const FUNC& f) const { - parallel_foreach_dart(f, nomask ); + parallel_foreach_dart(f, nomask); } template @@ -843,13 +855,16 @@ class MapBase : public MapBaseData template inline void foreach_boundary_cell(const FUNC& f) const { + using CellType = typename function_traits::template arg<0>::type; + static_assert(std::is_same::value, "Bad boundary orbit"); + foreach_cell(f, [this] (Dart d) { return this->is_boundary(d); }); } template inline void foreach_cell_nomask(const FUNC& f) const { - foreach_cell(f, [](Dart) { return true; }); + foreach_cell(f, nomask); } template @@ -1187,7 +1202,7 @@ class MapBase : public MapBaseData unsigned int it = attr.begin(); const unsigned int last = attr.end(); // find first valid dart in the topo cache - while (it < last && !mask(cache[it])) + while (it != last && !mask(cache[it])) { attr.next(it); } @@ -1225,7 +1240,7 @@ class MapBase : public MapBaseData unsigned int it = attr.begin(); const unsigned int last = attr.end(); // find first valid dart in the topo cache - while (it < last && !mask(cache[it])) + while (it != last && !mask(cache[it])) { attr.next(it); } @@ -1327,7 +1342,7 @@ class MapBase : public MapBaseData const unsigned int last = attr.end(); Dart d = cache[it]; // find first valid dart in the topo cache - while (it < last && !mask.valid(d)) + while (it != last && !mask(d)) { attr.next(it); d = cache[it]; @@ -1342,7 +1357,7 @@ class MapBase : public MapBaseData { attr.next(it); d = cache[it]; - } while (it < last && !mask.valid(d)); + } while (it < last && !mask(d)); } } }; diff --git a/cgogn/core/tests/cmap/cmap2_test.cpp b/cgogn/core/tests/cmap/cmap2_test.cpp index fab9b7ec..3b98d16f 100644 --- a/cgogn/core/tests/cmap/cmap2_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_test.cpp @@ -182,7 +182,9 @@ TEST_F(CMap2Test, add_face) EXPECT_EQ(cmap_.nb_cells(), count_vertices); EXPECT_EQ(cmap_.nb_cells(), count_vertices); - EXPECT_EQ(cmap_.nb_cells(), 2 * NB_MAX); + EXPECT_EQ(cmap_.nb_cells(), NB_MAX); + EXPECT_EQ(cmap_.nb_cells_nomask(), 2 * NB_MAX); + EXPECT_EQ(cmap_.nb_boundary_cells(), NB_MAX); EXPECT_EQ(cmap_.nb_cells(), NB_MAX); EXPECT_TRUE(cmap_.check_map_integrity()); } diff --git a/cgogn/geometry/tests/algos/algos_test.cpp b/cgogn/geometry/tests/algos/algos_test.cpp index d32b05ad..5d4f893c 100644 --- a/cgogn/geometry/tests/algos/algos_test.cpp +++ b/cgogn/geometry/tests/algos/algos_test.cpp @@ -176,6 +176,8 @@ TYPED_TEST(Algos_TEST, EarTriangulation) EXPECT_DOUBLE_EQ(area, 75.0); cgogn::geometry::apply_ear_triangulation(this->map2_, f, vertex_position); - EXPECT_TRUE(this->map2_.template nb_cells() == 4); + EXPECT_TRUE(this->map2_.template nb_cells() == 3); + EXPECT_TRUE(this->map2_.template nb_cells_nomask() == 4); + EXPECT_TRUE(this->map2_.nb_boundary_cells() == 1); EXPECT_TRUE(this->map2_.template nb_cells() == 7); } From 6ba91ec2ecce5f4e2884cb41b486cc2fcf53da6e Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Fri, 18 Mar 2016 23:40:47 +0100 Subject: [PATCH 366/402] missing return statement --- cgogn/core/cmap/map_base.h | 1 + 1 file changed, 1 insertion(+) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index ec60ef0b..2a9c992c 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -603,6 +603,7 @@ class MapBase : public MapBaseData { unsigned int result = 0; foreach_cell([&result] (Cell) { ++result; }, mask); + return result; } /** From 183550e8230b457c349d6a8d040e440b38be6fc9 Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Sat, 19 Mar 2016 11:57:40 +0100 Subject: [PATCH 367/402] fixed link error. Signed-off-by: Etienne Schmitt --- cgogn/io/mesh_generation/examples/CMakeLists.txt | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/cgogn/io/mesh_generation/examples/CMakeLists.txt b/cgogn/io/mesh_generation/examples/CMakeLists.txt index f8ca64ce..6ab26daa 100644 --- a/cgogn/io/mesh_generation/examples/CMakeLists.txt +++ b/cgogn/io/mesh_generation/examples/CMakeLists.txt @@ -18,15 +18,10 @@ set(SOURCE_FILES program_options.cpp ) - if (CGOGN_WITH_CGAL_EXAMPLES) - find_package(Boost QUIET REQUIRED COMPONENTS program_options) - - + find_package(Boost REQUIRED COMPONENTS program_options) add_executable(map3_from_image ${HEADER_FILES} ${SOURCE_FILES}) - target_link_libraries(map3_from_image cgogn_core cgogn_io_mesh_generation ) - - + target_link_libraries(map3_from_image cgogn_core cgogn_io_mesh_generation ${Boost_LIBRARIES}) endif() add_executable(map3_from_surface map3_from_surface.cpp) From e105e386afb41f429f79e2bcfa4d5bdf9446e70a Mon Sep 17 00:00:00 2001 From: Etienne Schmitt Date: Sun, 20 Mar 2016 12:06:45 +0100 Subject: [PATCH 368/402] Fixed bug in cmap3::foreach_dart_of_PHI21_PHI31 Signed-off-by: Etienne Schmitt --- cgogn/core/cmap/cmap3.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 7a3d5ceb..8b47b5a3 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -348,11 +348,11 @@ class CMap3_T : public CMap2_T marker.mark(d); for(unsigned int i = 0; i < marked_darts->size(); ++i) { - f((*marked_darts)[i]); + const Dart curr_dart = marked_darts->operator [](i); + f(curr_dart); - Dart d1 = this->phi1((*marked_darts)[i]); - Dart d21 = this->phi2(d1); // turn in volume - Dart d31 = phi3(d1); // change volume + const Dart d21 = this->phi1(this->phi2(curr_dart)); // turn in volume + const Dart d31 = this->phi1(this->phi3(curr_dart)); // change volume if(!marker.is_marked(d21)) marker.mark(d21); if(!marker.is_marked(d31)) From faa118390ef5390f28655a92c84b9ef861fb8464 Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Mon, 21 Mar 2016 10:29:03 +0100 Subject: [PATCH 369/402] update PHI21_PHI31 orbit traversal in CMap3 --- cgogn/core/cmap/cmap3.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 57e26f6c..604216a1 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -353,12 +353,14 @@ class CMap3_T : public CMap2_T const Dart curr_dart = marked_darts->operator [](i); f(curr_dart); - const Dart d21 = this->phi1(this->phi2(curr_dart)); // turn in volume - const Dart d31 = this->phi1(this->phi3(curr_dart)); // change volume - if(!marker.is_marked(d21)) - marker.mark(d21); - if(!marker.is_marked(d31)) - marker.mark(d31); + const Dart d_1 = this->phi_1(curr_dart); + const Dart d2_1 = this->phi2(d_1); // turn in volume + const Dart d3_1 = phi3(d_1); // change volume + + if(!marker.is_marked(d2_1)) + marker.mark(d2_1); + if(!marker.is_marked(d3_1)) + marker.mark(d3_1); } } From 942fd94cd91c66ed60f59c74293590009b6acc7b Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Mon, 21 Mar 2016 11:26:35 +0100 Subject: [PATCH 370/402] cleaning of degree / codegree notions --- cgogn/core/cmap/cmap1.h | 15 ++++- cgogn/core/cmap/cmap2.h | 39 +++++++++++- cgogn/core/cmap/cmap3.h | 72 +++++++++++++++++++++-- cgogn/core/cmap/cmap3_builder.h | 2 +- cgogn/core/tests/cmap/cmap1_test.cpp | 4 +- cgogn/core/tests/cmap/cmap1_topo_test.cpp | 34 +++++------ cgogn/core/tests/cmap/cmap2_test.cpp | 2 +- cgogn/core/tests/cmap/cmap2_topo_test.cpp | 18 +++--- cgogn/geometry/algos/area.h | 2 +- cgogn/geometry/algos/ear_triangulation.h | 2 +- cgogn/geometry/algos/normal.h | 2 +- cgogn/geometry/algos/picking.h | 54 ++++++++--------- cgogn/io/mesh_generation/tetgen_io.h | 2 +- cgogn/io/volume_import.h | 4 +- cgogn/rendering/map_render.h | 6 +- cgogn/rendering/volume_render.h | 6 +- 16 files changed, 180 insertions(+), 84 deletions(-) diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 770bcbdc..4f207669 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -344,17 +344,26 @@ class CMap1_T : public CMap0_T phi1_sew(e, d); // Sew the last edge } + /******************************************************************************* + * Connectivity information + *******************************************************************************/ + public: - inline unsigned int degree(Face f) const + inline unsigned int degree(Vertex v) const + { + return 2; + } + + inline unsigned int codegree(Face f) const { return this->nb_darts_of_orbit(f); } - inline bool has_degree(Face f, unsigned int degree) const + inline bool has_codegree(Face f, unsigned int codegree) const { Dart it = f.dart ; - for (unsigned int i=1;i } } + /******************************************************************************* + * Connectivity information + *******************************************************************************/ + + inline unsigned int degree(Vertex v) const + { + return this->nb_darts_of_orbit(v); + } + + inline unsigned int codegree(Edge e) const + { + return 2; + } + + inline unsigned int degree(Edge e) const + { + return 2; + } + + inline unsigned int codegree(Face f) const + { + return Inherit::codegree(f); + } + inline unsigned int degree(Face f) const { - return Inherit::degree(f); + return 1; } - inline unsigned int degree(Vertex v) const + inline unsigned int codegree(Volume v) const { - return this->nb_darts_of_orbit(v); + unsigned int result = 0; + foreach_incident_face(v, [&result] (Face) { ++result; }); + return result; + } + + inline unsigned int degree(Volume v) const + { + return 1; } /******************************************************************************* * Orbits traversal *******************************************************************************/ +protected: + template inline void foreach_dart_of_PHI2(Dart d, const FUNC& f) const { diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 604216a1..f6ab7d2a 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -317,22 +317,84 @@ class CMap3_T : public CMap2_T return d_quad; } + /******************************************************************************* + * Connectivity information + *******************************************************************************/ public: + inline unsigned int degree(Vertex2 v) const + { + return Inherit::degree(v); + } + + inline unsigned int degree(Vertex v) const + { + unsigned int result = 0; + foreach_incident_edge(v, [&result] (Edge) { ++result; }); + return result; + } + + inline unsigned int codegree(Edge2 e) const + { + return Inherit::codegree(e); + } + + inline unsigned int degree(Edge2 e) const + { + return Inherit::degree(e); + } + + inline unsigned int codegree(Edge e) const + { + return 2; + } + + inline unsigned int degree(Edge e) const + { + unsigned int result = 0; + foreach_incident_face(e, [&result] (Face) { ++result; }); + return result; + } + + inline unsigned int codegree(Face2 f) const + { + return Inherit::codegree(f); + } + + inline unsigned int degree(Face2 f) const + { + return Inherit::degree(f); + } + + inline unsigned int codegree(Face f) const + { + return codegree(Face2(f.dart)); + } + inline unsigned int degree(Face f) const { - return Inherit::degree(Face2(f.dart)); + return 2; + } + + inline unsigned int codegree(Volume v) const + { + return Inherit::codegree(v); + } + + inline unsigned int degree(Volume v) const + { + return 2; } - inline bool has_degree(Face f, unsigned int degree) const + inline bool has_codegree(Face2 f, unsigned int codegree) const { - return Inherit::has_degree(Face2(f.dart), degree); + return Inherit::has_codegree(f, codegree); } - inline bool has_degree(Face2 f, unsigned int degree) const + inline bool has_codegree(Face f, unsigned int codegree) const { - return Inherit::has_degree(f, degree); + return Inherit::has_codegree(Face2(f.dart), codegree); } protected: diff --git a/cgogn/core/cmap/cmap3_builder.h b/cgogn/core/cmap/cmap3_builder.h index dde7abfb..7ca06396 100644 --- a/cgogn/core/cmap/cmap3_builder.h +++ b/cgogn/core/cmap/cmap3_builder.h @@ -147,7 +147,7 @@ class CMap3Builder_T Dart it = visitedFaces[i]; Dart f = it; - const Dart b = map_.CMap3::Inherit::Inherit::add_face_topo(map_.degree(Face(f))); + const Dart b = map_.CMap3::Inherit::Inherit::add_face_topo(map_.codegree(Face(f))); boundary_marker.mark_orbit(Face2(b)); ++count; diff --git a/cgogn/core/tests/cmap/cmap1_test.cpp b/cgogn/core/tests/cmap/cmap1_test.cpp index ff63858d..be4f4913 100644 --- a/cgogn/core/tests/cmap/cmap1_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_test.cpp @@ -125,7 +125,7 @@ TEST_F(CMap1Test, remove_face) if (std::rand() % 3 == 1) { Face f(d); - unsigned int k = cmap_.degree(f); + unsigned int k = cmap_.codegree(f); cmap_.remove_face(f); count_vertices -= k; --count_faces; @@ -165,7 +165,7 @@ TEST_F(CMap1Test, remove_vertex) for (Dart d: darts_) { - unsigned int k = cmap_.degree(Face(d)); + unsigned int k = cmap_.codegree(Face(d)); cmap_.remove_vertex(Vertex(d)); --count_vertices; if (k == 1u) --count_faces; diff --git a/cgogn/core/tests/cmap/cmap1_topo_test.cpp b/cgogn/core/tests/cmap/cmap1_topo_test.cpp index a03ef439..bd49ba67 100644 --- a/cgogn/core/tests/cmap/cmap1_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_topo_test.cpp @@ -176,7 +176,7 @@ TEST_F(CMap1TopoTest, remove_face) if (std::rand() % 3 == 1) { Face f(d); - unsigned int k = degree(f); + unsigned int k = codegree(f); remove_face(f); count_vertices -= k; --count_faces; @@ -199,10 +199,10 @@ TEST_F(CMap1TopoTest, split_vertex_topo) for (Dart d : darts_) { - unsigned int k = degree(Face(d)); + unsigned int k = codegree(Face(d)); split_vertex_topo(d); ++count_vertices; - EXPECT_EQ(degree(Face(d)), k + 1); + EXPECT_EQ(codegree(Face(d)), k + 1); } EXPECT_EQ(nb_darts(), count_vertices); EXPECT_EQ(nb_cells(), count_vertices); @@ -221,13 +221,13 @@ TEST_F(CMap1TopoTest, remove_vertex) for (Dart d : darts_) { - unsigned int k = degree(Face(d)); + unsigned int k = codegree(Face(d)); if (k > 1) { Dart e = phi1(d); remove_vertex(Vertex(d)); --count_vertices; - EXPECT_EQ(degree(Face(e)), k - 1); + EXPECT_EQ(codegree(Face(e)), k - 1); } else { @@ -244,7 +244,7 @@ TEST_F(CMap1TopoTest, remove_vertex) /*! \brief Reversing a face reverses the order of its vertices. * The test reverses randomly generated faces. - * The number of faces and their degrees do not change and the map integrity is preserved. + * The number of faces and their codegree do not change and the map integrity is preserved. */ TEST_F(CMap1TopoTest, reverse_face_topo) { @@ -252,7 +252,7 @@ TEST_F(CMap1TopoTest, reverse_face_topo) for (Dart d : darts_) { - unsigned int k = degree(Face(d)); + unsigned int k = codegree(Face(d)); std::vector face_darts; face_darts.reserve(k); @@ -262,7 +262,7 @@ TEST_F(CMap1TopoTest, reverse_face_topo) }); reverse_face_topo(d); - EXPECT_EQ(degree(Face(d)), k); + EXPECT_EQ(codegree(Face(d)), k); d = phi1(d); foreach_dart_of_orbit(Face(d), [&] (Dart e) @@ -278,25 +278,25 @@ TEST_F(CMap1TopoTest, reverse_face_topo) EXPECT_TRUE(check_map_integrity()); } -/*! \brief The degree of a face is correctly computed. +/*! \brief The codegree of a face is correctly computed. */ -TEST_F(CMap1TopoTest, degree) +TEST_F(CMap1TopoTest, codegree) { Face f(this->add_face_topo(10u)); - EXPECT_EQ(degree(f), 10u); + EXPECT_EQ(codegree(f), 10u); } -/*! \brief The degree of a face is correctly tested. +/*! \brief The codegree of a face is correctly tested. */ -TEST_F(CMap1TopoTest, has_degree) +TEST_F(CMap1TopoTest, has_codegree) { Face f(this->add_face_topo(10u)); - EXPECT_TRUE(has_degree(f, 10u)); - EXPECT_FALSE(has_degree(f, 0u)); - EXPECT_FALSE(has_degree(f, 9u)); - EXPECT_FALSE(has_degree(f, 11u)); + EXPECT_TRUE(has_codegree(f, 10u)); + EXPECT_FALSE(has_codegree(f, 0u)); + EXPECT_FALSE(has_codegree(f, 9u)); + EXPECT_FALSE(has_codegree(f, 11u)); } #undef NB_MAX diff --git a/cgogn/core/tests/cmap/cmap2_test.cpp b/cgogn/core/tests/cmap/cmap2_test.cpp index 3b98d16f..ac47009e 100644 --- a/cgogn/core/tests/cmap/cmap2_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_test.cpp @@ -211,7 +211,7 @@ TEST_F(CMap2Test, cut_face) for (Dart d : darts_) { - if (cmap_.degree(Face(d)) > 1u) + if (cmap_.codegree(Face(d)) > 1u) { Dart e = d; // find a second dart in the face of d (distinct from d) unsigned int i = std::rand() % 10u; diff --git a/cgogn/core/tests/cmap/cmap2_topo_test.cpp b/cgogn/core/tests/cmap/cmap2_topo_test.cpp index 3e27818b..2095812a 100644 --- a/cgogn/core/tests/cmap/cmap2_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_topo_test.cpp @@ -277,17 +277,17 @@ TEST_F(CMap2TopoTest, cut_edge_topo) for (Dart d : darts_) { - unsigned int k1 = degree(Face(d)); - unsigned int k2 = degree(Face(phi2(d))); + unsigned int k1 = codegree(Face(d)); + unsigned int k2 = codegree(Face(phi2(d))); cut_edge_topo(d); if (same_cell(Face(d), Face(phi2(d)))) { - EXPECT_EQ(degree(Face(d)), k1 + 2u); + EXPECT_EQ(codegree(Face(d)), k1 + 2u); } else { - EXPECT_EQ(degree(Face(d)), k1 + 1u); - EXPECT_EQ(degree(Face(phi2(d))), k2 + 1u); + EXPECT_EQ(codegree(Face(d)), k1 + 1u); + EXPECT_EQ(codegree(Face(phi2(d))), k2 + 1u); } } EXPECT_EQ(nb_cells(), count_vertices + NB_MAX); @@ -318,7 +318,7 @@ TEST_F(CMap2TopoTest, cut_face_topo) bool boundary_face = is_boundary(dd); - unsigned int k = degree(Face(dd)); + unsigned int k = codegree(Face(dd)); if (k > 1u) { Dart e = dd; // find a second dart in the face of d (distinct from d) @@ -332,7 +332,7 @@ TEST_F(CMap2TopoTest, cut_face_topo) ++count_edges; ++count_faces; } - EXPECT_EQ(degree(Face(dd)) + degree(Face(e)), k + 2); + EXPECT_EQ(codegree(Face(dd)) + codegree(Face(e)), k + 2); } } EXPECT_EQ(nb_cells(), count_vertices); @@ -364,7 +364,7 @@ TEST_F(CMap2TopoTest, close_map) if (std::rand() % 2 == 1) { unsigned int n = std::rand() % 10u; - unsigned int k = degree(Face(d)); + unsigned int k = codegree(Face(d)); foreach_dart_of_orbit_until(Face(d), [&] (Dart e) { @@ -408,7 +408,7 @@ TEST_F(CMap2TopoTest, degree) { Face f(this->add_face_topo(10u)); - EXPECT_EQ(degree(f), 10u); + EXPECT_EQ(codegree(f), 10u); } #undef NB_MAX diff --git a/cgogn/geometry/algos/area.h b/cgogn/geometry/algos/area.h index c6483a57..2978ee0a 100644 --- a/cgogn/geometry/algos/area.h +++ b/cgogn/geometry/algos/area.h @@ -48,7 +48,7 @@ template inline typename VEC3_T::Scalar convex_face_area(const MAP& map, typename MAP::Face f, const typename MAP::template VertexAttributeHandler& position) { using Vertex = typename MAP::Vertex; - if(map.degree(f) == 3) + if (map.codegree(f) == 3) return triangle_area(map, f, position); else { diff --git a/cgogn/geometry/algos/ear_triangulation.h b/cgogn/geometry/algos/ear_triangulation.h index f6e2d384..0f377cb0 100644 --- a/cgogn/geometry/algos/ear_triangulation.h +++ b/cgogn/geometry/algos/ear_triangulation.h @@ -228,7 +228,7 @@ class EarTriangulation positions_(position), ears_(cmp_VP) { - if (map_.has_degree(f,3)) + if (map_.has_codegree(f, 3)) { face_ = f; nb_verts_ = 3; diff --git a/cgogn/geometry/algos/normal.h b/cgogn/geometry/algos/normal.h index 7ecd74fa..9c59696b 100644 --- a/cgogn/geometry/algos/normal.h +++ b/cgogn/geometry/algos/normal.h @@ -72,7 +72,7 @@ inline VEC3 newell_normal(const MAP& map, Cell f, const typename MA template inline VEC3 face_normal(const MAP& map, Cell f, const typename MAP::template VertexAttributeHandler& position) { - if (map.has_degree(f, 3)) + if (map.has_codegree(f, 3)) return triangle_normal(map, f, position); else return newell_normal(map, f, position); diff --git a/cgogn/geometry/algos/picking.h b/cgogn/geometry/algos/picking.h index 0e5132db..c7992ede 100644 --- a/cgogn/geometry/algos/picking.h +++ b/cgogn/geometry/algos/picking.h @@ -28,7 +28,6 @@ #include #include - #include #include #include @@ -43,7 +42,6 @@ namespace cgogn namespace geometry { - template inline void picking_internal_face(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector>& selected ) { @@ -52,10 +50,9 @@ inline void picking_internal_face(MAP& m, const typename MAP::template VertexAtt using Scalar = typename VEC3::Scalar; VEC3 AB = B - A ; - cgogn_message_assert(AB.squaredNorm()>0.0,"line must be defined by 2 different points"); + cgogn_message_assert(AB.squaredNorm() > 0.0, "line must be defined by 2 different points"); AB.normalize(); - // thread data using Triplet = typename std::vector>; std::vector selected_th(cgogn::get_nb_threads()); @@ -64,27 +61,27 @@ inline void picking_internal_face(MAP& m, const typename MAP::template VertexAtt m.parallel_foreach_cell([&] (Face f, unsigned int th) { VEC3 inter; - if (m.has_degree(f,3)) + if (m.has_codegree(f, 3)) { const VEC3& p1 = position[Vertex(f.dart)]; const VEC3& p2 = position[Vertex(m.phi1(f.dart))]; const VEC3& p3 = position[Vertex(m.phi1(m.phi1(f.dart)))]; - if (intersection_ray_triangle(A,AB,p1,p2,p3,&inter)) - selected_th[th].push_back(std::make_tuple(f,inter,(inter-A).squaredNorm())); + if (intersection_ray_triangle(A, AB, p1, p2, p3, &inter)) + selected_th[th].push_back(std::make_tuple(f, inter, (inter-A).squaredNorm())); } else { std::vector& ear_indices = ear_indices_th[th]; ear_indices.clear(); - cgogn::geometry::compute_ear_triangulation(m,f,position,ear_indices); - for(std::size_t i=0; i(m, f, position, ear_indices); + for(std::size_t i = 0; i < ear_indices.size(); i += 3) { const VEC3& p1 = position[ear_indices[i]]; const VEC3& p2 = position[ear_indices[i+1]]; const VEC3& p3 = position[ear_indices[i+2]]; - if (intersection_ray_triangle(A,AB,p1,p2,p3,&inter)) + if (intersection_ray_triangle(A, AB, p1, p2, p3, &inter)) { - selected_th[th].push_back(std::make_tuple(f,inter,(inter-A).squaredNorm())); + selected_th[th].push_back(std::make_tuple(f, inter, (inter-A).squaredNorm())); i = ear_indices.size(); } } @@ -92,9 +89,9 @@ inline void picking_internal_face(MAP& m, const typename MAP::template VertexAtt }); //merging thread result - for (unsigned int i=0;i bool picking_faces(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector& selected) { typename std::vector> sel; - picking_internal_face(m,position,A,B,sel); + picking_internal_face(m, position, A, B, sel); DartMarkerStore dm(m); selected.clear(); - for (auto fs: sel) + for (auto fs : sel) { selected.push_back(std::get<0>(fs)); } @@ -124,7 +121,6 @@ bool picking_faces(MAP& m, const typename MAP::template VertexAttributeHandler bool picking_vertices(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector& selected) { @@ -133,11 +129,11 @@ bool picking_vertices(MAP& m, const typename MAP::template VertexAttributeHandle using Scalar = typename VEC3::Scalar; typename std::vector> sel; - picking_internal_face(m,position,A,B,sel); + picking_internal_face(m, position, A, B, sel); DartMarkerStore dm(m); selected.clear(); - for (auto fs: sel) + for (auto fs : sel) { Scalar min_d2 = std::numeric_limits::max(); Vertex closest_vertex; @@ -145,7 +141,7 @@ bool picking_vertices(MAP& m, const typename MAP::template VertexAttributeHandle Face f = std::get<0>(fs); const VEC3& I = std::get<1>(fs); - m.foreach_incident_vertex( f, [&] (Vertex v) + m.foreach_incident_vertex(f, [&] (Vertex v) { Scalar d2 = (position[v] - I).squaredNorm(); if (d2 < min_d2) @@ -165,7 +161,6 @@ bool picking_vertices(MAP& m, const typename MAP::template VertexAttributeHandle return !selected.empty(); } - template bool picking_edges(MAP& m, const typename MAP::template VertexAttributeHandler& position, const VEC3& A, const VEC3& B, typename std::vector& selected) { @@ -175,11 +170,11 @@ bool picking_edges(MAP& m, const typename MAP::template VertexAttributeHandler> sel; - picking_internal_face(m,position,A,B,sel); + picking_internal_face(m, position, A, B, sel); DartMarkerStore dm(m); selected.clear(); - for (auto fs: sel) + for (auto fs : sel) { Scalar min_d2 = std::numeric_limits::max(); Edge closest_edge; @@ -187,11 +182,11 @@ bool picking_edges(MAP& m, const typename MAP::template VertexAttributeHandler(fs); const VEC3& I = std::get<1>(fs); - m.foreach_incident_edge( f, [&] (Edge e) + m.foreach_incident_edge(f, [&] (Edge e) { const VEC3& p_e1 = position[Vertex(e.dart)]; const VEC3& p_e2 = position[Vertex(m.phi1(e.dart))]; - Scalar d2 = squared_distance_line_point(p_e1,p_e2,I); + Scalar d2 = squared_distance_line_point(p_e1, p_e2, I); if (d2 < min_d2) { min_d2 = d2; @@ -217,11 +212,11 @@ bool picking_volumes(MAP& m, const typename MAP::template VertexAttributeHandler using Volume = typename MAP::Volume; typename std::vector> sel; - picking_internal_face(m,position,A,B,sel); + picking_internal_face(m, position, A, B, sel); selected.clear(); DartMarker dm(m); - for (auto fs: sel) + for (auto fs : sel) { Face f = std::get<0>(fs); m.foreach_incident_volume(f, [&] (Volume vo) @@ -231,15 +226,12 @@ bool picking_volumes(MAP& m, const typename MAP::template VertexAttributeHandler dm.mark_orbit(vo); selected.push_back(vo); } - }); } + return !selected.empty(); } - - - } // namespace geometry } // namespace cgogn diff --git a/cgogn/io/mesh_generation/tetgen_io.h b/cgogn/io/mesh_generation/tetgen_io.h index 41d816b7..6266b9e9 100644 --- a/cgogn/io/mesh_generation/tetgen_io.h +++ b/cgogn/io/mesh_generation/tetgen_io.h @@ -383,7 +383,7 @@ std::unique_ptr export_tetgen(CMap2& map, const typename C f->polygonlist = new tetgenio::polygon[f->numberofpolygons]; tetgenio::polygon* p = f->polygonlist; tetgenio::init(p); - p->numberofvertices = map.degree(face); + p->numberofvertices = map.codegree(face); p->vertexlist = new int[p->numberofvertices]; unsigned int j = 0u; diff --git a/cgogn/io/volume_import.h b/cgogn/io/volume_import.h index 8f8ecdbd..cb123913 100644 --- a/cgogn/io/volume_import.h +++ b/cgogn/io/volume_import.h @@ -354,8 +354,8 @@ class VolumeImport : public MeshImportGen if (!good_dart.is_nil()) //not a boundary faces { - const unsigned int degD = map.degree(Face(d)); - const unsigned int degGD = map.degree(Face(good_dart)); + const unsigned int degD = map.codegree(Face(d)); + const unsigned int degGD = map.codegree(Face(good_dart)); if(degD == degGD) // normal case : the two opposite faces have the same degree { diff --git a/cgogn/rendering/map_render.h b/cgogn/rendering/map_render.h index 06f5069a..6a5ebe9a 100644 --- a/cgogn/rendering/map_render.h +++ b/cgogn/rendering/map_render.h @@ -107,7 +107,7 @@ class MapRender // table_indices.reserve(m.get_nb_darts()/3); m.foreach_cell([&] (Face f) { - if (m.has_degree(f,3)) + if (m.has_codegree(f, 3)) { table_indices.push_back(m.get_embedding(Vertex(f.dart))); table_indices.push_back(m.get_embedding(Vertex(m.phi1(f.dart)))); @@ -115,7 +115,7 @@ class MapRender } else { - cgogn::geometry::compute_ear_triangulation(m,f,position,table_indices); + cgogn::geometry::compute_ear_triangulation(m, f, position, table_indices); } }); } @@ -201,7 +201,7 @@ void create_indices_vertices_faces(MAP& m, const typename MAP::template VertexAt m.foreach_cell([&] (Face f) { unsigned int ef = m.get_embedding(Face(f.dart)); - if (m.has_degree(f,3)) + if (m.has_codegree(f, 3)) { indices1.push_back(m.get_embedding(Vertex(f.dart))); indices1.push_back(m.get_embedding(Vertex(m.phi1(f.dart)))); diff --git a/cgogn/rendering/volume_render.h b/cgogn/rendering/volume_render.h index 9579064b..2721b599 100644 --- a/cgogn/rendering/volume_render.h +++ b/cgogn/rendering/volume_render.h @@ -128,10 +128,10 @@ void VolumeRender::update_face(MAP& m, const typename MAP::template VertexAttrib m.foreach_cell([&] (Volume v) { - VEC3 CV = geometry::centroid(m,v,position); + VEC3 CV = geometry::centroid(m, v, position); m.foreach_incident_face(v, [&] (Face f) { - if (m.has_degree(f,3)) + if (m.has_codegree(f, 3)) { const VEC3& P1 = position[Vertex(f.dart)]; const VEC3& P2 = position[Vertex(m.phi1(f.dart))]; @@ -145,7 +145,7 @@ void VolumeRender::update_face(MAP& m, const typename MAP::template VertexAttrib { ear_indices.clear(); cgogn::geometry::compute_ear_triangulation(m,f,position,ear_indices); - for(std::size_t i=0; i Date: Mon, 21 Mar 2016 14:19:32 +0100 Subject: [PATCH 371/402] ignore boundary cells in local traversals --- cgogn/core/cmap/cmap2.h | 112 ++++++++++++++----------- cgogn/core/cmap/cmap3.h | 119 ++++++++++++++++----------- cgogn/core/cmap/map_base.h | 21 +++-- cgogn/core/tests/cmap/cmap2_test.cpp | 12 +-- 4 files changed, 149 insertions(+), 115 deletions(-) diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index f203c2f1..64f2baf1 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -493,11 +493,6 @@ class CMap2_T : public CMap1_T return result; } - inline unsigned int degree(Volume v) const - { - return 1; - } - /******************************************************************************* * Orbits traversal *******************************************************************************/ @@ -670,7 +665,18 @@ class CMap2_T : public CMap1_T inline void foreach_incident_face(Vertex v, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); - foreach_dart_of_orbit(v, [&func] (Dart d) { func(Face(d)); }); + foreach_dart_of_orbit(v, [this, &func] (Dart d) + { + if (!this->is_boundary(d)) + func(Face(d)); + }); + } + + template + inline void foreach_incident_volume(Vertex v, const FUNC& func) const + { + static_assert(check_func_parameter_type(FUNC, Volume), "Wrong function cell parameter type"); + func(Volume(v.dart)); } template @@ -684,7 +690,18 @@ class CMap2_T : public CMap1_T inline void foreach_incident_face(Edge e, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); - foreach_dart_of_orbit(e, [&func] (Dart d) { func(Face(d)); }); + foreach_dart_of_orbit(e, [this, &func] (Dart d) + { + if (!this->is_boundary(d)) + func(Face(d)); + }); + } + + template + inline void foreach_incident_volume(Edge e, const FUNC& func) const + { + static_assert(check_func_parameter_type(FUNC, Volume), "Wrong function cell parameter type"); + func(Volume(e.dart)); } template @@ -702,7 +719,14 @@ class CMap2_T : public CMap1_T } template - inline void foreach_incident_vertex(Volume w, const FUNC& f) const + inline void foreach_incident_volume(Face f, const FUNC& func) const + { + static_assert(check_func_parameter_type(FUNC, Volume), "Wrong function cell parameter type"); + func(Volume(f.dart)); + } + + template + inline void foreach_incident_vertex(Volume w, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); DartMarkerStore marker(*this); @@ -711,13 +735,13 @@ class CMap2_T : public CMap1_T if (!marker.is_marked(d)) { marker.mark_orbit(Vertex(d)); - f(Vertex(d)); + func(Vertex(d)); } }); } template - inline void foreach_incident_edge(Volume w, const FUNC& f) const + inline void foreach_incident_edge(Volume w, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); DartMarkerStore marker(*this); @@ -726,47 +750,26 @@ class CMap2_T : public CMap1_T if (!marker.is_marked(d)) { marker.mark_orbit(Edge(d)); - f(Edge(d)); + func(Edge(d)); } }); } template - inline void foreach_incident_face(Volume w, const FUNC& f) const + inline void foreach_incident_face(Volume w, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); DartMarkerStore marker(*this); foreach_dart_of_orbit(w, [&] (Dart d) { - if (!marker.is_marked(d)) + if (!marker.is_marked(d) && !this->is_boundary(d)) { marker.mark_orbit(Face(d)); - f(Face(d)); + func(Face(d)); } }); } - template - inline void foreach_incident_volume(Face f, const FUNC& func) const - { - static_assert(check_func_parameter_type(FUNC, Volume), "Wrong function cell parameter type"); - func(Volume(f.dart)); - } - - template - inline void foreach_incident_volume(Edge e, const FUNC& func) const - { - static_assert(check_func_parameter_type(FUNC, Volume), "Wrong function cell parameter type"); - func(Volume(e.dart)); - } - - template - inline void foreach_incident_volume(Vertex v, const FUNC& func) const - { - static_assert(check_func_parameter_type(FUNC, Volume), "Wrong function cell parameter type"); - func(Volume(v.dart)); - } - /******************************************************************************* * Adjacence traversal *******************************************************************************/ @@ -784,13 +787,16 @@ class CMap2_T : public CMap1_T static_assert(check_func_parameter_type(FUNC, Vertex), "Wrong function cell parameter type"); foreach_dart_of_orbit(v, [this, &f] (Dart vd) { - Dart vd1 = this->phi1(vd); - this->foreach_dart_of_orbit(Face(vd), [&f, vd, vd1] (Dart fd) + if (!this->is_boundary(vd)) { - // skip Vertex v itself and its first successor around current face - if (fd != vd && fd != vd1) - f(Vertex(fd)); - }); + Dart vd1 = this->phi1(vd); + this->foreach_dart_of_orbit(Face(vd), [&f, vd, vd1] (Dart fd) + { + // skip Vertex v itself and its first successor around current face + if (fd != vd && fd != vd1) + f(Vertex(fd)); + }); + } }); } @@ -815,12 +821,15 @@ class CMap2_T : public CMap1_T static_assert(check_func_parameter_type(FUNC, Edge), "Wrong function cell parameter type"); foreach_dart_of_orbit(e, [&f, this] (Dart ed) { - this->foreach_dart_of_orbit(Face(ed), [&f, ed] (Dart fd) + if (!this->is_boundary(ed)) { - // skip Edge e itself - if (fd != ed) - f(Edge(fd)); - }); + this->foreach_dart_of_orbit(Face(ed), [&f, ed] (Dart fd) + { + // skip Edge e itself + if (fd != ed) + f(Edge(fd)); + }); + } }); } @@ -831,10 +840,10 @@ class CMap2_T : public CMap1_T foreach_dart_of_orbit(f, [this, &func] (Dart fd) { Dart fd1 = this->phi2(this->phi_1(fd)); - this->foreach_dart_of_orbit(Vertex(fd), [&func, fd, fd1] (Dart vd) + this->foreach_dart_of_orbit(Vertex(fd), [this, &func, fd, fd1] (Dart vd) { // skip Face f itself and its first successor around current vertex - if (vd != fd && vd != fd1) + if (vd != fd && vd != fd1 && !this->is_boundary(vd)) func(Face(vd)); }); }); @@ -844,7 +853,12 @@ class CMap2_T : public CMap1_T inline void foreach_adjacent_face_through_edge(Face f, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); - foreach_dart_of_orbit(f, [this, &func] (Dart d) { func(Face(this->phi2(d))); }); + foreach_dart_of_orbit(f, [this, &func] (Dart d) + { + const Dart d2 = this->phi2(d); + if (!this->is_boundary(d2)) + func(Face(d2)); + }); } }; diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index f6ab7d2a..40266c0b 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -382,11 +382,6 @@ class CMap3_T : public CMap2_T return Inherit::codegree(v); } - inline unsigned int degree(Volume v) const - { - return 2; - } - inline bool has_codegree(Face2 f, unsigned int codegree) const { return Inherit::has_codegree(f, codegree); @@ -611,7 +606,7 @@ class CMap3_T : public CMap2_T DartMarkerStore marker(*this); foreach_dart_of_orbit(v, [&] (Dart d) { - if (!marker.is_marked(d)) + if (!marker.is_marked(d) && !this->is_boundary(d)) { marker.mark_orbit(Vertex2(d)); func(Volume(d)); @@ -638,7 +633,11 @@ class CMap3_T : public CMap2_T inline void foreach_incident_volume(Edge e, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Volume), "Wrong function cell parameter type"); - foreach_dart_of_PHI23(e, [&func] (Dart d) { func(Volume(d)); }); + foreach_dart_of_PHI23(e, [this, &func] (Dart d) + { + if (!this->is_boundary(d)) + func(Volume(d)); + }); } template @@ -660,8 +659,11 @@ class CMap3_T : public CMap2_T inline void foreach_incident_volume(Face f, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Volume), "Wrong function cell parameter type"); - func(Volume(f.dart)); - func(Volume(phi3(f.dart))); + if (!this->is_boundary(f.dart)) + func(Volume(f.dart)); + const Dart d3 = phi3(f.dart); + if (!this->is_boundary(d3)) + func(Volume(d3)); } template @@ -688,14 +690,19 @@ class CMap3_T : public CMap2_T inline void foreach_incident_face(Volume v, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); - Inherit::foreach_incident_face(v, [&func] (Face2 f) + DartMarkerStore marker(*this); + foreach_dart_of_orbit(v, [&] (Dart d) { - func(Face(f.dart)); + if (!marker.is_marked(d)) + { + marker.mark_orbit(Face2(d)); + func(Face(d)); + } }); } - // redeclare CMap2 hidden functions + template inline void foreach_incident_edge(Vertex2 v, const FUNC& func) const { @@ -705,7 +712,17 @@ class CMap3_T : public CMap2_T template inline void foreach_incident_face(Vertex2 v, const FUNC& func) const { - Inherit::foreach_incident_face(v,func); + static_assert(check_func_parameter_type(FUNC, Face2), "Wrong function cell parameter type"); + foreach_dart_of_orbit(v, [this, &func] (Dart d) + { + func(Face2(d)); + }); + } + + template + inline void foreach_incident_volume(Vertex2 v, const FUNC& func) const + { + Inherit::foreach_incident_volume(v,func); } template @@ -717,7 +734,17 @@ class CMap3_T : public CMap2_T template inline void foreach_incident_face(Edge2 e, const FUNC& func) const { - Inherit::foreach_incident_face(e,func); + static_assert(check_func_parameter_type(FUNC, Face2), "Wrong function cell parameter type"); + foreach_dart_of_orbit(e, [this, &func] (Dart d) + { + func(Face2(d)); + }); + } + + template + inline void foreach_incident_volume(Edge2 e, const FUNC& func) const + { + Inherit::foreach_incident_volume(e,func); } template @@ -738,19 +765,6 @@ class CMap3_T : public CMap2_T Inherit::foreach_incident_volume(f,func); } - template - inline void foreach_incident_volume(Edge2 e, const FUNC& func) const - { - Inherit::foreach_incident_volume(e,func); - } - - template - inline void foreach_incident_volume(Vertex2 v, const FUNC& func) const - { - Inherit::foreach_incident_volume(v,func); - } - - /******************************************************************************* * Adjacence traversal *******************************************************************************/ @@ -775,7 +789,7 @@ class CMap3_T : public CMap2_T { foreach_incident_vertex(inc_face, [&] (Vertex vertex_of_face) { - if (!marker_vertex.is_marked(vertex_of_face)) + if (!marker_vertex.is_marked(vertex_of_face.dart)) { marker_vertex.mark_orbit(vertex_of_face); func(vertex_of_face); @@ -794,7 +808,7 @@ class CMap3_T : public CMap2_T { foreach_incident_vertex(inc_vol, [&] (Vertex inc_vert) { - if (!marker_vertex.is_marked(inc_vert)) + if (!marker_vertex.is_marked(inc_vert.dart)) { marker_vertex.mark_orbit(inc_vert); func(inc_vert); @@ -827,7 +841,7 @@ class CMap3_T : public CMap2_T { foreach_incident_edge(inc_face, [&] (Edge inc_edge) { - if (!marker_edge.is_marked(inc_edge)) + if (!marker_edge.is_marked(inc_edge.dart)) { marker_edge.mark_orbit(inc_edge); func(inc_edge); @@ -846,7 +860,7 @@ class CMap3_T : public CMap2_T { foreach_incident_edge(inc_vol, [&] (Edge inc_edge) { - if (!marker_edge.is_marked(inc_edge)) + if (!marker_edge.is_marked(inc_edge.dart)) { marker_edge.mark_orbit(inc_edge); func(inc_edge); @@ -865,7 +879,7 @@ class CMap3_T : public CMap2_T { foreach_incident_face(f, [&](Face inc_fac) { - if (!marker_face.is_marked(inc_fac)) + if (!marker_face.is_marked(inc_fac.dart)) { marker_face.mark_orbit(inc_fac); func(inc_fac); @@ -894,23 +908,29 @@ class CMap3_T : public CMap2_T static_assert(check_func_parameter_type(FUNC, Face), "Wrong function cell parameter type"); DartMarker marker_face(*this); marker_face.mark_orbit(f); - foreach_incident_face(Volume(f.dart), [&] (Face inc_face) + if (!this->is_boundary(f.dart)) { - if (!marker_face.is_marked(inc_face)) + foreach_incident_face(Volume(f.dart), [&] (Face inc_face) { - marker_face.mark_orbit((inc_face)); - func(inc_face); - } - }); - - foreach_incident_face(Volume(phi3(f)), [&] (Face inc_face) + if (!marker_face.is_marked(inc_face.dart)) + { + marker_face.mark_orbit((inc_face)); + func(inc_face); + } + }); + } + const Dart d3 = phi3(f.dart); + if (!this->is_boundary(d3)) { - if (!marker_face.is_marked(inc_face)) + foreach_incident_face(Volume(d3), [&] (Face inc_face) { - marker_face.mark_orbit((inc_face)); - func(inc_face); - } - }); + if (!marker_face.is_marked(inc_face.dart)) + { + marker_face.mark_orbit((inc_face)); + func(inc_face); + } + }); + } } template @@ -923,7 +943,7 @@ class CMap3_T : public CMap2_T { foreach_incident_volume(inc_vert, [&](Volume inc_vol) { - if (!marker_volume.is_marked(inc_vol)) + if (!marker_volume.is_marked(inc_vol.dart) && !this->is_boundary(inc_vol.dart)) { marker_volume.mark_orbit(inc_vol); func(inc_vol); @@ -942,7 +962,7 @@ class CMap3_T : public CMap2_T { foreach_incident_volume(inc_edge, [&] (Volume inc_vol) { - if (!marker_volume.is_marked(inc_vol)) + if (!marker_volume.is_marked(inc_vol.dart) && !this->is_boundary(inc_vol.dart)) { marker_volume.mark_orbit(inc_vol); func(inc_vol); @@ -961,7 +981,7 @@ class CMap3_T : public CMap2_T { foreach_incident_volume(inc_face, [&] (Volume inc_vol) { - if (!marker_volume.is_marked(inc_vol)) + if (!marker_volume.is_marked(inc_vol.dart) && !this->is_boundary(inc_vol.dart)) { marker_volume.mark_orbit(inc_vol); func(inc_vol); @@ -970,7 +990,8 @@ class CMap3_T : public CMap2_T }); } - //redeclare CMap2 hidden functions + // redeclare CMap2 hidden functions + template inline void foreach_adjacent_vertex_through_edge(Vertex2 v, const FUNC& func) const { diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 2a9c992c..0b5216e7 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -340,10 +340,10 @@ class MapBase : public MapBaseData this->embeddings_[ORBIT] = ca; // initialize all darts indices to EMBNULL for this ORBIT - foreach_dart_nomask([this, ca] (Dart d) { (*ca)[d.index] = EMBNULL; }); + foreach_dart_nomask([ca] (Dart d) { (*ca)[d.index] = EMBNULL; }); // initialize the indices of the existing orbits - foreach_cell_nomask([this] (Cell c) { new_orbit_embedding(c); }); + foreach_cell_nomask([this] (Cell c) { this->new_orbit_embedding(c); }); cgogn_assert(check_map_integrity()); } @@ -353,7 +353,8 @@ class MapBase : public MapBaseData { using CellType = Cell; const unsigned int emb = add_attribute_element(); - to_concrete()->foreach_dart_of_orbit(c, [this, emb] (Dart d) { + to_concrete()->foreach_dart_of_orbit(c, [this, emb] (Dart d) + { this->template set_embedding(d, emb); }); return emb; @@ -373,14 +374,12 @@ class MapBase : public MapBaseData AttributeHandler counter = add_attribute("__tmp_counter"); for (unsigned int& i : counter) i = 0; - foreach_cell_nomask( - [this, &counter] (Cell c) - { - if (counter[c] > 0) - this->new_orbit_embedding(c); - counter[c]++; - } - ); + foreach_cell_nomask([this, &counter] (Cell c) + { + if (counter[c] > 0) + this->new_orbit_embedding(c); + counter[c]++; + }); remove_attribute(counter); } diff --git a/cgogn/core/tests/cmap/cmap2_test.cpp b/cgogn/core/tests/cmap/cmap2_test.cpp index ac47009e..c8fe298c 100644 --- a/cgogn/core/tests/cmap/cmap2_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_test.cpp @@ -133,28 +133,28 @@ class CMap2Test : public ::testing::Test } } // Close the map (remove remaining boundary) - cmap_.foreach_dart_nomask( [&] (Dart d) + cmap_.foreach_dart_nomask([&] (Dart d) { if (cmap_.phi2(d) == d) mbuild.close_hole_topo(d); }); // Embed the map - cmap_.foreach_dart_nomask( [&] (Dart d) + cmap_.foreach_dart_nomask([&] (Dart d) { mbuild.new_orbit_embedding(CDart(d)); }); - cmap_.foreach_cell_nomask( [&] (Vertex v) + cmap_.foreach_cell_nomask([&] (Vertex v) { mbuild.new_orbit_embedding(v); }); - cmap_.foreach_cell_nomask( [&] (Edge e) + cmap_.foreach_cell_nomask([&] (Edge e) { mbuild.new_orbit_embedding(e); }); - cmap_.foreach_cell_nomask( [&] (Face f) + cmap_.foreach_cell_nomask([&] (Face f) { mbuild.new_orbit_embedding(f); }); - cmap_.foreach_cell_nomask( [&] (Volume w) + cmap_.foreach_cell_nomask([&] (Volume w) { mbuild.new_orbit_embedding(w); }); From 14c6ae377ab99e4b7d91e36da64dbd55aa08d35e Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Mon, 21 Mar 2016 14:25:31 +0100 Subject: [PATCH 372/402] update some degree / codegree methods to ignore boundary cells --- cgogn/core/cmap/cmap2.h | 5 ++++- cgogn/core/cmap/cmap3.h | 9 +++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 64f2baf1..21de8852 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -473,7 +473,10 @@ class CMap2_T : public CMap1_T inline unsigned int degree(Edge e) const { - return 2; + if (this->is_boundary(e.dart) || this->is_boundary(phi2(e.dart))) + return 1; + else + return 2; } inline unsigned int codegree(Face f) const diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 40266c0b..93a3d2bc 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -374,12 +374,17 @@ class CMap3_T : public CMap2_T inline unsigned int degree(Face f) const { - return 2; + if (this->is_boundary(f.dart) || this->is_boundary(phi3(f.dart))) + return 1; + else + return 2; } inline unsigned int codegree(Volume v) const { - return Inherit::codegree(v); + unsigned int result = 0; + foreach_incident_face(v, [&result] (Face) { ++result; }); + return result; } inline bool has_codegree(Face2 f, unsigned int codegree) const From fb304852101004db588f471e6e5a4ad5bb5409bd Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Mon, 21 Mar 2016 14:41:27 +0100 Subject: [PATCH 373/402] bug fix for QOGLViewer pivot point update --- thirdparty/libQGLViewer/QOGLViewer/qoglviewer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/thirdparty/libQGLViewer/QOGLViewer/qoglviewer.cpp b/thirdparty/libQGLViewer/QOGLViewer/qoglviewer.cpp index 8d6464ee..1793afcf 100644 --- a/thirdparty/libQGLViewer/QOGLViewer/qoglviewer.cpp +++ b/thirdparty/libQGLViewer/QOGLViewer/qoglviewer.cpp @@ -958,6 +958,7 @@ void QOGLViewer::performClickAction(ClickAction ca, const QMouseEvent* const e) update(); break; case RAP_FROM_PIXEL : + makeCurrent(); if (! camera()->setPivotPointFromPixel(e->pos())) camera()->setPivotPoint(sceneCenter()); setVisualHintsMask(1); From 0efbdf25e418c6c535af2b0e818cbbcff53475d8 Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Mon, 21 Mar 2016 15:15:46 +0100 Subject: [PATCH 374/402] fix foreach_dart_of_PHI21_PHI31_until --- cgogn/core/cmap/cmap3.h | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 93a3d2bc..af694e4d 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -492,16 +492,18 @@ class CMap3_T : public CMap2_T marker.mark(d); for(unsigned int i = 0; i < marked_darts->size(); ++i) { - if (!f((*marked_darts)[i])) + const Dart curr_dart = marked_darts->operator [](i); + if (!f(curr_dart)) break; - Dart d2 = this->phi2((*marked_darts)[i]); - Dart d21 = this->phi1(d2); // turn in volume - Dart d23 = phi3(d2); // change volume - if(!marker.is_marked(d21)) - marker.mark(d21); - if(!marker.is_marked(d23)) - marker.mark(d23); + const Dart d_1 = this->phi_1(curr_dart); + const Dart d2_1 = this->phi2(d_1); // turn in volume + const Dart d3_1 = phi3(d_1); // change volume + + if(!marker.is_marked(d2_1)) + marker.mark(d2_1); + if(!marker.is_marked(d3_1)) + marker.mark(d3_1); } } From aa528bf0fbcd777a11b42abcfd26c6d5038c4df8 Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Mon, 21 Mar 2016 15:26:56 +0100 Subject: [PATCH 375/402] remove boundary tests on 2-dimensional local traverals in CMap3 --- cgogn/core/cmap/cmap3.h | 60 ++++++++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 13 deletions(-) diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index af694e4d..1fd4a985 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -713,7 +713,7 @@ class CMap3_T : public CMap2_T template inline void foreach_incident_edge(Vertex2 v, const FUNC& func) const { - Inherit::foreach_incident_edge(v,func); + Inherit::foreach_incident_edge(v, func); } template @@ -729,13 +729,13 @@ class CMap3_T : public CMap2_T template inline void foreach_incident_volume(Vertex2 v, const FUNC& func) const { - Inherit::foreach_incident_volume(v,func); + Inherit::foreach_incident_volume(v, func); } template inline void foreach_incident_vertex(Edge2 e, const FUNC& func) const { - Inherit::foreach_incident_vertex(e,func); + Inherit::foreach_incident_vertex(e, func); } template @@ -751,25 +751,25 @@ class CMap3_T : public CMap2_T template inline void foreach_incident_volume(Edge2 e, const FUNC& func) const { - Inherit::foreach_incident_volume(e,func); + Inherit::foreach_incident_volume(e, func); } template inline void foreach_incident_vertex(Face2 f, const FUNC& func) const { - Inherit::foreach_incident_vertex(f,func); + Inherit::foreach_incident_vertex(f, func); } template inline void foreach_incident_edge(Face2 f, const FUNC& func) const { - Inherit::foreach_incident_edge(f,func); + Inherit::foreach_incident_edge(f, func); } template inline void foreach_incident_volume(Face2 f, const FUNC& func) const { - Inherit::foreach_incident_volume(f,func); + Inherit::foreach_incident_volume(f, func); } /******************************************************************************* @@ -1002,37 +1002,71 @@ class CMap3_T : public CMap2_T template inline void foreach_adjacent_vertex_through_edge(Vertex2 v, const FUNC& func) const { - Inherit::foreach_adjacent_vertex_through_edge(v,func); + Inherit::foreach_adjacent_vertex_through_edge(v, func); } template inline void foreach_adjacent_vertex_through_face(Vertex2 v, const FUNC& func) const { - Inherit::foreach_adjacent_vertex_through_face(v,func); + static_assert(check_func_parameter_type(FUNC, Vertex2), "Wrong function cell parameter type"); + foreach_dart_of_orbit(v, [this, &f] (Dart vd) + { + Dart vd1 = this->phi1(vd); + this->foreach_dart_of_orbit(Face2(vd), [&f, vd, vd1] (Dart fd) + { + // skip Vertex2 v itself and its first successor around current face + if (fd != vd && fd != vd1) + f(Vertex2(fd)); + }); + }); } template inline void foreach_adjacent_edge_through_vertex(Edge2 e, const FUNC& func) const { - Inherit::foreach_adjacent_edge_through_vertex(e,func); + Inherit::foreach_adjacent_edge_through_vertex(e, func); } template inline void foreach_adjacent_edge_through_face(Edge2 e, const FUNC& func) const { - Inherit::foreach_adjacent_edge_through_face(e,func); + static_assert(check_func_parameter_type(FUNC, Edge2), "Wrong function cell parameter type"); + foreach_dart_of_orbit(e, [&f, this] (Dart ed) + { + this->foreach_dart_of_orbit(Face2(ed), [&f, ed] (Dart fd) + { + // skip Edge2 e itself + if (fd != ed) + f(Edge2(fd)); + }); + }); } template inline void foreach_adjacent_face_through_vertex(Face2 f, const FUNC& func) const { - Inherit::foreach_adjacent_face_through_vertex(f,func); + static_assert(check_func_parameter_type(FUNC, Face2), "Wrong function cell parameter type"); + foreach_dart_of_orbit(f, [this, &func] (Dart fd) + { + Dart fd1 = this->phi2(this->phi_1(fd)); + this->foreach_dart_of_orbit(Vertex2(fd), [this, &func, fd, fd1] (Dart vd) + { + // skip Face2 f itself and its first successor around current vertex + if (vd != fd && vd != fd1) + func(Face2(vd)); + }); + }); } template inline void foreach_adjacent_face_through_edge(Face2 f, const FUNC& func) const { - Inherit::foreach_adjacent_face_through_vertex(f,func); + static_assert(check_func_parameter_type(FUNC, Face2), "Wrong function cell parameter type"); + foreach_dart_of_orbit(f, [this, &func] (Dart d) + { + const Dart d2 = this->phi2(d); + func(Face2(d2)); + }); } }; From 96eafbc815f8d4573bdec7b4daf9aab63d524591 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Mon, 21 Mar 2016 19:04:35 +0100 Subject: [PATCH 376/402] numerics types --- .../multithreading/bench_multithreading.cpp | 17 +- cgogn/core/basic/cell.h | 4 +- cgogn/core/basic/cell_marker.h | 8 +- cgogn/core/basic/dart.h | 9 +- cgogn/core/cmap/attribute_handler.h | 16 +- cgogn/core/cmap/cmap1.h | 12 +- cgogn/core/cmap/cmap2.h | 12 +- cgogn/core/cmap/cmap2_builder.h | 6 +- cgogn/core/cmap/cmap3.h | 28 +-- cgogn/core/cmap/cmap3_builder.h | 14 +- cgogn/core/cmap/map_base.h | 130 ++++++------- cgogn/core/cmap/map_base_data.h | 28 +-- cgogn/core/cmap/map_traits.h | 2 +- cgogn/core/container/chunk_array.cpp | 2 +- cgogn/core/container/chunk_array.h | 174 +++++++++--------- .../core/container/chunk_array_container.cpp | 2 +- cgogn/core/container/chunk_array_container.h | 153 +++++++-------- cgogn/core/container/chunk_array_factory.h | 6 +- cgogn/core/container/chunk_array_gen.h | 22 +-- cgogn/core/container/chunk_stack.cpp | 2 +- cgogn/core/container/chunk_stack.h | 18 +- .../chunk_array/bench_chunk_array.cpp | 52 +++--- .../core/examples/chunk_array/chunk_array.cpp | 61 +++--- .../examples/chunk_array/chunk_array2.cpp | 12 +- cgogn/core/examples/map/map.cpp | 6 +- cgogn/core/tests/basic/cell_test.cpp | 7 +- cgogn/core/tests/basic/dart_test.cpp | 4 +- cgogn/core/tests/cmap/cmap0_test.cpp | 6 +- cgogn/core/tests/cmap/cmap0_topo_test.cpp | 6 +- cgogn/core/tests/cmap/cmap1_test.cpp | 24 +-- cgogn/core/tests/cmap/cmap1_topo_test.cpp | 38 ++-- cgogn/core/tests/cmap/cmap2_test.cpp | 20 +- cgogn/core/tests/cmap/cmap2_topo_test.cpp | 50 ++--- cgogn/core/tests/utils/name_types_test.cpp | 6 +- cgogn/core/utils/buffers.h | 8 +- cgogn/core/utils/definitions.h | 33 ++++ cgogn/core/utils/serialization.cpp | 12 +- cgogn/core/utils/serialization.h | 20 +- cgogn/core/utils/thread.cpp | 8 +- cgogn/core/utils/thread.h | 20 +- cgogn/core/utils/thread_barrier.h | 10 +- cgogn/core/utils/thread_pool.cpp | 4 +- cgogn/core/utils/thread_pool.h | 12 +- cgogn/geometry/algos/centroid.h | 2 +- cgogn/geometry/algos/ear_triangulation.h | 10 +- cgogn/geometry/algos/normal.h | 6 +- cgogn/geometry/algos/picking.h | 8 +- cgogn/geometry/functions/intersection.h | 6 +- cgogn/geometry/tests/algos/algos_test.cpp | 4 +- cgogn/geometry/types/bounding_box.h | 16 +- cgogn/geometry/types/geometry_traits.h | 6 +- cgogn/io/data_io.h | 44 ++--- cgogn/io/examples/cmap2_import.cpp | 40 ++-- cgogn/io/examples/cmap3_import.cpp | 13 +- cgogn/io/io_utils.cpp | 28 +-- cgogn/io/io_utils.h | 6 +- cgogn/io/lm6_io.h | 2 +- cgogn/io/map_export.h | 106 +++++------ .../examples/map3_from_surface.cpp | 13 +- cgogn/io/mesh_generation/tetgen_io.h | 28 +-- cgogn/io/obj_io.h | 20 +- cgogn/io/off_io.h | 58 +++--- cgogn/io/ply_io.h | 14 +- cgogn/io/surface_import.h | 36 ++-- cgogn/io/volume_import.h | 50 ++--- cgogn/io/vtk_io.h | 108 +++++------ .../cph/attribute_handler_cph.h | 24 +-- cgogn/multiresolution/cph/cph2.h | 20 +- cgogn/multiresolution/cph/cph3.h | 12 +- cgogn/multiresolution/cph/cph_base.h | 22 +-- cgogn/multiresolution/cph/ihcmap2.h | 32 ++-- cgogn/multiresolution/cph/ihcmap2_adaptive.h | 72 ++++---- cgogn/multiresolution/cph/ihcmap2_regular.h | 24 +-- cgogn/multiresolution/cph/ihcmap3.h | 20 +- cgogn/multiresolution/mrcmap/mr_base.h | 18 +- cgogn/rendering/drawer.cpp | 6 +- cgogn/rendering/drawer.h | 16 +- cgogn/rendering/examples/picking_viewer.cpp | 10 +- cgogn/rendering/examples/viewer_per_face.cpp | 8 +- cgogn/rendering/examples/viewer_topo3.cpp | 3 +- cgogn/rendering/map_render.h | 26 +-- cgogn/rendering/shaders/shader_bold_line.cpp | 4 +- cgogn/rendering/shaders/shader_bold_line.h | 6 +- .../shaders/shader_color_per_vertex.cpp | 2 +- .../shaders/shader_color_per_vertex.h | 2 +- .../shaders/shader_explode_volumes.cpp | 2 +- .../shaders/shader_explode_volumes.h | 10 +- .../shaders/shader_explode_volumes_line.cpp | 2 +- .../shaders/shader_explode_volumes_line.h | 8 +- cgogn/rendering/shaders/shader_flat.cpp | 2 +- cgogn/rendering/shaders/shader_flat.h | 10 +- cgogn/rendering/shaders/shader_phong.cpp | 2 +- cgogn/rendering/shaders/shader_phong.h | 16 +- .../rendering/shaders/shader_point_sprite.cpp | 2 +- cgogn/rendering/shaders/shader_point_sprite.h | 10 +- cgogn/rendering/shaders/shader_program.h | 23 +-- .../rendering/shaders/shader_round_point.cpp | 2 +- cgogn/rendering/shaders/shader_round_point.h | 6 +- .../rendering/shaders/shader_simple_color.cpp | 2 +- cgogn/rendering/shaders/shader_simple_color.h | 4 +- .../shaders/shader_vector_per_vertex.cpp | 2 +- .../shaders/shader_vector_per_vertex.h | 6 +- cgogn/rendering/shaders/vbo.h | 58 +++--- cgogn/rendering/topo_render.cpp | 4 +- cgogn/rendering/topo_render.h | 38 ++-- cgogn/rendering/volume_render.h | 14 +- 106 files changed, 1159 insertions(+), 1099 deletions(-) diff --git a/benchmarks/multithreading/bench_multithreading.cpp b/benchmarks/multithreading/bench_multithreading.cpp index 7114e5cf..515788f1 100644 --- a/benchmarks/multithreading/bench_multithreading.cpp +++ b/benchmarks/multithreading/bench_multithreading.cpp @@ -32,6 +32,9 @@ #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) +using namespace cgogn::numerics; + + using Map2 = cgogn::CMap2; Map2 bench_map; @@ -41,7 +44,7 @@ const cgogn::Orbit VERTEX = Vertex::ORBIT; using Face = Map2::Face; const cgogn::Orbit FACE = Face::ORBIT; -const unsigned int ITERATIONS = 1u; +const uint32 ITERATIONS = 1u; //using Vec3 = Eigen::Vector3d; using Vec3 = cgogn::geometry::Vec_T>; @@ -64,16 +67,16 @@ static void BENCH_Dart_count_multi_threaded(benchmark::State& state) { while (state.KeepRunning()) { - unsigned int nb_darts_2 = 0u; - std::vector nb_darts_per_thread(cgogn::get_nb_threads()+2); + uint32 nb_darts_2 = 0u; + std::vector nb_darts_per_thread(cgogn::get_nb_threads()+2); for (auto& n : nb_darts_per_thread) n = 0u; nb_darts_2 = 0u; - bench_map.parallel_foreach_dart([&nb_darts_per_thread] (cgogn::Dart, unsigned int thread_index) + bench_map.parallel_foreach_dart([&nb_darts_per_thread] (cgogn::Dart, uint32 thread_index) { nb_darts_per_thread[thread_index]++; }); - for (unsigned int n : nb_darts_per_thread) + for (uint32 n : nb_darts_per_thread) nb_darts_2 += n; cgogn_assert(nb_darts_2 == bench_map.nb_darts()); @@ -111,7 +114,7 @@ static void BENCH_faces_normals_multi_threaded(benchmark::State& state) cgogn_assert(face_normal_mt.is_valid()); state.ResumeTiming(); - bench_map.template parallel_foreach_cell([&] (Face f,unsigned int) + bench_map.template parallel_foreach_cell([&] (Face f,uint32) { face_normal_mt[f] = cgogn::geometry::face_normal(bench_map, f, vertex_position); }); @@ -169,7 +172,7 @@ static void BENCH_vertices_normals_multi_threaded(benchmark::State& state) cgogn_assert(vertices_normal_mt.is_valid()); state.ResumeTiming(); - bench_map.template parallel_foreach_cell([&] (Vertex v, unsigned int) + bench_map.template parallel_foreach_cell([&] (Vertex v, uint32) { vertices_normal_mt[v] = cgogn::geometry::vertex_normal(bench_map, v, vertex_position); }); diff --git a/cgogn/core/basic/cell.h b/cgogn/core/basic/cell.h index f8e37164..aa20df40 100644 --- a/cgogn/core/basic/cell.h +++ b/cgogn/core/basic/cell.h @@ -38,7 +38,7 @@ namespace cgogn { -enum Orbit: unsigned int +enum Orbit: uint32 { DART = 0, PHI1, @@ -52,7 +52,7 @@ enum Orbit: unsigned int static const std::size_t NB_ORBITS = Orbit::PHI21_PHI31 + 1; -static const unsigned int EMBNULL = UINT_MAX; +static const uint32 EMBNULL = UINT_MAX; inline std::string orbit_name(Orbit orbit) { diff --git a/cgogn/core/basic/cell_marker.h b/cgogn/core/basic/cell_marker.h index df77d972..d0597354 100644 --- a/cgogn/core/basic/cell_marker.h +++ b/cgogn/core/basic/cell_marker.h @@ -38,7 +38,7 @@ class CellMarker_T public: - static const unsigned int CHUNKSIZE = MAP::CHUNKSIZE; + static const uint32 CHUNKSIZE = MAP::CHUNKSIZE; using Self = CellMarker_T; using Map = MAP; using ChunkArrayBool = ChunkArray; @@ -137,7 +137,7 @@ class CellMarkerStore : public CellMarker_T protected: - std::vector* marked_cells_; + std::vector* marked_cells_; public: @@ -168,12 +168,12 @@ class CellMarkerStore : public CellMarker_T inline void unmark_all() { cgogn_message_assert(this->mark_attribute_ != nullptr, "CellMarkerStore has null mark attribute"); - for (unsigned int i : *(this->marked_cells_)) + for (uint32 i : *(this->marked_cells_)) this->mark_attribute_->set_false(i); marked_cells_->clear(); } - inline const std::vector* get_marked_cells() const + inline const std::vector* get_marked_cells() const { return marked_cells_; } diff --git a/cgogn/core/basic/dart.h b/cgogn/core/basic/dart.h index 8b682073..225b2559 100644 --- a/cgogn/core/basic/dart.h +++ b/cgogn/core/basic/dart.h @@ -27,6 +27,7 @@ #include #include #include +#include /** * \file cgogn/core/basic/dart.h @@ -40,13 +41,13 @@ namespace cgogn */ struct Dart { - // MSVC doesn't support std::numeric_limits::max() when declaring static const variables - static const unsigned int INVALID_INDEX = UINT_MAX; + // MSVC doesn't support std::numeric_limits::max() when declaring static const variables + static const uint32 INVALID_INDEX = UINT_MAX; /** * \brief the value of a dart. */ - unsigned int index; + uint32 index; /** * \brief Creates a new nil Dart @@ -64,7 +65,7 @@ struct Dart * * \param[in] v the value of the new dart */ - inline explicit Dart(unsigned int v) : index(v) + inline explicit Dart(uint32 v) : index(v) {} /** diff --git a/cgogn/core/cmap/attribute_handler.h b/cgogn/core/cmap/attribute_handler.h index df404942..2bdb2247 100644 --- a/cgogn/core/cmap/attribute_handler.h +++ b/cgogn/core/cmap/attribute_handler.h @@ -114,7 +114,7 @@ class AttributeHandlerOrbit : public AttributeHandlerGen using Self = AttributeHandlerOrbit; using MapData = typename Inherit::MapData; - static const unsigned int CHUNKSIZE = MapData::CHUNKSIZE; + static const uint32 CHUNKSIZE = MapData::CHUNKSIZE; static const Orbit orbit_value = ORBIT; template @@ -124,7 +124,7 @@ class AttributeHandlerOrbit : public AttributeHandlerGen protected: - ChunkArrayContainer* chunk_array_cont_; + ChunkArrayContainer* chunk_array_cont_; public: @@ -382,7 +382,7 @@ class AttributeHandler : public AttributeHandlerOrbit * @param i * @return */ - inline T& operator[](unsigned int i) + inline T& operator[](uint32 i) { cgogn_message_assert(is_valid(), "Invalid AttributeHandler"); return chunk_array_->operator[](i); @@ -393,7 +393,7 @@ class AttributeHandler : public AttributeHandlerOrbit * @param i * @return */ - inline const T& operator[](unsigned int i) const + inline const T& operator[](uint32 i) const { cgogn_message_assert(is_valid(), "Invalid AttributeHandler"); return chunk_array_->operator[](i); @@ -404,9 +404,9 @@ class AttributeHandler : public AttributeHandlerOrbit { public: const AttributeHandler* const ah_ptr_; - unsigned int index_; + uint32 index_; - inline const_iterator(const AttributeHandler* ah, unsigned int i) : + inline const_iterator(const AttributeHandler* ah, uint32 i) : ah_ptr_(ah), index_(i) {} @@ -456,9 +456,9 @@ class AttributeHandler : public AttributeHandlerOrbit { public: AttributeHandler* const ah_ptr_; - unsigned int index_; + uint32 index_; - inline iterator(AttributeHandler* ah, unsigned int i) : + inline iterator(AttributeHandler* ah, uint32 i) : ah_ptr_(ah), index_(i) {} diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 770bcbdc..bc31a090 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -208,7 +208,7 @@ class CMap1_T : public CMap0_T * \param size : the number of darts in the built face * \return A dart of the built face */ - inline Dart add_face_topo(unsigned int size) + inline Dart add_face_topo(uint32 size) { cgogn_message_assert(size > 0u, "Cannot create an empty face"); @@ -216,7 +216,7 @@ class CMap1_T : public CMap0_T std::cerr << "Warning: attempt to create an empty face results in a single dart" << std::endl; Dart d = this->add_dart(); - for (unsigned int i = 1u; i < size; ++i) + for (uint32 i = 1u; i < size; ++i) split_vertex_topo(d); return d; } @@ -229,7 +229,7 @@ class CMap1_T : public CMap0_T * \return The built face. If the map has Vertex or Face attributes, * the new inserted cells are automatically embedded on new attribute elements. */ - Face add_face(unsigned int size) + Face add_face(uint32 size) { CGOGN_CHECK_CONCRETE_TYPE; @@ -346,15 +346,15 @@ class CMap1_T : public CMap0_T public: - inline unsigned int degree(Face f) const + inline uint32 degree(Face f) const { return this->nb_darts_of_orbit(f); } - inline bool has_degree(Face f, unsigned int degree) const + inline bool has_degree(Face f, uint32 degree) const { Dart it = f.dart ; - for (unsigned int i=1;i * Two 1-face are built. The first one is the returned face, * the second is a boundary face that closes the map. */ - Dart add_face_topo(unsigned int size) + Dart add_face_topo(uint32 size) { Dart d = Inherit::add_face_topo(size); Dart e = Inherit::add_face_topo(size); @@ -243,7 +243,7 @@ class CMap2_T : public CMap1_T * More precisely : * - a Face attribute is created, if needed, for the new face. */ - Face add_face(unsigned int size) + Face add_face(uint32 size) { CGOGN_CHECK_CONCRETE_TYPE; @@ -457,12 +457,12 @@ class CMap2_T : public CMap1_T } } - inline unsigned int degree(Face f) const + inline uint32 degree(Face f) const { return Inherit::degree(f); } - inline unsigned int degree(Vertex v) const + inline uint32 degree(Vertex v) const { return this->nb_darts_of_orbit(v); } @@ -498,7 +498,7 @@ class CMap2_T : public CMap1_T visited_faces->push_back(d); // Start with the face of d // For every face added to the list - for(unsigned int i = 0; i < visited_faces->size(); ++i) + for(uint32 i = 0; i < visited_faces->size(); ++i) { Dart e = (*visited_faces)[i]; if (!marker.is_marked(e)) // Face has not been visited yet @@ -570,7 +570,7 @@ class CMap2_T : public CMap1_T visited_faces->push_back(d); // Start with the face of d // For every face added to the list - for(unsigned int i = 0; i < visited_faces->size(); ++i) + for(uint32 i = 0; i < visited_faces->size(); ++i) { Dart e = (*visited_faces)[i]; if (!marker.is_marked(e)) // Face has not been visited yet diff --git a/cgogn/core/cmap/cmap2_builder.h b/cgogn/core/cmap/cmap2_builder.h index 8ee807ca..6ae4c5da 100644 --- a/cgogn/core/cmap/cmap2_builder.h +++ b/cgogn/core/cmap/cmap2_builder.h @@ -68,7 +68,7 @@ class CMap2Builder_T } template - inline void set_embedding(Dart d, unsigned int emb) + inline void set_embedding(Dart d, uint32 emb) { map_.template set_embedding(d, emb); } @@ -89,7 +89,7 @@ class CMap2Builder_T map_.phi2_unsew(d); } - inline Dart add_face_topo_parent(unsigned int nb_edges) + inline Dart add_face_topo_parent(uint32 nb_edges) { return map_.CMap2::Inherit::add_face_topo(nb_edges); } @@ -172,7 +172,7 @@ class CMap2Builder_T if (map_.template is_embedded()) { - const unsigned int idx = map_.get_embedding(Volume(d)); + const uint32 idx = map_.get_embedding(Volume(d)); map_.foreach_dart_of_orbit(f, [this, idx] (Dart it) { map_.template set_embedding(it, idx); diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 604216a1..9c8ae3d8 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -218,7 +218,7 @@ class CMap3_T : public CMap2_T * @param n, the number of edges of the base * @return a dart from the base */ - inline Dart add_pyramid_topo(unsigned int n) + inline Dart add_pyramid_topo(uint32 n) { cgogn_message_assert( n >= 3u ,"The base must have at least 3 edges."); @@ -226,11 +226,11 @@ class CMap3_T : public CMap2_T m_tableVertDarts.reserve(n); // creation of triangles around circumference and storing vertices - for (unsigned int i = 0u; i < n; ++i) + for (uint32 i = 0u; i < n; ++i) m_tableVertDarts.push_back(this->Inherit::Inherit::add_face_topo(3u)); // sewing the triangles - for (unsigned int i = 0u; i < n-1u; ++i) + for (uint32 i = 0u; i < n-1u; ++i) { const Dart d = this->phi_1(m_tableVertDarts[i]); const Dart e = this->phi1(m_tableVertDarts[i+1]); @@ -243,7 +243,7 @@ class CMap3_T : public CMap2_T // sewing the bottom face Dart base = this->Inherit::Inherit::add_face_topo(n); const Dart dres = base; - for(unsigned int i = 0u; i < n; ++i) + for(uint32 i = 0u; i < n; ++i) { this->phi2_sew(m_tableVertDarts[i], base); base = this->phi1(base); @@ -258,22 +258,22 @@ class CMap3_T : public CMap2_T * @param n, the number of edges of the base * @return a dart from the base */ - Dart add_prism_topo(unsigned int n) + Dart add_prism_topo(uint32 n) { cgogn_message_assert( n >= 3u ,"The base must have at least 3 edges."); std::vector m_tableVertDarts; m_tableVertDarts.reserve(n*2u); // creation of quads around circunference and storing vertices - for (unsigned int i = 0u; i < n; ++i) + for (uint32 i = 0u; i < n; ++i) m_tableVertDarts.push_back(this->Inherit::Inherit::add_face_topo(4u)); // storing a dart from the vertex pointed by phi1(phi1(d)) - for (unsigned int i = 0u; i < n; ++i) + for (uint32 i = 0u; i < n; ++i) m_tableVertDarts.push_back(this->phi1(this->phi1(m_tableVertDarts[i]))); // sewing the quads - for (unsigned int i = 0u; i < n-1u; ++i) + for (uint32 i = 0u; i < n-1u; ++i) { const Dart d = this->phi_1(m_tableVertDarts[i]); const Dart e = this->phi1(m_tableVertDarts[i+1u]); @@ -286,7 +286,7 @@ class CMap3_T : public CMap2_T Dart top = this->Inherit::Inherit::add_face_topo(n); Dart bottom = this->Inherit::Inherit::add_face_topo(n); const Dart dres = top; - for(unsigned int i = 0u; i < n; ++i) + for(uint32 i = 0u; i < n; ++i) { this->phi2_sew(m_tableVertDarts[i], top); this->phi2_sew(m_tableVertDarts[n+i], bottom); @@ -320,17 +320,17 @@ class CMap3_T : public CMap2_T public: - inline unsigned int degree(Face f) const + inline uint32 degree(Face f) const { return Inherit::degree(Face2(f.dart)); } - inline bool has_degree(Face f, unsigned int degree) const + inline bool has_degree(Face f, uint32 degree) const { return Inherit::has_degree(Face2(f.dart), degree); } - inline bool has_degree(Face2 f, unsigned int degree) const + inline bool has_degree(Face2 f, uint32 degree) const { return Inherit::has_degree(f, degree); } @@ -348,7 +348,7 @@ class CMap3_T : public CMap2_T const std::vector* marked_darts = marker.get_marked_darts(); marker.mark(d); - for(unsigned int i = 0; i < marked_darts->size(); ++i) + for(uint32 i = 0; i < marked_darts->size(); ++i) { const Dart curr_dart = marked_darts->operator [](i); f(curr_dart); @@ -428,7 +428,7 @@ class CMap3_T : public CMap2_T const std::vector* marked_darts = marker.get_marked_darts(); marker.mark(d); - for(unsigned int i = 0; i < marked_darts->size(); ++i) + for(uint32 i = 0; i < marked_darts->size(); ++i) { if (!f((*marked_darts)[i])) break; diff --git a/cgogn/core/cmap/cmap3_builder.h b/cgogn/core/cmap/cmap3_builder.h index dde7abfb..4453f4a5 100644 --- a/cgogn/core/cmap/cmap3_builder.h +++ b/cgogn/core/cmap/cmap3_builder.h @@ -72,7 +72,7 @@ class CMap3Builder_T map_.attributes_[ORBIT].swap(cac); } - inline void init_parent_vertex_embedding(Dart d, unsigned int emb) + inline void init_parent_vertex_embedding(Dart d, uint32 emb) { map_.foreach_dart_of_PHI21(d, [&] (Dart dit) { @@ -100,17 +100,17 @@ class CMap3Builder_T return map_.phi3_unsew(d); } - inline Dart add_face_topo(unsigned int nb_edges) + inline Dart add_face_topo(uint32 nb_edges) { return map_.add_face_topo(nb_edges); } - inline Dart add_prism_topo(unsigned int nb_edges) + inline Dart add_prism_topo(uint32 nb_edges) { return map_.add_prism_topo(nb_edges); } - inline Dart add_pyramid_topo(unsigned int nb_edges) + inline Dart add_pyramid_topo(uint32 nb_edges) { return map_.add_pyramid_topo(nb_edges); } @@ -121,7 +121,7 @@ class CMap3Builder_T } template - inline void set_embedding(Dart d, unsigned int emb) + inline void set_embedding(Dart d, uint32 emb) { map_.template set_embedding(d, emb); } @@ -139,10 +139,10 @@ class CMap3Builder_T visitedFaces.push_back(d); // Start with the face of d dmarker.mark_orbit(Face2(d)); - unsigned int count = 0u; + uint32 count = 0u; // For every face added to the list - for(unsigned int i = 0u; i < visitedFaces.size(); ++i) + for(uint32 i = 0u; i < visitedFaces.size(); ++i) { Dart it = visitedFaces[i]; Dart f = it; diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 2a9c992c..a55494f4 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -96,7 +96,7 @@ class MapBase : public MapBaseData { this->topology_.clear_attributes(); - for (unsigned int i = 0u; i < NB_ORBITS; ++i) + for (uint32 i = 0u; i < NB_ORBITS; ++i) this->attributes_[i].clear_attributes(); } @@ -155,11 +155,11 @@ class MapBase : public MapBaseData * Container elements management *******************************************************************************/ - inline unsigned int add_topology_element() + inline uint32 add_topology_element() { - const unsigned int idx = this->topology_.template insert_lines(); + const uint32 idx = this->topology_.template insert_lines(); this->topology_.init_markers_of_line(idx); - for (unsigned int orbit = 0u; orbit < NB_ORBITS; ++orbit) + for (uint32 orbit = 0u; orbit < NB_ORBITS; ++orbit) { if (this->embeddings_[orbit]) (*this->embeddings_[orbit])[idx] = EMBNULL; @@ -176,15 +176,15 @@ class MapBase : public MapBaseData * * \param int [description] */ - inline void remove_topology_element(unsigned int index) + inline void remove_topology_element(uint32 index) { this->topology_.template remove_lines(index); - for(unsigned int orbit = 0; orbit < NB_ORBITS; ++orbit) + for(uint32 orbit = 0; orbit < NB_ORBITS; ++orbit) { if(this->embeddings_[orbit]) { - unsigned int emb = (*this->embeddings_[orbit])[index]; + uint32 emb = (*this->embeddings_[orbit])[index]; if (emb != EMBNULL) this->attributes_[orbit].unref_line(emb); } @@ -192,17 +192,17 @@ class MapBase : public MapBaseData } template - inline unsigned int add_attribute_element() + inline uint32 add_attribute_element() { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); - unsigned int idx = this->attributes_[ORBIT].template insert_lines<1>(); + uint32 idx = this->attributes_[ORBIT].template insert_lines<1>(); this->attributes_[ORBIT].init_markers_of_line(idx); return idx; } template - inline void remove_attribute_element(unsigned int index) + inline void remove_attribute_element(uint32 index) { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); @@ -336,7 +336,7 @@ class MapBase : public MapBaseData oss << "EMB_" << orbit_name(ORBIT); // create the topology attribute that stores the orbit indices - ChunkArray* ca = this->topology_.template add_attribute(oss.str()); + ChunkArray* ca = this->topology_.template add_attribute(oss.str()); this->embeddings_[ORBIT] = ca; // initialize all darts indices to EMBNULL for this ORBIT @@ -349,10 +349,10 @@ class MapBase : public MapBaseData } template - inline unsigned int new_orbit_embedding(Cell c) + inline uint32 new_orbit_embedding(Cell c) { using CellType = Cell; - const unsigned int emb = add_attribute_element(); + const uint32 emb = add_attribute_element(); to_concrete()->foreach_dart_of_orbit(c, [this, emb] (Dart d) { this->template set_embedding(d, emb); }); @@ -370,8 +370,8 @@ class MapBase : public MapBaseData static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); cgogn_message_assert(this->template is_embedded(), "Invalid parameter: orbit not embedded"); - AttributeHandler counter = add_attribute("__tmp_counter"); - for (unsigned int& i : counter) i = 0; + AttributeHandler counter = add_attribute("__tmp_counter"); + for (uint32& i : counter) i = 0; foreach_cell_nomask( [this, &counter] (Cell c) @@ -401,20 +401,20 @@ class MapBase : public MapBaseData cgogn_message_assert(this->template is_embedded(), "Invalid parameter: orbit not embedded"); const ConcreteMap* cmap = to_concrete(); - AttributeHandler counter = add_attribute("__tmp_marker"); + AttributeHandler counter = add_attribute("__tmp_marker"); bool result = true; - const typename Inherit::template ChunkArrayContainer& container = this->attributes_[ORBIT]; + const typename Inherit::template ChunkArrayContainer& container = this->attributes_[ORBIT]; // a marker is initialized to false for each "used" index of the container - for (unsigned int i = container.begin(), end = container.end(); i != end; container.next(i)) + for (uint32 i = container.begin(), end = container.end(); i != end; container.next(i)) counter[i] = 0; // Check that the indexation of cells is correct foreach_cell_until_nomask( [&] (CellType c) { - unsigned int idx = this->get_embedding(c); + uint32 idx = this->get_embedding(c); // check used indices are valid if (idx == EMBNULL) { @@ -446,7 +446,7 @@ class MapBase : public MapBaseData // check that all cells present in the attribute handler are used if (result) { - for (unsigned int i = container.begin(), end = container.end(); i != end; container.next(i)) + for (uint32 i = container.begin(), end = container.end(); i != end; container.next(i)) { if (counter[i] == 0) { @@ -562,7 +562,7 @@ class MapBase : public MapBaseData * \brief return the number of darts in the map * @return */ - unsigned int nb_darts() const + uint32 nb_darts() const { return this->topology_.size(); } @@ -571,37 +571,37 @@ class MapBase : public MapBaseData * \brief return the number of cells of the given orbit in the map */ template - unsigned int nb_cells() const + uint32 nb_cells() const { - unsigned int result = 0; + uint32 result = 0; foreach_cell([&result] (Cell) { ++result; }); return result; } - unsigned int nb_boundary_cells() const + uint32 nb_boundary_cells() const { - unsigned int result = 0; + uint32 result = 0; foreach_boundary_cell([&result] (typename ConcreteMap::Boundary) { ++result; }); return result; } template - unsigned int nb_cells_nomask() const + uint32 nb_cells_nomask() const { if (this->template is_embedded()) return this->attributes_[ORBIT].size(); else { - unsigned int result = 0; + uint32 result = 0; foreach_cell_nomask([&result] (Cell) { ++result; }); return result; } } template - unsigned int nb_cells(const MASK& mask) const + uint32 nb_cells(const MASK& mask) const { - unsigned int result = 0; + uint32 result = 0; foreach_cell([&result] (Cell) { ++result; }, mask); return result; } @@ -610,9 +610,9 @@ class MapBase : public MapBaseData * \brief return the number of darts in the given cell */ template - unsigned int nb_darts_of_orbit(Cell c) const + uint32 nb_darts_of_orbit(Cell c) const { - unsigned int result = 0u; + uint32 result = 0u; to_concrete()->foreach_dart_of_orbit(c, [&result] (Dart) { ++result; }); return result; } @@ -737,11 +737,11 @@ class MapBase : public MapBaseData inline void parallel_foreach_dart(const FUNC& f, const MASK& mask) const { static_assert(check_func_ith_parameter_type(FUNC, 0, Dart), "Wrong function first parameter type"); - static_assert(check_func_ith_parameter_type(FUNC, 1, unsigned int), "Wrong function second parameter type"); + static_assert(check_func_ith_parameter_type(FUNC, 1, uint32), "Wrong function second parameter type"); static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); - using Future = std::future::type>; + using Future = std::future::type>; using VecDarts = std::vector; ThreadPool* thread_pool = cgogn::get_thread_pool(); @@ -761,9 +761,9 @@ class MapBase : public MapBaseData while (it.index < last.index) { - for (unsigned int i = 0u; i < 2u; ++i) + for (uint32 i = 0u; i < 2u; ++i) { - for (unsigned int j = 0u; j < nb_threads_pool && it.index < last.index; ++j) + for (uint32 j = 0u; j < nb_threads_pool && it.index < last.index; ++j) { dart_buffers[i].push_back(dbuffs->get_buffer()); cgogn_assert(dart_buffers[i].size() <= nb_threads_pool); @@ -775,14 +775,14 @@ class MapBase : public MapBaseData next(it, mask); } - futures[i].push_back(thread_pool->enqueue([&darts, &f] (unsigned int th_id) + futures[i].push_back(thread_pool->enqueue([&darts, &f] (uint32 th_id) { for (auto d : darts) f(d, th_id); })); } - const unsigned int id = (i+1u) % 2u; + const uint32 id = (i+1u) % 2u; for (auto& fu : futures[id]) fu.wait(); @@ -920,7 +920,7 @@ class MapBase : public MapBaseData template inline void parallel_foreach_cell(const FUNC& f, const MASK& mask) const { - static_assert(check_func_ith_parameter_type(FUNC, 1, unsigned int), "Wrong function second parameter type"); + static_assert(check_func_ith_parameter_type(FUNC, 1, uint32), "Wrong function second parameter type"); static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); @@ -1030,7 +1030,7 @@ class MapBase : public MapBaseData static const Orbit ORBIT = CellType::ORBIT; using VecCell = std::vector; - using Future = std::future::type>; + using Future = std::future::type>; ThreadPool* thread_pool = cgogn::get_thread_pool(); const std::size_t nb_threads_pool = thread_pool->get_nb_threads(); @@ -1048,8 +1048,8 @@ class MapBase : public MapBaseData Dart it = begin(mask); Dart last = end(); - unsigned int i = 0u; // buffer id (0/1) - unsigned int j = 0u; // thread id (0..nb_threads_pool) + uint32 i = 0u; // buffer id (0/1) + uint32 j = 0u; // thread id (0..nb_threads_pool) while (it.index < last.index) { // fill buffer @@ -1068,7 +1068,7 @@ class MapBase : public MapBaseData next(it, mask); } //launch thread - futures[i].push_back(thread_pool->enqueue([&cells, &f] (unsigned int th_id) + futures[i].push_back(thread_pool->enqueue([&cells, &f] (uint32 th_id) { for (auto c : cells) f(c, th_id); @@ -1077,7 +1077,7 @@ class MapBase : public MapBaseData if (++j == nb_threads_pool) { // again from 0 & change buffer j = 0; - const unsigned int id = (i+1u) % 2u; + const uint32 id = (i+1u) % 2u; for (auto& fu : futures[id]) fu.wait(); for (auto& b : cells_buffers[id]) @@ -1123,7 +1123,7 @@ class MapBase : public MapBaseData static const Orbit ORBIT = CellType::ORBIT; using VecCell = std::vector; - using Future = std::future::type>; + using Future = std::future::type>; ThreadPool* thread_pool = cgogn::get_thread_pool(); const std::size_t nb_threads_pool = thread_pool->get_nb_threads(); @@ -1141,8 +1141,8 @@ class MapBase : public MapBaseData Dart it = begin(mask); Dart last = end(); - unsigned int i = 0u; // buffer id (0/1) - unsigned int j = 0u; // thread id (0..nb_threads_pool) + uint32 i = 0u; // buffer id (0/1) + uint32 j = 0u; // thread id (0..nb_threads_pool) while (it.index < last.index) { // fill buffer @@ -1161,7 +1161,7 @@ class MapBase : public MapBaseData next(it, mask); } // launch thread - futures[i].push_back(thread_pool->enqueue([&cells, &f] (unsigned int th_id) + futures[i].push_back(thread_pool->enqueue([&cells, &f] (uint32 th_id) { for (auto c : cells) f(c, th_id); @@ -1170,7 +1170,7 @@ class MapBase : public MapBaseData if (++j == nb_threads_pool) { // again from 0 & change buffer j = 0; - const unsigned int id = (i+1u) % 2u; + const uint32 id = (i+1u) % 2u; for (auto& fu : futures[id]) fu.wait(); for (auto& b : cells_buffers[id]) @@ -1200,8 +1200,8 @@ class MapBase : public MapBaseData const auto& cache = *(this->global_topo_cache_[ORBIT]); const auto& attr = this->attributes_[ORBIT]; - unsigned int it = attr.begin(); - const unsigned int last = attr.end(); + uint32 it = attr.begin(); + const uint32 last = attr.end(); // find first valid dart in the topo cache while (it != last && !mask(cache[it])) { @@ -1226,7 +1226,7 @@ class MapBase : public MapBaseData static const Orbit ORBIT = CellType::ORBIT; using VecCell = std::vector; - using Future = std::future::type>; + using Future = std::future::type>; ThreadPool* thread_pool = cgogn::get_thread_pool(); const std::size_t nb_threads_pool = thread_pool->get_nb_threads(); @@ -1238,31 +1238,31 @@ class MapBase : public MapBaseData const auto& cache = *(this->global_topo_cache_[ORBIT]); const auto& attr = this->attributes_[ORBIT]; - unsigned int it = attr.begin(); - const unsigned int last = attr.end(); + uint32 it = attr.begin(); + const uint32 last = attr.end(); // find first valid dart in the topo cache while (it != last && !mask(cache[it])) { attr.next(it); } - unsigned int nbc = PARALLEL_BUFFER_SIZE; + uint32 nbc = PARALLEL_BUFFER_SIZE; // do block of PARALLEL_BUFFER_SIZE only if nb cells is huge else just divide - if ( (static_cast(last - it) < 16*nb_threads_pool*PARALLEL_BUFFER_SIZE ) - && (static_cast(last - it) > nb_threads_pool)) - nbc = static_cast((last - it) / nb_threads_pool); + if ( (static_cast(last - it) < 16*nb_threads_pool*PARALLEL_BUFFER_SIZE ) + && (static_cast(last - it) > nb_threads_pool)) + nbc = static_cast((last - it) / nb_threads_pool); - unsigned int local_end = std::min(it+nbc, last); + uint32 local_end = std::min(it+nbc, last); - unsigned int i = 0; // used buffered futures 0/1 - unsigned int j = 0; // thread num + uint32 i = 0; // used buffered futures 0/1 + uint32 j = 0; // thread num while (it < last) { - futures[i].push_back(thread_pool->enqueue([&cache, &attr, &mask, it, local_end, &f] (unsigned int th_id) + futures[i].push_back(thread_pool->enqueue([&cache, &attr, &mask, it, local_end, &f] (uint32 th_id) { - unsigned int loc_it = it; + uint32 loc_it = it; while (loc_it < local_end) { f(CellType(cache[loc_it]), th_id); @@ -1278,7 +1278,7 @@ class MapBase : public MapBaseData if (++j == nb_threads_pool) // change thread { // again from 0 & change buffer j = 0; - const unsigned int id = (i+1u) % 2u; + const uint32 id = (i+1u) % 2u; for (auto& fu : futures[id]) fu.wait(); futures[id].clear(); @@ -1339,8 +1339,8 @@ class MapBase : public MapBaseData const auto& cache = *(this->global_topo_cache_[ORBIT]); const auto& attr = this->attributes_[ORBIT]; - unsigned int it = attr.begin(); - const unsigned int last = attr.end(); + uint32 it = attr.begin(); + const uint32 last = attr.end(); Dart d = cache[it]; // find first valid dart in the topo cache while (it != last && !mask(d)) diff --git a/cgogn/core/cmap/map_base_data.h b/cgogn/core/cmap/map_base_data.h index c1c14cf2..79d054b6 100644 --- a/cgogn/core/cmap/map_base_data.h +++ b/cgogn/core/cmap/map_base_data.h @@ -98,8 +98,8 @@ class MapBaseData : public MapGen using Inherit = MapGen; using Self = MapBaseData; - static const unsigned int CHUNKSIZE = MAP_TRAITS::CHUNK_SIZE; - static const unsigned int NB_UNKNOWN_THREADS = 4u; + static const uint32 CHUNKSIZE = MAP_TRAITS::CHUNK_SIZE; + static const uint32 NB_UNKNOWN_THREADS = 4u; template friend class AttributeHandlerOrbit; template friend class AttributeHandler; @@ -115,10 +115,10 @@ class MapBaseData : public MapGen ChunkArrayContainer topology_; /// per orbit attributes - std::array, NB_ORBITS> attributes_; + std::array, NB_ORBITS> attributes_; /// embedding indices shortcuts - std::array*, NB_ORBITS> embeddings_; + std::array*, NB_ORBITS> embeddings_; /// boundary marker shortcut ChunkArray* boundary_marker_; @@ -148,21 +148,21 @@ class MapBaseData : public MapGen ChunkArrayFactory::reset(); init_CA_factory = false; } - for (unsigned int i = 0; i < NB_ORBITS; ++i) + for (uint32 i = 0; i < NB_ORBITS; ++i) { mark_attributes_[i].reserve(NB_UNKNOWN_THREADS + 2u*MAX_NB_THREADS); mark_attributes_[i].resize(NB_UNKNOWN_THREADS + MAX_NB_THREADS); embeddings_[i] = nullptr; global_topo_cache_[i] = nullptr; - for (unsigned int j = 0; j < NB_UNKNOWN_THREADS + MAX_NB_THREADS; ++j) + for (uint32 j = 0; j < NB_UNKNOWN_THREADS + MAX_NB_THREADS; ++j) mark_attributes_[i][j].reserve(8); } mark_attributes_topology_.reserve(NB_UNKNOWN_THREADS + 2u*MAX_NB_THREADS); mark_attributes_topology_.resize(NB_UNKNOWN_THREADS + MAX_NB_THREADS); - for (unsigned int i = 0; i < MAX_NB_THREADS; ++i) + for (uint32 i = 0; i < MAX_NB_THREADS; ++i) mark_attributes_topology_[i].reserve(8); boundary_marker_ = topology_.add_marker_attribute(); @@ -189,7 +189,7 @@ class MapBaseData : public MapGen *******************************************************************************/ template - inline const ChunkArrayContainer& get_attribute_container() const + inline const ChunkArrayContainer& get_attribute_container() const { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); return attributes_[ORBIT]; @@ -198,7 +198,7 @@ class MapBaseData : public MapGen protected: template - inline ChunkArrayContainer& get_attribute_container() + inline ChunkArrayContainer& get_attribute_container() { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); return attributes_[ORBIT]; @@ -259,7 +259,7 @@ class MapBaseData : public MapGen } template - inline unsigned int get_embedding(Cell c) const + inline uint32 get_embedding(Cell c) const { static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); cgogn_message_assert(is_embedded(), "Invalid parameter: orbit not embedded"); @@ -271,14 +271,14 @@ class MapBaseData : public MapGen protected: template - inline void set_embedding(Dart d, unsigned int emb) + inline void set_embedding(Dart d, uint32 emb) { static const Orbit ORBIT = CellType::ORBIT; static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); cgogn_message_assert(is_embedded(), "Invalid parameter: orbit not embedded"); cgogn_message_assert(emb != EMBNULL,"cannot set an embedding to EMBNULL."); - const unsigned int old = (*embeddings_[ORBIT])[d.index]; + const uint32 old = (*embeddings_[ORBIT])[d.index]; // ref_line() is done before unref_line() to avoid deleting the indexed line if old == emb attributes_[ORBIT].ref_line(emb); // ref the new emb @@ -303,9 +303,9 @@ class MapBaseData : public MapGen * Thread management *******************************************************************************/ - inline unsigned int add_unknown_thread() const + inline uint32 add_unknown_thread() const { - static unsigned int index = 0u; + static uint32 index = 0u; const std::thread::id& th_id = std::this_thread::get_id(); std::cerr << "WARNING: registration of an unknown thread (id :" << th_id << ") in the map." << std::endl; std::cerr << "Data can be lost. Please use add_thread and remove_thread interface." << std::endl; diff --git a/cgogn/core/cmap/map_traits.h b/cgogn/core/cmap/map_traits.h index d466d3bc..cc923e44 100644 --- a/cgogn/core/cmap/map_traits.h +++ b/cgogn/core/cmap/map_traits.h @@ -32,7 +32,7 @@ namespace cgogn struct DefaultMapTraits { - static const unsigned int CHUNK_SIZE = DEFAULT_CHUNK_SIZE; + static const uint32 CHUNK_SIZE = DEFAULT_CHUNK_SIZE; }; } // namespace cgogn diff --git a/cgogn/core/container/chunk_array.cpp b/cgogn/core/container/chunk_array.cpp index b4767598..68b5a5db 100644 --- a/cgogn/core/container/chunk_array.cpp +++ b/cgogn/core/container/chunk_array.cpp @@ -31,7 +31,7 @@ namespace cgogn { template class CGOGN_CORE_API ChunkArray; -template class CGOGN_CORE_API ChunkArray; +template class CGOGN_CORE_API ChunkArray; template class CGOGN_CORE_API ChunkArray; template class CGOGN_CORE_API ChunkArray>; template class CGOGN_CORE_API ChunkArray>; diff --git a/cgogn/core/container/chunk_array.h b/cgogn/core/container/chunk_array.h index 5f582a52..8a80b420 100644 --- a/cgogn/core/container/chunk_array.h +++ b/cgogn/core/container/chunk_array.h @@ -44,7 +44,7 @@ namespace cgogn * @tparam CHUNKSIZE size of each chunk (in T, not in bytes!), must be a power of 2 >=32 * @tparam T type of stored data */ -template +template class ChunkArray : public ChunkArrayGen { public: @@ -110,7 +110,7 @@ class ChunkArray : public ChunkArrayGen * @brief set number of chunks * @param nbc number of chunks */ - void set_nb_chunks(unsigned int nbc) override + void set_nb_chunks(uint32 nbc) override { if (nbc >= table_data_.size()) { @@ -129,18 +129,18 @@ class ChunkArray : public ChunkArrayGen * @brief get the number of chunks of the array * @return the number of chunks */ - unsigned int get_nb_chunks() const override + uint32 get_nb_chunks() const override { - return static_cast(table_data_.size()); + return static_cast(table_data_.size()); } /** * @brief get the capacity of the array * @return number of allocated lines */ - unsigned int capacity() const override + uint32 capacity() const override { - return static_cast(table_data_.size())*CHUNKSIZE; + return static_cast(table_data_.size())*CHUNKSIZE; } /** @@ -159,7 +159,7 @@ class ChunkArray : public ChunkArrayGen * @param byte_chunk_size filled with CHUNKSIZE*sizeof(T) * @return addr.size() */ - unsigned int get_chunks_pointers(std::vector& addr, unsigned int& byte_chunk_size) const override + uint32 get_chunks_pointers(std::vector& addr, uint32& byte_chunk_size) const override { byte_chunk_size = CHUNKSIZE * sizeof(T); @@ -169,14 +169,14 @@ class ChunkArray : public ChunkArrayGen for (typename std::vector::const_iterator it = table_data_.begin(); it != table_data_.end(); ++it) addr.push_back(*it); - return static_cast(addr.size()); + return static_cast(addr.size()); } /** * @brief initialize an element (overwrite with T()) * @param id index of the element */ - void init_element(unsigned int id) override + void init_element(uint32 id) override { table_data_[id / CHUNKSIZE][id % CHUNKSIZE] = T(); } @@ -186,7 +186,7 @@ class ChunkArray : public ChunkArrayGen * @param dst destination index * @param src source index */ - void copy_element(unsigned int dst, unsigned int src) override + void copy_element(uint32 dst, uint32 src) override { table_data_[dst / CHUNKSIZE][dst % CHUNKSIZE] = table_data_[src / CHUNKSIZE][src % CHUNKSIZE]; } @@ -196,7 +196,7 @@ class ChunkArray : public ChunkArrayGen * @param idx1 first element index * @param idx2 second element index */ - void swap_elements(unsigned int idx1, unsigned int idx2) override + void swap_elements(uint32 idx1, uint32 idx2) override { // small workaround to avoid difficulties with std::swap when _GLIBCXX_DEBUG is defined. #ifndef _GLIBCXX_DEBUG @@ -210,25 +210,25 @@ class ChunkArray : public ChunkArrayGen #endif // _GLIBCXX_DEBUG } -// void save(std::ostream& fs, unsigned int nb_lines) const +// void save(std::ostream& fs, uint32 nb_lines) const // { -// unsigned int nbs[3]; -// nbs[0] = (unsigned int)(table_data_.size()); +// uint32 nbs[3]; +// nbs[0] = (uint32)(table_data_.size()); // nbs[1] = nb_lines; // nbs[2] = CHUNKSIZE*sizeof(T); // assert(nb_lines/CHUNKSIZE <= table_data_.size()); // // TODO: if (nb_lines == 0) nb_lines = CHUNKSIZE*table_data_.size(); ?? -// fs.write(reinterpret_cast(nbs),3*sizeof(unsigned int)); +// fs.write(reinterpret_cast(nbs),3*sizeof(uint32)); // // no data -> finished // if (nbs[0] == 0) // return; -// unsigned int nbca = nbs[0]-1; +// uint32 nbca = nbs[0]-1; // // save data chunks except last -// for(unsigned int i=0; i(table_data_[i]),CHUNKSIZE*sizeof(T)); // } @@ -240,8 +240,8 @@ class ChunkArray : public ChunkArrayGen // bool load(std::istream& fs) // { -// unsigned int nbs[3]; -// fs.read(reinterpret_cast(nbs), 3*sizeof(unsigned int)); +// uint32 nbs[3]; +// fs.read(reinterpret_cast(nbs), 3*sizeof(uint32)); // if (nbs[2] != CHUNKSIZE*sizeof(T)) // { @@ -256,18 +256,18 @@ class ChunkArray : public ChunkArrayGen // return true; // // load data chunks except last -// unsigned int nbca = nbs[0]-1; -// for(unsigned int i = 0; i < nbca; ++i) +// uint32 nbca = nbs[0]-1; +// for(uint32 i = 0; i < nbca; ++i) // fs.read(reinterpret_cast(table_data_[i]),CHUNKSIZE*sizeof(T)); // // load last chunk -// unsigned int nbl = nbs[1] - CHUNKSIZE*nbca; +// uint32 nbl = nbs[1] - CHUNKSIZE*nbca; // fs.read(reinterpret_cast(table_data_[nbca]),std::streamsize(nbl*sizeof(T))); // return true; // } - void save(std::ostream& fs, unsigned int nb_lines) const override + void save(std::ostream& fs, uint32 nb_lines) const override { cgogn_assert(fs.good()); cgogn_assert(nb_lines / CHUNKSIZE <= get_nb_chunks()); @@ -281,7 +281,7 @@ class ChunkArray : public ChunkArrayGen return; } - unsigned int nbc = get_nb_chunks() - 1u; + uint32 nbc = get_nb_chunks() - 1u; // nb of lines of last chunk const unsigned nb = nb_lines - nbc*CHUNKSIZE; @@ -293,7 +293,7 @@ class ChunkArray : public ChunkArrayGen } else { - for(unsigned int i = 0u; i < nbc; ++i) + for(uint32 i = 0u; i < nbc; ++i) chunk_bytes += serialization::data_length(table_data_[i], CHUNKSIZE); } chunk_bytes +=serialization::data_length(table_data_[nbc], nb); @@ -305,7 +305,7 @@ class ChunkArray : public ChunkArrayGen // save data chunks except last - for(unsigned int i = 0u; i < nbc; ++i) + for(uint32 i = 0u; i < nbc; ++i) { serialization::save(fs, table_data_[i], CHUNKSIZE); } @@ -323,14 +323,14 @@ class ChunkArray : public ChunkArrayGen std::size_t chunk_bytes; serialization::load(fs, &chunk_bytes, 1); - unsigned int nb_lines; + uint32 nb_lines; serialization::load(fs, &nb_lines, 1); // no data -> finished if (nb_lines == 0) return true; // compute number of chunks - unsigned int nbc = nb_lines / CHUNKSIZE; + uint32 nbc = nb_lines / CHUNKSIZE; if (nb_lines % CHUNKSIZE != 0) nbc++; @@ -338,11 +338,11 @@ class ChunkArray : public ChunkArrayGen // load data chunks except last nbc--; - for(unsigned int i = 0u; i < nbc; ++i) + for(uint32 i = 0u; i < nbc; ++i) serialization::load(fs, table_data_[i], CHUNKSIZE); // load last incomplete chunk - const unsigned int nb = nb_lines - nbc*CHUNKSIZE; + const uint32 nb = nb_lines - nbc*CHUNKSIZE; serialization::load(fs, table_data_[nbc], nb); cgogn_assert(fs.good()); @@ -354,7 +354,7 @@ class ChunkArray : public ChunkArrayGen * @param i index of element to access * @return ref to the element */ - inline T& operator[](unsigned int i) + inline T& operator[](uint32 i) { cgogn_assert(i / CHUNKSIZE < table_data_.size()); return table_data_[i / CHUNKSIZE][i % CHUNKSIZE]; @@ -365,7 +365,7 @@ class ChunkArray : public ChunkArrayGen * @param i index of element to access * @return const ref to the element */ - inline const T& operator[](unsigned int i) const + inline const T& operator[](uint32 i) const { cgogn_assert(i / CHUNKSIZE < table_data_.size()); return table_data_[i / CHUNKSIZE][i % CHUNKSIZE]; @@ -376,7 +376,7 @@ class ChunkArray : public ChunkArrayGen * @param i index of element to set * @param v value */ - inline void set_value(unsigned int i, const T& v) + inline void set_value(uint32 i, const T& v) { cgogn_assert(i / CHUNKSIZE < table_data_.size()); table_data_[i / CHUNKSIZE][i % CHUNKSIZE] = v; @@ -386,7 +386,7 @@ class ChunkArray : public ChunkArrayGen { for(T* chunk : table_data_) { - for(unsigned int i=0; i /** * @brief specialized version of ChunkArray for bool data. One bit per bool */ -template +template class ChunkArray : public ChunkArrayGen { public: using Inherit = ChunkArrayGen; using Self = ChunkArray; - using value_type = unsigned int; + using value_type = uint32; protected: /// vector of block pointers - std::vector table_data_; + std::vector table_data_; public: @@ -447,14 +447,14 @@ class ChunkArray : public ChunkArrayGen void add_chunk() override { // adding the empty parentheses for default-initialization - table_data_.push_back(new unsigned int[CHUNKSIZE/32u]()); + table_data_.push_back(new uint32[CHUNKSIZE/32u]()); } /** * @brief set number of chunks * @param nbc number of chunks */ - void set_nb_chunks(unsigned int nbc) override + void set_nb_chunks(uint32 nbc) override { if (nbc >= table_data_.size()) { @@ -473,18 +473,18 @@ class ChunkArray : public ChunkArrayGen * @brief get the number of chunks of the array * @return the number of chunks */ - unsigned int get_nb_chunks() const override + uint32 get_nb_chunks() const override { - return static_cast(table_data_.size()); + return static_cast(table_data_.size()); } /** * @brief get the capacity of the array * @return number of allocated lines */ - unsigned int capacity() const override + uint32 capacity() const override { - return static_cast(table_data_.size())*CHUNKSIZE/32u; + return static_cast(table_data_.size())*CHUNKSIZE/32u; } /** @@ -503,24 +503,24 @@ class ChunkArray : public ChunkArrayGen * @param byte_block_size filled with CHUNKSIZE*sizeof(T) * @return addr.size() */ - inline unsigned int get_chunks_pointers(std::vector& addr, unsigned int& byte_block_size) const override + inline uint32 get_chunks_pointers(std::vector& addr, uint32& byte_block_size) const override { byte_block_size = CHUNKSIZE / 8u; addr.reserve(table_data_.size()); addr.clear(); - for (typename std::vector::const_iterator it = table_data_.begin(); it != table_data_.end(); ++it) + for (typename std::vector::const_iterator it = table_data_.begin(); it != table_data_.end(); ++it) addr.push_back(*it); - return static_cast(addr.size()); + return static_cast(addr.size()); } /** * @brief initialize an element (overwrite with T()) * @param id index of the element */ - inline void init_element(unsigned int id) override + inline void init_element(uint32 id) override { set_false(id); } @@ -530,7 +530,7 @@ class ChunkArray : public ChunkArrayGen * @param dst destination index * @param src source index */ - inline void copy_element(unsigned int dst, unsigned int src) override + inline void copy_element(uint32 dst, uint32 src) override { set_value(dst, this->operator[](src)); } @@ -540,14 +540,14 @@ class ChunkArray : public ChunkArrayGen * @param idx1 first element index * @param idx2 second element index */ - inline void swap_elements(unsigned int idx1, unsigned int idx2) override + inline void swap_elements(uint32 idx1, uint32 idx2) override { bool data = this->operator[](idx1); set_value(idx1, this->operator[](idx2)); set_value(idx2, data); } - void save(std::ostream& fs, unsigned int nb_lines) const override + void save(std::ostream& fs, uint32 nb_lines) const override { // no data -> finished if (nb_lines == 0) @@ -574,15 +574,15 @@ class ChunkArray : public ChunkArrayGen serialization::save(fs, &nb_lines, 1); - const unsigned int nbc = get_nb_chunks() - 1u; + const uint32 nbc = get_nb_chunks() - 1u; // save data chunks except last - for(unsigned int i = 0u; i < nbc; ++i) + for(uint32 i = 0u; i < nbc; ++i) { fs.write(reinterpret_cast(table_data_[i]), CHUNKSIZE / 8u); // /8 because bool = 1 bit & octet = 8 bit } // save last - const unsigned int nb = nb_lines - nbc*CHUNKSIZE; + const uint32 nb = nb_lines - nbc*CHUNKSIZE; fs.write(reinterpret_cast(table_data_[nbc]), nb / 8u); } @@ -593,7 +593,7 @@ class ChunkArray : public ChunkArrayGen serialization::load(fs, &chunk_bytes, 1); // get number of lines to load - unsigned int nb_lines; + uint32 nb_lines; serialization::load(fs, &nb_lines, 1); // no data -> finished @@ -601,7 +601,7 @@ class ChunkArray : public ChunkArrayGen return true; // compute number of chunks - unsigned int nbc = nb_lines / CHUNKSIZE; + uint32 nbc = nb_lines / CHUNKSIZE; if (nb_lines % CHUNKSIZE != 0u) nbc++; @@ -609,11 +609,11 @@ class ChunkArray : public ChunkArrayGen // load data chunks except last nbc--; - for(unsigned int i = 0u; i < nbc; ++i) + for(uint32 i = 0u; i < nbc; ++i) fs.read(reinterpret_cast(table_data_[i]), CHUNKSIZE / 8u);// /8 because bool = 1 bit & octet = 8 bit // load last chunk - unsigned int nb = nb_lines - nbc*CHUNKSIZE; + uint32 nb = nb_lines - nbc*CHUNKSIZE; fs.read(reinterpret_cast(table_data_[nbc]), nb / 8u); return true; @@ -624,49 +624,49 @@ class ChunkArray : public ChunkArrayGen * @param i index of element to access * @return value of the element */ - inline bool operator[](unsigned int i) const + inline bool operator[](uint32 i) const { - const unsigned int jj = i / CHUNKSIZE; + const uint32 jj = i / CHUNKSIZE; cgogn_assert(jj < table_data_.size()); - const unsigned int j = i % CHUNKSIZE; - const unsigned int x = j/32u; - const unsigned int y = j%32u; + const uint32 j = i % CHUNKSIZE; + const uint32 x = j/32u; + const uint32 y = j%32u; - const unsigned int mask = 1u << y; + const uint32 mask = 1u << y; return (table_data_[jj][x] & mask) != 0u; } - inline void set_false(unsigned int i) + inline void set_false(uint32 i) { - const unsigned int jj = i / CHUNKSIZE; + const uint32 jj = i / CHUNKSIZE; cgogn_assert(jj < table_data_.size()); - const unsigned int j = i % CHUNKSIZE; - const unsigned int x = j / 32u; - const unsigned int y = j % 32u; - const unsigned int mask = 1u << y; + const uint32 j = i % CHUNKSIZE; + const uint32 x = j / 32u; + const uint32 y = j % 32u; + const uint32 mask = 1u << y; table_data_[jj][x] &= ~mask; } - inline void set_true(unsigned int i) + inline void set_true(uint32 i) { - const unsigned int jj = i / CHUNKSIZE; + const uint32 jj = i / CHUNKSIZE; cgogn_assert(jj < table_data_.size()); - const unsigned int j = i % CHUNKSIZE; - const unsigned int x = j / 32u; - const unsigned int y = j % 32u; - const unsigned int mask = 1u << y; + const uint32 j = i % CHUNKSIZE; + const uint32 x = j / 32u; + const uint32 y = j % 32u; + const uint32 mask = 1u << y; table_data_[jj][x] |= mask; } - inline void set_value(unsigned int i, bool b) + inline void set_value(uint32 i, bool b) { - const unsigned int jj = i / CHUNKSIZE; + const uint32 jj = i / CHUNKSIZE; cgogn_assert(jj < table_data_.size()); - const unsigned int j = i % CHUNKSIZE; - const unsigned int x = j / 32u; - const unsigned int y = j % 32u; - const unsigned int mask = 1u << y; + const uint32 j = i % CHUNKSIZE; + const uint32 x = j / 32u; + const uint32 y = j % 32u; + const uint32 mask = 1u << y; if (b) table_data_[jj][x] |= mask; else @@ -680,17 +680,17 @@ class ChunkArray : public ChunkArrayGen * This version overwrites element AND SOME OF HIS NEIGHBOURS with 0 * Use only if final goal is to set all array to 0 (MarkerStore) */ - inline void set_false_byte(unsigned int i) + inline void set_false_byte(uint32 i) { - const unsigned int jj = i / CHUNKSIZE; + const uint32 jj = i / CHUNKSIZE; cgogn_assert(jj < table_data_.size()); - const unsigned int j = (i % CHUNKSIZE)/32u; + const uint32 j = (i % CHUNKSIZE)/32u; table_data_[jj][j] = 0u; } inline void all_false() { - for (unsigned int * const ptr : table_data_) + for (uint32 * const ptr : table_data_) { #pragma omp for for (int j = 0; j < int(CHUNKSIZE/32); ++j) @@ -702,7 +702,7 @@ class ChunkArray : public ChunkArrayGen // { // for (auto ptr : table_data_) // { -// for (unsigned int j = 0u; j < CHUNKSIZE/32u; ++j) +// for (uint32 j = 0u; j < CHUNKSIZE/32u; ++j) // *ptr++ = 0xffffffff; // } // } @@ -710,7 +710,7 @@ class ChunkArray : public ChunkArrayGen #if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_CONTAINER_CHUNK_ARRAY_CPP_)) extern template class CGOGN_CORE_API ChunkArray; -extern template class CGOGN_CORE_API ChunkArray; +extern template class CGOGN_CORE_API ChunkArray; extern template class CGOGN_CORE_API ChunkArray; extern template class CGOGN_CORE_API ChunkArray>; extern template class CGOGN_CORE_API ChunkArray>; diff --git a/cgogn/core/container/chunk_array_container.cpp b/cgogn/core/container/chunk_array_container.cpp index d06b7afe..149d9d96 100644 --- a/cgogn/core/container/chunk_array_container.cpp +++ b/cgogn/core/container/chunk_array_container.cpp @@ -32,7 +32,7 @@ namespace cgogn ContainerBrowser::~ContainerBrowser() {} -template class CGOGN_CORE_API ChunkArrayContainer; +template class CGOGN_CORE_API ChunkArrayContainer; template class CGOGN_CORE_API ChunkArrayContainer; } // namespace cgogn diff --git a/cgogn/core/container/chunk_array_container.h b/cgogn/core/container/chunk_array_container.h index 3136d117..961ee8e8 100644 --- a/cgogn/core/container/chunk_array_container.h +++ b/cgogn/core/container/chunk_array_container.h @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -47,10 +48,10 @@ class CGOGN_CORE_API ContainerBrowser { public: - virtual unsigned int begin() const = 0; - virtual unsigned int end() const = 0; - virtual void next(unsigned int &it) const = 0; - virtual void next_primitive(unsigned int &it, unsigned int primSz) const = 0; + virtual uint32 begin() const = 0; + virtual uint32 end() const = 0; + virtual void next(uint32 &it) const = 0; + virtual void next_primitive(uint32 &it, uint32 primSz) const = 0; virtual void enable() = 0; virtual void disable() = 0; virtual ~ContainerBrowser(); @@ -64,10 +65,10 @@ class ContainerStandardBrowser : public ContainerBrowser public: ContainerStandardBrowser(const CONTAINER* cac) : cac_(cac) {} - virtual unsigned int begin() const { return cac_->real_begin(); } - virtual unsigned int end() const { return cac_->real_end(); } - virtual void next(unsigned int &it) const { cac_->real_next(it); } - virtual void next_primitive(unsigned int &it, unsigned int primSz) const { cac_->real_next_primitive(it,primSz); } + virtual uint32 begin() const { return cac_->real_begin(); } + virtual uint32 end() const { return cac_->real_end(); } + virtual void next(uint32 &it) const { cac_->real_next(it); } + virtual void next_primitive(uint32 &it, uint32 primSz) const { cac_->real_next_primitive(it,primSz); } virtual void enable() {} virtual void disable() {} virtual ~ContainerStandardBrowser() {} @@ -78,7 +79,7 @@ class ContainerStandardBrowser : public ContainerBrowser * @brief class that manage the storage of several ChunkArray * @tparam CHUNKSIZE chunk size for ChunkArray */ -template +template class ChunkArrayContainer { public: @@ -95,7 +96,7 @@ class ChunkArrayContainer /** * constante d'attribut inconnu */ - static const unsigned int UNKNOWN = UINT_MAX; + static const uint32 UNKNOWN = UINT_MAX; protected: @@ -121,17 +122,17 @@ class ChunkArrayContainer /** * stack of holes */ - ChunkStack holes_stack_; + ChunkStack holes_stack_; /** * size (number of elts) of the container */ - unsigned int nb_used_lines_; + uint32 nb_used_lines_; /** * size of the container with holes (also index of next inserted line if no holes) */ - unsigned int nb_max_lines_; + uint32 nb_max_lines_; /** * Browser that allow special traversals @@ -149,9 +150,9 @@ class ChunkArrayContainer * @param attribName name of ChunkArray * @return the index in table */ - unsigned int get_array_index(const std::string& attribute_name) const + uint32 get_array_index(const std::string& attribute_name) const { - for (unsigned int i = 0u; i != names_.size(); ++i) + for (uint32 i = 0u; i != names_.size(); ++i) { if (names_[i] == attribute_name) return i; @@ -165,9 +166,9 @@ class ChunkArrayContainer * @param ptr of ChunkArray * @return the index in table */ - unsigned int get_array_index(const ChunkArrayGen* ptr) const + uint32 get_array_index(const ChunkArrayGen* ptr) const { - for (unsigned int i = 0u; i != table_arrays_.size(); ++i) + for (uint32 i = 0u; i != table_arrays_.size(); ++i) { if (table_arrays_[i] == ptr) return i; @@ -179,7 +180,7 @@ class ChunkArrayContainer * @brief remove an attribute by its index * @param index index of attribute to remove */ - void remove_attribute(unsigned int index) + void remove_attribute(uint32 index) { // store ptr for using it before delete ChunkArrayGen* ptr_to_del = table_arrays_[index]; @@ -242,7 +243,7 @@ class ChunkArrayContainer ChunkArray* get_attribute(const std::string& attribute_name) const { // first check if attribute already exist - unsigned int index = get_array_index(attribute_name); + uint32 index = get_array_index(attribute_name); if (index == UNKNOWN) { std::cerr << "attribute " << attribute_name << " not found." << std::endl; @@ -264,7 +265,7 @@ class ChunkArrayContainer cgogn_assert(attribute_name.size() != 0); // first check if attribute already exist - unsigned int index = get_array_index(attribute_name); + uint32 index = get_array_index(attribute_name); if (index != UNKNOWN) { std::cerr << "attribute " << attribute_name << " already exists.." << std::endl; @@ -294,7 +295,7 @@ class ChunkArrayContainer */ bool remove_attribute(const std::string& attribute_name) { - unsigned int index = get_array_index(attribute_name); + uint32 index = get_array_index(attribute_name); if (index == UNKNOWN) { @@ -314,7 +315,7 @@ class ChunkArrayContainer */ bool remove_attribute(const ChunkArrayGen* ptr) { - unsigned int index = get_array_index(ptr); + uint32 index = get_array_index(ptr); if (index == UNKNOWN) { @@ -346,7 +347,7 @@ class ChunkArrayContainer */ void remove_marker_attribute(const ChunkArray* ptr) { - unsigned int index = 0u; + uint32 index = 0u; while (index < table_marker_arrays_.size() && table_marker_arrays_[index] != ptr) ++index; @@ -376,7 +377,7 @@ class ChunkArrayContainer template ChunkArray* get_data_array(const std::string& attribute_name) { - unsigned int index = get_array_index(attribute_name); + uint32 index = get_array_index(attribute_name); if (index == UNKNOWN) return nullptr; @@ -394,7 +395,7 @@ class ChunkArrayContainer */ ChunkArrayGen* get_virtual_data_array(const std::string& attribute_name) { - unsigned int index = get_array_index(attribute_name); + uint32 index = get_array_index(attribute_name); if (index == UNKNOWN) return nullptr; @@ -405,7 +406,7 @@ class ChunkArrayContainer * @brief size (number of used lines) * @return the number of lines */ - unsigned int size() const + uint32 size() const { return nb_used_lines_; } @@ -414,7 +415,7 @@ class ChunkArrayContainer * @brief capacity (number of reserved lines) * @return number of reserved lines */ - unsigned int capacity() const + uint32 capacity() const { return refs_.capacity(); } @@ -441,7 +442,7 @@ class ChunkArrayContainer * @brief begin * @return the index of the first used line of the container */ - inline unsigned int begin() const + inline uint32 begin() const { return current_browser_->begin(); } @@ -450,7 +451,7 @@ class ChunkArrayContainer * @brief end * @return the index after the last used line of the container */ - inline unsigned int end() const + inline uint32 end() const { return current_browser_->end(); } @@ -459,7 +460,7 @@ class ChunkArrayContainer * @brief next it <- next used index in the container * @param it index to "increment" */ - inline void next(unsigned int& it) const + inline void next(uint32& it) const { current_browser_->next(it); } @@ -468,7 +469,7 @@ class ChunkArrayContainer * @brief next primitive: it <- next primitive used index in the container (eq to PRIMSIZE next) * @param it index to "increment" */ - inline void next_primitive(unsigned int& it, unsigned int prim_size) const + inline void next_primitive(uint32& it, uint32 prim_size) const { current_browser_->next_primitive(it, prim_size); } @@ -477,9 +478,9 @@ class ChunkArrayContainer * @brief begin of container without browser * @return the real index of the first used line of the container */ - inline unsigned int real_begin() const + inline uint32 real_begin() const { - unsigned int it = 0u; + uint32 it = 0u; while ((it < nb_max_lines_) && (!used(it))) ++it; return it; @@ -489,7 +490,7 @@ class ChunkArrayContainer * @brief end of container without browser * @return the real index after the last used line of the container */ - inline unsigned int real_end() const + inline uint32 real_end() const { return nb_max_lines_; } @@ -498,7 +499,7 @@ class ChunkArrayContainer * @brief next without browser * @param it */ - inline void real_next(unsigned int& it) const + inline void real_next(uint32& it) const { do { @@ -510,7 +511,7 @@ class ChunkArrayContainer * @brief next primitive without browser * @param it */ - inline void real_next_primitive(unsigned int &it, unsigned int prim_size) const + inline void real_next_primitive(uint32 &it, uint32 prim_size) const { do { @@ -522,9 +523,9 @@ class ChunkArrayContainer * @brief reverse begin of container without browser * @return the real index of the first used line of the container in reverse order */ - unsigned int real_rbegin() const + uint32 real_rbegin() const { - unsigned int it = nb_max_lines_- 1u; + uint32 it = nb_max_lines_- 1u; while ((it != 0xffffffff) && (!used(it))) --it; return it; @@ -534,7 +535,7 @@ class ChunkArrayContainer * @brief reverse end of container without browser * @return the real index before the last used line of the container in reverse order */ - unsigned int real_rend() const + uint32 real_rend() const { return 0xffffffff; // -1 } @@ -543,7 +544,7 @@ class ChunkArrayContainer * @brief reverse next without browser * @param it */ - void real_rnext(unsigned int &it) const + void real_rnext(uint32 &it) const { do { @@ -632,20 +633,20 @@ class ChunkArrayContainer * @brief container compacting * @param map_old_new vector that contains a map from old indices to new indices (holes -> 0xffffffff) */ - template - void compact(std::vector& map_old_new) + template + void compact(std::vector& map_old_new) { map_old_new.clear(); map_old_new.resize(real_end(), 0xffffffff); - unsigned int up = real_rbegin(); - unsigned int down = 0u; + uint32 up = real_rbegin(); + uint32 down = 0u; while (down < up) { if (!used(down)) { - for(unsigned int i = 0u; i < PRIMSIZE; ++i) + for(uint32 i = 0u; i < PRIMSIZE; ++i) { unsigned rdown = down + PRIMSIZE-1u - i; map_old_new[up] = rdown; @@ -661,7 +662,7 @@ class ChunkArrayContainer nb_max_lines_ = nb_used_lines_; // free unused memory blocks - unsigned int new_nb_blocks = nb_max_lines_/CHUNKSIZE + 1u; + uint32 new_nb_blocks = nb_max_lines_/CHUNKSIZE + 1u; for (auto arr : table_arrays_) arr->set_nb_chunks(new_nb_blocks); @@ -684,7 +685,7 @@ class ChunkArrayContainer * @param index index to test * @return true if the index is used, false otherwise */ - bool used(unsigned int index) const + bool used(uint32 index) const { return refs_[index] != 0; } @@ -693,12 +694,12 @@ class ChunkArrayContainer * @brief insert a group of PRIMSIZE consecutive lines in the container * @return index of the first line of group */ - template - unsigned int insert_lines() + template + uint32 insert_lines() { static_assert(PRIMSIZE < CHUNKSIZE, "Cannot insert lines in a container if PRIMSIZE < CHUNKSIZE"); - unsigned int index; + uint32 index; if (holes_stack_.empty()) // no holes -> insert at the end { @@ -732,7 +733,7 @@ class ChunkArrayContainer } // mark lines as used - for(unsigned int i = 0u; i < PRIMSIZE; ++i) + for(uint32 i = 0u; i < PRIMSIZE; ++i) refs_.set_value(index + i, 1u); // do not use [] in case of refs_ is bool nb_used_lines_ += PRIMSIZE; @@ -744,17 +745,17 @@ class ChunkArrayContainer * @brief remove a group of PRIMSIZE lines in the container * @param index index of one line of group to remove */ - template - void remove_lines(unsigned int index) + template + void remove_lines(uint32 index) { - unsigned int begin_prim_idx = (index / PRIMSIZE) * PRIMSIZE; + uint32 begin_prim_idx = (index / PRIMSIZE) * PRIMSIZE; cgogn_message_assert(used(begin_prim_idx), "Error removing non existing index"); holes_stack_.push(begin_prim_idx); // mark lines as unused - for(unsigned int i = 0u; i < PRIMSIZE; ++i) + for(uint32 i = 0u; i < PRIMSIZE; ++i) refs_.set_value(begin_prim_idx++, 0u); // do not use [] in case of refs_ is bool nb_used_lines_ -= PRIMSIZE; @@ -764,7 +765,7 @@ class ChunkArrayContainer * @brief initialize a line of the container (an element of each attribute) * @param index line index */ - void init_line(unsigned int index) + void init_line(uint32 index) { cgogn_message_assert(used(index), "init_line only with allocated lines"); @@ -776,7 +777,7 @@ class ChunkArrayContainer * @brief initialize the markers of a line of the container * @param index line index */ - void init_markers_of_line(unsigned int index) + void init_markers_of_line(uint32 index) { cgogn_message_assert(used(index), "init_markers_of_line only with allocated lines"); @@ -789,7 +790,7 @@ class ChunkArrayContainer * @param dstIndex destination * @param srcIndex source */ - void copy_line(unsigned int dst, unsigned int src) + void copy_line(uint32 dst, uint32 src) { for (auto ptr : table_arrays_) ptr->copy_element(dst, src); @@ -804,7 +805,7 @@ class ChunkArrayContainer * @brief increment the reference counter of the given line (only for PRIMSIZE==1) * @param index index of the line */ - void ref_line(unsigned int index) + void ref_line(uint32 index) { // static_assert(PRIMSIZE == 1u, "refLine with container where PRIMSIZE!=1"); refs_[index]++; @@ -815,7 +816,7 @@ class ChunkArrayContainer * @param index index of the line * @return true if the line was removed */ - bool unref_line(unsigned int index) + bool unref_line(uint32 index) { // static_assert(PRIMSIZE == 1u, "unrefLine with container where PRIMSIZE!=1"); cgogn_message_assert(refs_[index] > 1u, "Container: unref line with nb_ref == 1"); @@ -836,7 +837,7 @@ class ChunkArrayContainer * @param index index of the line * @return number of references of the line */ - T_REF get_nb_refs(unsigned int index) const + T_REF get_nb_refs(uint32 index) const { // static_assert(PRIMSIZE == 1u, "getNbRefs with container where PRIMSIZE!=1"); return refs_[index]; @@ -847,22 +848,22 @@ class ChunkArrayContainer cgogn_assert(fs.good()); // save info (size+used_lines+max_lines+sizeof names) - std::vector buffer; + std::vector buffer; buffer.reserve(1024); - buffer.push_back(static_cast(table_arrays_.size())); + buffer.push_back(static_cast(table_arrays_.size())); buffer.push_back(nb_used_lines_); buffer.push_back(nb_max_lines_); - for(unsigned int i = 0u; i < table_arrays_.size(); ++i) + for(uint32 i = 0u; i < table_arrays_.size(); ++i) { - buffer.push_back(static_cast(names_[i].size()+1)); - buffer.push_back(static_cast(type_names_[i].size()+1)); + buffer.push_back(static_cast(names_[i].size()+1)); + buffer.push_back(static_cast(type_names_[i].size()+1)); } - fs.write(reinterpret_cast(&(buffer[0])), std::streamsize(buffer.size()*sizeof(unsigned int))); + fs.write(reinterpret_cast(&(buffer[0])), std::streamsize(buffer.size()*sizeof(uint32))); // save names - for(unsigned int i = 0; i < table_arrays_.size(); ++i) + for(uint32 i = 0; i < table_arrays_.size(); ++i) { const char* s1 = names_[i].c_str(); const char* s2 = type_names_[i].c_str(); @@ -871,7 +872,7 @@ class ChunkArrayContainer } // save chunk arrays - for(unsigned int i = 0u; i < table_arrays_.size(); ++i) + for(uint32 i = 0u; i < table_arrays_.size(); ++i) { table_arrays_[i]->save(fs, nb_max_lines_); } @@ -891,21 +892,21 @@ class ChunkArrayContainer ChunkArrayFactory::register_known_types(); // read info - unsigned int buff1[4]; - fs.read(reinterpret_cast(buff1), 3u*sizeof(unsigned int)); + uint32 buff1[4]; + fs.read(reinterpret_cast(buff1), 3u*sizeof(uint32)); nb_used_lines_ = buff1[1]; nb_max_lines_ = buff1[2]; - std::vector buff2(2u*buff1[0]); - fs.read(reinterpret_cast(&(buff2[0])), std::streamsize(2u*buff1[0]*sizeof(unsigned int))); + std::vector buff2(2u*buff1[0]); + fs.read(reinterpret_cast(&(buff2[0])), std::streamsize(2u*buff1[0]*sizeof(uint32))); names_.resize(buff1[0]); type_names_.resize(buff1[0]); // read name char buff3[256]; - for(unsigned int i = 0u; i < buff1[0]; ++i) + for(uint32 i = 0u; i < buff1[0]; ++i) { fs.read(buff3, std::streamsize(buff2[2u*i]*sizeof(char))); names_[i] = std::string(buff3); @@ -917,7 +918,7 @@ class ChunkArrayContainer // read chunk array table_arrays_.reserve(buff1[0]); bool ok = true; - for (unsigned int i = 0u; i < names_.size();) + for (uint32 i = 0u; i < names_.size();) { ChunkArrayGen* cag = ChunkArrayFactory::create(type_names_[i]); if (cag) @@ -943,7 +944,7 @@ class ChunkArrayContainer #if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_CONTAINER_CHUNK_ARRAY_CONTAINER_CPP_)) -extern template class CGOGN_CORE_API ChunkArrayContainer; +extern template class CGOGN_CORE_API ChunkArrayContainer; extern template class CGOGN_CORE_API ChunkArrayContainer; #endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_CONTAINER_CHUNK_ARRAY_CONTAINER_CPP_)) diff --git a/cgogn/core/container/chunk_array_factory.h b/cgogn/core/container/chunk_array_factory.h index a8e33a74..b11325b0 100644 --- a/cgogn/core/container/chunk_array_factory.h +++ b/cgogn/core/container/chunk_array_factory.h @@ -36,7 +36,7 @@ namespace cgogn { -template +template class ChunkArrayFactory { static_assert(CHUNKSIZE >= 1u,"ChunkSize must be at least 1"); @@ -82,7 +82,7 @@ class ChunkArrayFactory register_CA(); register_CA(); register_CA(); - register_CA(); + register_CA(); register_CA(); register_CA(); register_CA(); @@ -121,7 +121,7 @@ class ChunkArrayFactory } }; -template +template typename ChunkArrayFactory::UniqueNamePtrMap ChunkArrayFactory::map_CA_ = nullptr; diff --git a/cgogn/core/container/chunk_array_gen.h b/cgogn/core/container/chunk_array_gen.h index 9291a013..72af2d4e 100644 --- a/cgogn/core/container/chunk_array_gen.h +++ b/cgogn/core/container/chunk_array_gen.h @@ -34,12 +34,12 @@ namespace cgogn { -static const unsigned int DEFAULT_CHUNK_SIZE = 4096; +static const uint32 DEFAULT_CHUNK_SIZE = 4096; /** * @brief Virtual version of ChunkArray */ -template +template class ChunkArrayGen { public: @@ -105,19 +105,19 @@ class ChunkArrayGen * @brief set number of chunks * @param nbc number of chunks */ - virtual void set_nb_chunks(unsigned int nbb) = 0; + virtual void set_nb_chunks(uint32 nbb) = 0; /** * @brief get the number of chunks of the array * @return the number of chunks */ - virtual unsigned int get_nb_chunks() const = 0; + virtual uint32 get_nb_chunks() const = 0; /** * @brief get the capacity of the array * @return number of allocated lines */ - virtual unsigned int capacity() const = 0; + virtual uint32 capacity() const = 0; /** * @brief clear the array @@ -130,34 +130,34 @@ class ChunkArrayGen * @param byte_block_size filled with CHUNKSIZE*sizeof(T) * @return addr.size() */ - virtual unsigned int get_chunks_pointers(std::vector& addr, unsigned int& byte_block_size) const = 0; + virtual uint32 get_chunks_pointers(std::vector& addr, uint32& byte_block_size) const = 0; /** * @brief initialize an element of the array (overwrite with T()) * @param id index of the element */ - virtual void init_element(unsigned int id) = 0; + virtual void init_element(uint32 id) = 0; /** * @brief copy an element to another one * @param dst destination element index * @param src source element index */ - virtual void copy_element(unsigned int dst, unsigned int src) = 0; + virtual void copy_element(uint32 dst, uint32 src) = 0; /** * @brief swap two elements * @param idx1 first element index * @param idx2 second element index */ - virtual void swap_elements(unsigned int idx1, unsigned int idx2) = 0; + virtual void swap_elements(uint32 idx1, uint32 idx2) = 0; /** * @brief save * @param fs file stream * @param nb_lines number of line to save */ - virtual void save(std::ostream& fs, unsigned int nb_lines) const = 0; + virtual void save(std::ostream& fs, uint32 nb_lines) const = 0; /** * @brief load @@ -174,7 +174,7 @@ class ChunkArrayGen { std::size_t chunk_bytes; serialization::load(fs, &chunk_bytes, 1); - unsigned int nb_lines; + uint32 nb_lines; serialization::load(fs, &nb_lines, 1); fs.ignore(std::streamsize(chunk_bytes), EOF); } diff --git a/cgogn/core/container/chunk_stack.cpp b/cgogn/core/container/chunk_stack.cpp index 20beab9c..0883eceb 100644 --- a/cgogn/core/container/chunk_stack.cpp +++ b/cgogn/core/container/chunk_stack.cpp @@ -29,6 +29,6 @@ namespace cgogn { -template class CGOGN_CORE_API ChunkStack; +template class CGOGN_CORE_API ChunkStack; } // namespace cgogn diff --git a/cgogn/core/container/chunk_stack.h b/cgogn/core/container/chunk_stack.h index 4536a4b7..177c72d9 100644 --- a/cgogn/core/container/chunk_stack.h +++ b/cgogn/core/container/chunk_stack.h @@ -36,7 +36,7 @@ namespace cgogn * @tparam CHUNKSIZE chunk size of array * @tparam T type stored in heap */ -template +template class ChunkStack : public ChunkArray { public: @@ -46,7 +46,7 @@ class ChunkStack : public ChunkArray protected: - unsigned int stack_size_; + uint32 stack_size_; public: /** @@ -75,8 +75,8 @@ class ChunkStack : public ChunkArray void push(const T& val) { stack_size_++; - unsigned int offset = stack_size_ % CHUNKSIZE; - unsigned int blkId = stack_size_ / CHUNKSIZE; + uint32 offset = stack_size_ % CHUNKSIZE; + uint32 blkId = stack_size_ / CHUNKSIZE; if (blkId >= this->table_data_.size()) this->add_chunk(); @@ -96,7 +96,7 @@ class ChunkStack : public ChunkArray /** * @return number of elements in the heap */ - unsigned int size() const + uint32 size() const { return stack_size_; } @@ -116,8 +116,8 @@ class ChunkStack : public ChunkArray */ inline T head() const { - const unsigned int offset = stack_size_ % CHUNKSIZE; - const unsigned int blkId = stack_size_ / CHUNKSIZE; + const uint32 offset = stack_size_ % CHUNKSIZE; + const uint32 blkId = stack_size_ / CHUNKSIZE; return this->table_data_[blkId][offset]; } @@ -127,7 +127,7 @@ class ChunkStack : public ChunkArray */ void compact() { - const unsigned int keep = (stack_size_+CHUNKSIZE-1u) / CHUNKSIZE; + const uint32 keep = (stack_size_+CHUNKSIZE-1u) / CHUNKSIZE; while (this->table_data_.size() > keep) { delete[] this->table_data_.back(); @@ -152,7 +152,7 @@ class ChunkStack : public ChunkArray }; #if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_CONTAINER_CHUNK_STACK_CPP_)) -extern template class CGOGN_CORE_API ChunkStack; +extern template class CGOGN_CORE_API ChunkStack; #endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_CONTAINER_CHUNK_STACK_CPP_)) } // namespace cgogn diff --git a/cgogn/core/examples/chunk_array/bench_chunk_array.cpp b/cgogn/core/examples/chunk_array/bench_chunk_array.cpp index f6dba580..3ad48ac4 100644 --- a/cgogn/core/examples/chunk_array/bench_chunk_array.cpp +++ b/cgogn/core/examples/chunk_array/bench_chunk_array.cpp @@ -36,7 +36,7 @@ class Vec3f } }; -const unsigned int NB_LINES = 20000000; +const uint32 NB_LINES = 20000000; int test1() { @@ -47,26 +47,26 @@ int test1() ChunkArray* att2 = container.add_attribute("reel"); ChunkArray* att3 = container.add_attribute("Vec3f"); - for (unsigned int i = 0; i < NB_LINES; ++i) + for (uint32 i = 0; i < NB_LINES; ++i) container.insert_lines<1>(); - for(unsigned int i = container.begin(); i != container.end(); container.next(i)) + for(uint32 i = container.begin(); i != container.end(); container.next(i)) { (*att1)[i] = 1+int(i); (*att2)[i] = 3.0f + 0.1f*float(i); (*att3)[i] = Vec3f(float(i), float(i), float(i)); } - for (unsigned int j = 0; j < 100; ++j) + for (uint32 j = 0; j < 100; ++j) { - for (unsigned int i = 0; i < NB_LINES/10; ++i) + for (uint32 i = 0; i < NB_LINES/10; ++i) { container.remove_lines<1>(j%2+1+i*10); container.remove_lines<1>(j%2+3+i*10); container.remove_lines<1>(j%2+8+i*10); } - for (unsigned int i = 0; i < 3*NB_LINES/10; ++i) + for (uint32 i = 0; i < 3*NB_LINES/10; ++i) container.insert_lines<1>(); } @@ -83,26 +83,26 @@ int test2() ChunkArray* att2 = container.add_attribute("reel"); ChunkArray* att3 = container.add_attribute("Vec3f"); - for (unsigned int i = 0; i < NB_LINES; ++i) + for (uint32 i = 0; i < NB_LINES; ++i) container.insert_lines<1>(); - for(unsigned int i = container.begin(); i != container.end(); container.next(i)) + for(uint32 i = container.begin(); i != container.end(); container.next(i)) { (*att1)[i] = 1+int(i); (*att2)[i] = 3.0f + 0.1f*float(i); (*att3)[i] = Vec3f(float(i), float(i), float(i)); } - for (unsigned int j = 0; j < 100; ++j) + for (uint32 j = 0; j < 100; ++j) { - for (unsigned int i = 0; i < NB_LINES/10; ++i) + for (uint32 i = 0; i < NB_LINES/10; ++i) { container.remove_lines<1>(j%2+1+i*10); container.remove_lines<1>(j%2+3+i*10); container.remove_lines<1>(j%2+8+i*10); } - for (unsigned int i = 0; i < 3*NB_LINES/10; ++i) + for (uint32 i = 0; i < 3*NB_LINES/10; ++i) container.insert_lines<1>(); } @@ -117,17 +117,17 @@ int test3() ChunkArrayContainer container; ChunkArray* att1 = container.add_attribute("bools"); - for (unsigned int i = 0; i < NB_LINES; ++i) + for (uint32 i = 0; i < NB_LINES; ++i) container.insert_lines<1>(); - for(unsigned int i = container.begin(); i != container.end(); container.next(i)) + for(uint32 i = container.begin(); i != container.end(); container.next(i)) { att1->set_value(i, true); } - for (unsigned int j = 0; j < 100; ++j) + for (uint32 j = 0; j < 100; ++j) { - for (unsigned int i = 0; i < NB_LINES/2; ++i) + for (uint32 i = 0; i < NB_LINES/2; ++i) { att1->set_false(i); att1->set_false(NB_LINES-1-i); @@ -145,17 +145,17 @@ int test4() ChunkArrayContainer container; ChunkArray* att1 = container.add_attribute("bools"); - for (unsigned int i = 0; i < NB_LINES; ++i) + for (uint32 i = 0; i < NB_LINES; ++i) container.insert_lines<1>(); - for(unsigned int i = container.begin(); i != container.end(); container.next(i)) + for(uint32 i = container.begin(); i != container.end(); container.next(i)) { att1->set_value(i, true); } - for (unsigned int j = 0; j < 100; ++j) + for (uint32 j = 0; j < 100; ++j) { - for (unsigned int i = 0; i < NB_LINES/2; ++i) + for (uint32 i = 0; i < NB_LINES/2; ++i) { att1->set_false_byte(i); att1->set_false_byte(NB_LINES-1-i); @@ -170,22 +170,22 @@ int test5() { std::cout << "= TEST 5 = Traversal" << std::endl; - ChunkArrayContainer container; - ChunkArray* att1 = container.add_attribute("uints"); + ChunkArrayContainer container; + ChunkArray* att1 = container.add_attribute("uints"); - for (unsigned int i = 0; i < NB_LINES; ++i) + for (uint32 i = 0; i < NB_LINES; ++i) container.insert_lines<1>(); - for(unsigned int i = container.begin(); i != container.end(); container.next(i)) + for(uint32 i = container.begin(); i != container.end(); container.next(i)) att1->operator[](i) = i; - for(unsigned int i = container.begin(); i < container.end(); i += 9) + for(uint32 i = container.begin(); i < container.end(); i += 9) container.remove_lines<1>(i); int total = 0; - for (unsigned int j = 0; j < 50; ++j) + for (uint32 j = 0; j < 50; ++j) { - for(unsigned int i = container.begin(); i != container.end(); container.next(i)) + for(uint32 i = container.begin(); i != container.end(); container.next(i)) { if (att1->operator[](i) % i != 0) total += att1->operator[](i); diff --git a/cgogn/core/examples/chunk_array/chunk_array.cpp b/cgogn/core/examples/chunk_array/chunk_array.cpp index 81d67d0a..e59d6a11 100644 --- a/cgogn/core/examples/chunk_array/chunk_array.cpp +++ b/cgogn/core/examples/chunk_array/chunk_array.cpp @@ -3,7 +3,10 @@ #include -const unsigned int SIZE = 32u; +using namespace cgogn::numerics; + + +const uint32 SIZE = 32u; template using ChunkArray = cgogn::ChunkArray; template @@ -18,14 +21,14 @@ int test1() { std::cout << "=============== TEST 1 ===============" << std::endl; - ChunkArrayContainer container; + ChunkArrayContainer container; ChunkArray* att1 = container.add_attribute("entier"); ChunkArray* att2 = container.add_attribute("reel"); - for (unsigned int i = 0; i < 41; ++i) + for (uint32 i = 0; i < 41; ++i) container.insert_lines<1>(); - for(unsigned int i = container.begin(); i != container.end(); container.next(i)) + for(uint32 i = container.begin(); i != container.end(); container.next(i)) { (*att1)[i] = 1+int(i); (*att2)[i] = 3.0f + 0.1f*float(i); @@ -36,13 +39,13 @@ int test1() container.remove_lines<1>(35); - for(unsigned int i = container.begin(); i != container.end(); container.next(i)) + for(uint32 i = container.begin(); i != container.end(); container.next(i)) { std::cout << i << ": " << (*att1)[i] << " / " << (*att2)[i] << std::endl; } std::cout << "----------------------------------------" << std::endl; - unsigned int li = container.insert_lines<1>(); + uint32 li = container.insert_lines<1>(); (*att1)[li] = 110; (*att2)[li] = 123.1f; @@ -57,7 +60,7 @@ int test1() (*att1)[li] = 112; (*att2)[li] = 323.1f; - for(unsigned int i = container.begin(); i != container.end(); container.next(i)) + for(uint32 i = container.begin(); i != container.end(); container.next(i)) { std::cout << i << ": " << (*att1)[i] << " / " << (*att2)[i] << std::endl; } @@ -67,10 +70,10 @@ int test1() container.remove_lines<1>(19); container.remove_lines<1>(35); - std::vector mapOldNew; + std::vector mapOldNew; container.compact<1>(mapOldNew); - for(unsigned int i = container.begin(); i != container.end(); container.next(i)) + for(uint32 i = container.begin(); i != container.end(); container.next(i)) { std::cout << i << ": " << (*att1)[i] << " / " << (*att2)[i] << std::endl; } @@ -89,10 +92,10 @@ int test2() for (int i = 0; i < 13; ++i) container.insert_lines<3>(); - for(unsigned int i = container.begin(); i != container.end(); container.next(i)) + for(uint32 i = container.begin(); i != container.end(); container.next(i)) (*att1)[i] = 1+int(i); - for(unsigned int i = container.begin(); i != container.end(); container.next(i)) + for(uint32 i = container.begin(); i != container.end(); container.next(i)) { std::cout << i << ": " << (*att1)[i] << std::endl; } @@ -101,27 +104,27 @@ int test2() container.remove_lines<3>(2); container.remove_lines<3>(35); - unsigned int li = container.insert_lines<3>(); + uint32 li = container.insert_lines<3>(); (*att1)[li] = 110; (*att1)[li+1] = 111; (*att1)[li+2] = 112; - for(unsigned int i = container.begin(); i != container.end(); container.next(i)) + for(uint32 i = container.begin(); i != container.end(); container.next(i)) std::cout << i << ": " << (*att1)[i] << std::endl; std::cout << "----------------------------------------" << std::endl; container.remove_lines<3>(8); container.remove_lines<3>(17); - for(unsigned int i = container.begin(); i != container.end(); container.next(i)) + for(uint32 i = container.begin(); i != container.end(); container.next(i)) std::cout << i << ": " << (*att1)[i] << std::endl; std::cout << "-Compact--------------------------------------" << std::endl; - std::vector mapOldNew; + std::vector mapOldNew; container.compact<3>(mapOldNew); - for(unsigned int i = container.begin(); i != container.end(); container.next(i)) + for(uint32 i = container.begin(); i != container.end(); container.next(i)) std::cout << i << ": " << (*att1)[i] << std::endl; std::cout << "----------------------------------------" << std::endl; @@ -137,13 +140,13 @@ int test2() (*att1)[li+1] = 211; (*att1)[li+2] = 212; - for(unsigned int i = container.begin(); i != container.end(); container.next(i)) + for(uint32 i = container.begin(); i != container.end(); container.next(i)) std::cout << i << ": " << (*att1)[i] << std::endl; std::cout << "----------------------------------------" << std::endl; ChunkArray* attB = container.add_attribute("bools"); - for(unsigned int i = container.begin(); i != container.end(); container.next(i)) + for(uint32 i = container.begin(); i != container.end(); container.next(i)) std::cout << i << ": " << (*att1)[i]<< " / "<< (*attB)[i] << std::endl; std::cout << "----------------------------------------" << std::endl; @@ -159,17 +162,17 @@ int test3() ChunkArray >* att2 = container.add_attribute >("V_entier"); ChunkArray >* att3 = container.add_attribute >("L_entier"); - for (unsigned int i = 0; i < 13; ++i) + for (uint32 i = 0; i < 13; ++i) container.insert_lines<3>(); std::vector vect = (*att2)[0]; - for(unsigned int i = container.begin(); i != container.end(); container.next(i)) + for(uint32 i = container.begin(); i != container.end(); container.next(i)) { (*att1)[i] = 1+int(i); - for (unsigned int j = 0; j < i; ++j) + for (uint32 j = 0; j < i; ++j) (*att2)[i].push_back(int(j)); - for (unsigned int j = 0; j < i/2; ++j) + for (uint32 j = 0; j < i/2; ++j) (*att3)[i].push_front(int(j)); } @@ -179,7 +182,7 @@ int test3() container.insert_lines<3>(); - for(unsigned int i = container.begin(); i != container.end(); container.next(i)) + for(uint32 i = container.begin(); i != container.end(); container.next(i)) { std::cout << i << ": " << (*att1)[i] << " // "; for (auto j : (*att2)[i]) @@ -191,7 +194,7 @@ int test3() } std::cout << "----------------------------------------" << std::endl; - for(unsigned int i = container.begin(); i != container.end(); container.next_primitive(i,3)) + for(uint32 i = container.begin(); i != container.end(); container.next_primitive(i,3)) { std::cout << i << ": " << (*att1)[i] << " // "; for (auto j : (*att2)[i]) @@ -211,17 +214,17 @@ int test4() std::cout << "=============== TEST 4 ===============" << std::endl; using vecvecdouble = std::vector< std::vector< double > >; using veclistdouble = std::vector< std::list< double > >; - ChunkArrayContainer container; + ChunkArrayContainer container; ChunkArray* att1 = container.add_attribute("entier"); ChunkArray* att2 = container.add_attribute("reel"); ChunkArray* att3 = container.add_attribute("bools"); ChunkArray* att4 = container.add_attribute("vecvecdouble"); ChunkArray* att5 = container.add_attribute("veclistdouble"); - for (unsigned int i = 0u; i < 7u; ++i) + for (uint32 i = 0u; i < 7u; ++i) container.insert_lines<3>(); - for(unsigned int i = container.begin(); i != container.end(); container.next(i)) + for(uint32 i = container.begin(); i != container.end(); container.next(i)) { (*att1)[i] = 1+int(i); (*att2)[i] = 3.0f + 0.1f*float(i); @@ -237,7 +240,7 @@ int test4() container.save(of); of.close(); - ChunkArrayContainer cont2; + ChunkArrayContainer cont2; std::ifstream ifi("pipo.map", std::ios::binary); cont2.load(ifi); ifi.close(); @@ -248,7 +251,7 @@ int test4() ChunkArray* load_att4 = cont2.get_attribute("vecvecdouble"); ChunkArray* load_att5 = cont2.get_attribute("veclistdouble"); - for(unsigned int i = cont2.begin(); i != cont2.end(); cont2.next(i)) + for(uint32 i = cont2.begin(); i != cont2.end(); cont2.next(i)) { std::cout << i << ": " << (*load_att1)[i] << " / " << (*load_att2)[i] << " / " << (*load_att3)[i] << " / "; for (const auto& v : (*load_att4)[i]) diff --git a/cgogn/core/examples/chunk_array/chunk_array2.cpp b/cgogn/core/examples/chunk_array/chunk_array2.cpp index 1d6e1738..550c57c0 100644 --- a/cgogn/core/examples/chunk_array/chunk_array2.cpp +++ b/cgogn/core/examples/chunk_array/chunk_array2.cpp @@ -5,7 +5,9 @@ #include -const unsigned int SIZE = 32u; +using namespace cgogn::numerics; + +const uint32 SIZE = 32u; template using ChunkArray = cgogn::ChunkArray; using ChunkArrayContainer = cgogn::ChunkArrayContainer; @@ -31,10 +33,10 @@ int test_save() ChunkArray* att3 = container.add_attribute("VecListString"); ChunkArray* att_string_array = container.add_attribute("StringArray"); - for (unsigned int i = 0u; i < 10u; ++i) + for (uint32 i = 0u; i < 10u; ++i) container.insert_lines<1>(); - for(unsigned int i = container.begin(); i != container.end(); container.next(i)) + for(uint32 i = container.begin(); i != container.end(); container.next(i)) { (*att1)[i] = 0.1f*float(i); (*att4)[i] = std::string(3,char('Z'-i)); @@ -59,7 +61,7 @@ int test_save() container.remove_lines<1>(5); - for(unsigned int i = container.begin(); i != container.end(); container.next(i)) + for(uint32 i = container.begin(); i != container.end(); container.next(i)) { if (att1) std::cout << "FLOAT=" << (*att1)[i] << "/"; @@ -131,7 +133,7 @@ int test_load(bool with_register) ChunkArray* att3 = cont2.get_attribute("VecListString"); ChunkArray* att_string_array = cont2.get_attribute("StringArray"); - for(unsigned int i = cont2.begin(); i != cont2.end(); cont2.next(i)) + for(uint32 i = cont2.begin(); i != cont2.end(); cont2.next(i)) { if (att1) std::cout << "FLOAT=" << (*att1)[i] << "/"; diff --git a/cgogn/core/examples/map/map.cpp b/cgogn/core/examples/map/map.cpp index f619b757..8952e8d7 100644 --- a/cgogn/core/examples/map/map.cpp +++ b/cgogn/core/examples/map/map.cpp @@ -70,7 +70,7 @@ int test1(MAP& map) map.remove_attribute(ahf); std::cout << "ahf valid : " << std::boolalpha << ahf.is_valid() << std::endl; - std::vector* uib = cgogn::get_uint_buffers()->get_buffer(); + std::vector* uib = cgogn::get_uint_buffers()->get_buffer(); uib->push_back(3); cgogn::get_uint_buffers()->release_buffer(uib); @@ -113,9 +113,9 @@ int test1(MAP& map) // }); // get ChunkArrayContainer -> get ChunkArray -> fill -// typename MAP::template ChunkArrayContainer& container = map.get_attribute_container(MAP::Vertex); +// typename MAP::template ChunkArrayContainer& container = map.get_attribute_container(MAP::Vertex); // typename MAP::template ChunkArray* att = container.template get_attribute("floats"); -// for (unsigned int i = 0; i < 10; ++i) +// for (uint32 i = 0; i < 10; ++i) // container.template insert_lines<1>(); for (auto& v : ah) v = 3.0f; diff --git a/cgogn/core/tests/basic/cell_test.cpp b/cgogn/core/tests/basic/cell_test.cpp index 3cddaac7..fe28c2ae 100644 --- a/cgogn/core/tests/basic/cell_test.cpp +++ b/cgogn/core/tests/basic/cell_test.cpp @@ -27,17 +27,18 @@ namespace cgogn { - +uint32_t toto; +std::uint32_t tutu; const Dart dglobal(10u); -const Dart dmax(std::numeric_limits::max()); +const Dart dmax(std::numeric_limits::max()); TEST(CellTest, DefaultConstructor) { Cell c; Dart d = c; - EXPECT_EQ(std::numeric_limits::max(), d.index); + EXPECT_EQ(std::numeric_limits::max(), d.index); } TEST(CellTest, Constructor) diff --git a/cgogn/core/tests/basic/dart_test.cpp b/cgogn/core/tests/basic/dart_test.cpp index 2361e52d..3d1f0315 100644 --- a/cgogn/core/tests/basic/dart_test.cpp +++ b/cgogn/core/tests/basic/dart_test.cpp @@ -34,7 +34,7 @@ class DartTest : public ::testing::Test public: DartTest() : d10a_(10u), d10b_(10u), d20a_(20u), - dMax_(std::numeric_limits::max()) {} + dMax_(std::numeric_limits::max()) {} // virtual void TearDown() {} @@ -47,7 +47,7 @@ class DartTest : public ::testing::Test TEST_F(DartTest, DefaultConstructor) { - EXPECT_EQ(std::numeric_limits::max(), dNil_.index); + EXPECT_EQ(std::numeric_limits::max(), dNil_.index); } TEST_F(DartTest, Constructor) diff --git a/cgogn/core/tests/cmap/cmap0_test.cpp b/cgogn/core/tests/cmap/cmap0_test.cpp index 2d21cd04..07fcf840 100644 --- a/cgogn/core/tests/cmap/cmap0_test.cpp +++ b/cgogn/core/tests/cmap/cmap0_test.cpp @@ -63,7 +63,7 @@ class CMap0Test : public ::testing::Test CMap0Test() { darts_.reserve(NB_MAX); - std::srand(static_cast(std::time(0))); + std::srand(static_cast(std::time(0))); cmap_.add_attribute("vertices"); } @@ -71,10 +71,10 @@ class CMap0Test : public ::testing::Test * \brief Initialize the darts in darts_ with added vertices * \param n : the number of added darts or vertices */ - void add_vertices(unsigned int n) + void add_vertices(uint32 n) { darts_.clear(); - for (unsigned int i = 0; i < n; ++i) + for (uint32 i = 0; i < n; ++i) darts_.push_back(cmap_.add_vertex()); } }; diff --git a/cgogn/core/tests/cmap/cmap0_topo_test.cpp b/cgogn/core/tests/cmap/cmap0_topo_test.cpp index 270eb39b..b000c7e4 100644 --- a/cgogn/core/tests/cmap/cmap0_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap0_topo_test.cpp @@ -58,17 +58,17 @@ class CMap0TopoTest : public ::testing::Test CMap0TopoTest() { darts_.reserve(NB_MAX); - std::srand(static_cast(std::time(0))); + std::srand(static_cast(std::time(0))); } /*! * \brief Initialize the darts in darts_ with added vertices * \param n : the number of added darts or vertices */ - void add_vertices(unsigned int n) + void add_vertices(uint32 n) { darts_.clear(); - for (unsigned int i = 0; i < n; ++i) + for (uint32 i = 0; i < n; ++i) darts_.push_back(cmap_.add_vertex()); } }; diff --git a/cgogn/core/tests/cmap/cmap1_test.cpp b/cgogn/core/tests/cmap/cmap1_test.cpp index ff63858d..1e176909 100644 --- a/cgogn/core/tests/cmap/cmap1_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_test.cpp @@ -60,7 +60,7 @@ class CMap1Test : public ::testing::Test CMap1Test() { darts_.reserve(NB_MAX); - std::srand(static_cast(std::time(0))); + std::srand(static_cast(std::time(0))); cmap_.add_attribute("vertices"); cmap_.add_attribute("faces"); @@ -72,13 +72,13 @@ class CMap1Test : public ::testing::Test * The face size ranges from 1 to 10. * A random dart of each face is put in the darts_ array. */ - unsigned int add_faces(unsigned int n) + uint32 add_faces(uint32 n) { darts_.clear(); - unsigned int count = 0u; - for (unsigned int i = 0u; i < n; ++i) + uint32 count = 0u; + for (uint32 i = 0u; i < n; ++i) { - unsigned int m = 1u + std::rand() % 10; + uint32 m = 1u + std::rand() % 10; Dart d = cmap_.add_face(m); count += m; @@ -105,7 +105,7 @@ TEST_F(CMap1Test, random_map_generators) */ TEST_F(CMap1Test, add_face) { - unsigned int count_vertices = add_faces(NB_MAX); + uint32 count_vertices = add_faces(NB_MAX); EXPECT_EQ(cmap_.nb_cells(), count_vertices); EXPECT_EQ(cmap_.nb_cells(), NB_MAX); @@ -117,7 +117,7 @@ TEST_F(CMap1Test, add_face) */ TEST_F(CMap1Test, remove_face) { - unsigned int count_vertices = add_faces(NB_MAX); + uint32 count_vertices = add_faces(NB_MAX); int count_faces = NB_MAX; for (Dart d : darts_) @@ -125,7 +125,7 @@ TEST_F(CMap1Test, remove_face) if (std::rand() % 3 == 1) { Face f(d); - unsigned int k = cmap_.degree(f); + uint32 k = cmap_.degree(f); cmap_.remove_face(f); count_vertices -= k; --count_faces; @@ -142,7 +142,7 @@ TEST_F(CMap1Test, remove_face) */ TEST_F(CMap1Test, split_vertex) { - unsigned int count_vertices = add_faces(NB_MAX); + uint32 count_vertices = add_faces(NB_MAX); for (Dart d : darts_) { @@ -160,12 +160,12 @@ TEST_F(CMap1Test, split_vertex) */ TEST_F(CMap1Test, remove_vertex) { - unsigned int count_vertices = add_faces(NB_MAX); - unsigned int count_faces = NB_MAX; + uint32 count_vertices = add_faces(NB_MAX); + uint32 count_faces = NB_MAX; for (Dart d: darts_) { - unsigned int k = cmap_.degree(Face(d)); + uint32 k = cmap_.degree(Face(d)); cmap_.remove_vertex(Vertex(d)); --count_vertices; if (k == 1u) --count_faces; diff --git a/cgogn/core/tests/cmap/cmap1_topo_test.cpp b/cgogn/core/tests/cmap/cmap1_topo_test.cpp index a03ef439..0fb6b6d7 100644 --- a/cgogn/core/tests/cmap/cmap1_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_topo_test.cpp @@ -56,17 +56,17 @@ class CMap1TopoTest : public CMap1, public ::testing::Test CMap1TopoTest() { darts_.reserve(NB_MAX); - std::srand(static_cast(std::time(0))); + std::srand(static_cast(std::time(0))); } /*! * \brief Initialize the darts in darts_ with added vertices * \param n : the number of added darts or vertices */ - void add_vertices(unsigned int n) + void add_vertices(uint32 n) { darts_.clear(); - for (unsigned int i = 0u; i < n; ++i) + for (uint32 i = 0u; i < n; ++i) darts_.push_back(add_dart()); } @@ -76,13 +76,13 @@ class CMap1TopoTest : public CMap1, public ::testing::Test * The face size ranges from 1 to 10. * A random dart of each face is put in the darts_ array. */ - unsigned int add_faces(unsigned int n) + uint32 add_faces(uint32 n) { darts_.clear(); - unsigned int count = 0u; - for (unsigned int i = 0u; i < n; ++i) + uint32 count = 0u; + for (uint32 i = 0u; i < n; ++i) { - unsigned int m = 1u + std::rand() % 10u; + uint32 m = 1u + std::rand() % 10u; Dart d = add_face_topo(m); count += m; @@ -118,7 +118,7 @@ TEST_F(CMap1TopoTest, phi1_sew_unsew) { add_vertices(NB_MAX); - for (unsigned int i = 0u; i < NB_MAX; ++i) + for (uint32 i = 0u; i < NB_MAX; ++i) { Dart d = darts_[std::rand() % NB_MAX]; Dart e = darts_[std::rand() % NB_MAX]; @@ -154,7 +154,7 @@ TEST_F(CMap1TopoTest, add_face_topo) EXPECT_EQ(nb_cells(), 11u); EXPECT_EQ(nb_cells(), 2u); - unsigned int count_vertices = 11u + add_faces(NB_MAX); + uint32 count_vertices = 11u + add_faces(NB_MAX); EXPECT_EQ(nb_darts(), count_vertices); EXPECT_EQ(nb_cells(), count_vertices); @@ -168,15 +168,15 @@ TEST_F(CMap1TopoTest, add_face_topo) */ TEST_F(CMap1TopoTest, remove_face) { - unsigned int count_vertices = add_faces(NB_MAX); - unsigned int count_faces = NB_MAX; + uint32 count_vertices = add_faces(NB_MAX); + uint32 count_faces = NB_MAX; for (Dart d : darts_) { if (std::rand() % 3 == 1) { Face f(d); - unsigned int k = degree(f); + uint32 k = degree(f); remove_face(f); count_vertices -= k; --count_faces; @@ -195,11 +195,11 @@ TEST_F(CMap1TopoTest, remove_face) */ TEST_F(CMap1TopoTest, split_vertex_topo) { - unsigned int count_vertices = add_faces(NB_MAX); + uint32 count_vertices = add_faces(NB_MAX); for (Dart d : darts_) { - unsigned int k = degree(Face(d)); + uint32 k = degree(Face(d)); split_vertex_topo(d); ++count_vertices; EXPECT_EQ(degree(Face(d)), k + 1); @@ -216,12 +216,12 @@ TEST_F(CMap1TopoTest, split_vertex_topo) */ TEST_F(CMap1TopoTest, remove_vertex) { - unsigned int count_vertices = add_faces(NB_MAX); - unsigned int count_faces = NB_MAX; + uint32 count_vertices = add_faces(NB_MAX); + uint32 count_faces = NB_MAX; for (Dart d : darts_) { - unsigned int k = degree(Face(d)); + uint32 k = degree(Face(d)); if (k > 1) { Dart e = phi1(d); @@ -248,11 +248,11 @@ TEST_F(CMap1TopoTest, remove_vertex) */ TEST_F(CMap1TopoTest, reverse_face_topo) { - unsigned int count_vertices = add_faces(NB_MAX); + uint32 count_vertices = add_faces(NB_MAX); for (Dart d : darts_) { - unsigned int k = degree(Face(d)); + uint32 k = degree(Face(d)); std::vector face_darts; face_darts.reserve(k); diff --git a/cgogn/core/tests/cmap/cmap2_test.cpp b/cgogn/core/tests/cmap/cmap2_test.cpp index 3b98d16f..f0cd47a5 100644 --- a/cgogn/core/tests/cmap/cmap2_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_test.cpp @@ -64,7 +64,7 @@ class CMap2Test : public ::testing::Test CMap2Test() { darts_.reserve(NB_MAX); - std::srand(static_cast(std::time(0))); + std::srand(static_cast(std::time(0))); cmap_.add_attribute("darts"); cmap_.add_attribute("vertices"); @@ -79,13 +79,13 @@ class CMap2Test : public ::testing::Test * The face size ranges from 1 to 10. * A random dart of each face is put in the darts_ array. */ - unsigned int add_faces(unsigned int n) + uint32 add_faces(uint32 n) { darts_.clear(); - unsigned int count = 0u; - for (unsigned int i = 0u; i < n; ++i) + uint32 count = 0u; + for (uint32 i = 0u; i < n; ++i) { - unsigned int m = 1u + std::rand() % 10u; + uint32 m = 1u + std::rand() % 10u; Dart d = cmap_.add_face(m); count += m; @@ -104,17 +104,17 @@ class CMap2Test : public ::testing::Test { darts_.clear(); MapBuilder mbuild(cmap_); - unsigned int n; + uint32 n; // Generate NB_MAX random 1-faces (without boundary) - for (unsigned int i = 0u; i < NB_MAX; ++i) + for (uint32 i = 0u; i < NB_MAX; ++i) { n = 1u + std::rand() % 10u; Dart d = mbuild.add_face_topo_parent(n); darts_.push_back(d); } // Sew some pairs off edges - for (unsigned int i = 0u; i < 3u * NB_MAX; ++i) + for (uint32 i = 0u; i < 3u * NB_MAX; ++i) { Dart e1 = darts_[std::rand() % NB_MAX]; n = std::rand() % 10u; @@ -178,7 +178,7 @@ TEST_F(CMap2Test, random_map_generators) */ TEST_F(CMap2Test, add_face) { - unsigned int count_vertices = add_faces(NB_MAX); + uint32 count_vertices = add_faces(NB_MAX); EXPECT_EQ(cmap_.nb_cells(), count_vertices); EXPECT_EQ(cmap_.nb_cells(), count_vertices); @@ -214,7 +214,7 @@ TEST_F(CMap2Test, cut_face) if (cmap_.degree(Face(d)) > 1u) { Dart e = d; // find a second dart in the face of d (distinct from d) - unsigned int i = std::rand() % 10u; + uint32 i = std::rand() % 10u; while (i-- > 0u) e = cmap_.phi1(e); if (e == d) e = cmap_.phi1(e); diff --git a/cgogn/core/tests/cmap/cmap2_topo_test.cpp b/cgogn/core/tests/cmap/cmap2_topo_test.cpp index 3e27818b..377587e5 100644 --- a/cgogn/core/tests/cmap/cmap2_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_topo_test.cpp @@ -65,7 +65,7 @@ class CMap2TopoTest : public CMap2, public ::testing::Test CMap2TopoTest() { darts_.reserve(NB_MAX); - std::srand(static_cast(std::time(0))); + std::srand(static_cast(std::time(0))); } /*! @@ -113,7 +113,7 @@ class CMap2TopoTest : public CMap2, public ::testing::Test void new_open_vertex_embedding(Dart d) { cgogn_assert(phi2(d) == d); - const unsigned int emb = add_attribute_element(); + const uint32 emb = add_attribute_element(); Dart it = d; Dart it1 = phi_1(it); @@ -133,13 +133,13 @@ class CMap2TopoTest : public CMap2, public ::testing::Test * The face size ranges from 1 to 10. * A random dart of each face is put in the darts_ array. */ - unsigned int add_faces(unsigned int n) + uint32 add_faces(uint32 n) { darts_.clear(); - unsigned int count = 0u; - for (unsigned int i = 0u; i < n; ++i) + uint32 count = 0u; + for (uint32 i = 0u; i < n; ++i) { - unsigned int m = 1u + std::rand() % 10u; + uint32 m = 1u + std::rand() % 10u; Dart d = add_face_topo(m); count += m; @@ -157,17 +157,17 @@ class CMap2TopoTest : public CMap2, public ::testing::Test void add_closed_surfaces() { darts_.clear(); - unsigned int n; + uint32 n; // Generate NB_MAX random 1-faces (without boundary) - for (unsigned int i = 0u; i < NB_MAX; ++i) + for (uint32 i = 0u; i < NB_MAX; ++i) { n = 1u + std::rand() % 10; Dart d = Inherit::Inherit::add_face_topo(n); darts_.push_back(d); } // Sew some pairs off 1-edges - for (unsigned int i = 0u; i < 3u * NB_MAX; ++i) + for (uint32 i = 0u; i < 3u * NB_MAX; ++i) { Dart e1 = darts_[std::rand() % NB_MAX]; n = std::rand() % 10u; @@ -214,7 +214,7 @@ TEST_F(CMap2TopoTest, phi2_sew_unsew) { add_faces(NB_MAX); - for (unsigned int i = 0u; i < NB_MAX; ++i) + for (uint32 i = 0u; i < NB_MAX; ++i) { Dart d0 = darts_[std::rand() % NB_MAX]; Dart d2 = phi2(d0); @@ -252,7 +252,7 @@ TEST_F(CMap2TopoTest, add_face_topo) EXPECT_EQ(nb_cells(), 2u); EXPECT_EQ(nb_cells(), 2u); - unsigned int count_vertices = 11u + add_faces(NB_MAX); + uint32 count_vertices = 11u + add_faces(NB_MAX); EXPECT_EQ(nb_darts(), 2u * count_vertices); EXPECT_EQ(nb_cells(), count_vertices); @@ -270,15 +270,15 @@ TEST_F(CMap2TopoTest, cut_edge_topo) { add_closed_surfaces(); - unsigned int count_vertices = nb_cells(); - unsigned int count_edges = nb_cells(); - unsigned int count_faces = nb_cells(); - unsigned int count_volumes = nb_cells(); + uint32 count_vertices = nb_cells(); + uint32 count_edges = nb_cells(); + uint32 count_faces = nb_cells(); + uint32 count_volumes = nb_cells(); for (Dart d : darts_) { - unsigned int k1 = degree(Face(d)); - unsigned int k2 = degree(Face(phi2(d))); + uint32 k1 = degree(Face(d)); + uint32 k2 = degree(Face(phi2(d))); cut_edge_topo(d); if (same_cell(Face(d), Face(phi2(d)))) { @@ -306,10 +306,10 @@ TEST_F(CMap2TopoTest, cut_face_topo) { add_closed_surfaces(); - unsigned int count_vertices = nb_cells(); - unsigned int count_edges = nb_cells(); - unsigned int count_faces = nb_cells(); - unsigned int count_volumes = nb_cells(); + uint32 count_vertices = nb_cells(); + uint32 count_edges = nb_cells(); + uint32 count_faces = nb_cells(); + uint32 count_volumes = nb_cells(); for (Dart d : darts_) { @@ -318,11 +318,11 @@ TEST_F(CMap2TopoTest, cut_face_topo) bool boundary_face = is_boundary(dd); - unsigned int k = degree(Face(dd)); + uint32 k = degree(Face(dd)); if (k > 1u) { Dart e = dd; // find a second dart in the face of d (distinct from d) - unsigned int i = std::rand() % 10u; + uint32 i = std::rand() % 10u; while (i-- > 0u) e = phi1(e); if (e == dd) e = phi1(e); @@ -363,8 +363,8 @@ TEST_F(CMap2TopoTest, close_map) { if (std::rand() % 2 == 1) { - unsigned int n = std::rand() % 10u; - unsigned int k = degree(Face(d)); + uint32 n = std::rand() % 10u; + uint32 k = degree(Face(d)); foreach_dart_of_orbit_until(Face(d), [&] (Dart e) { diff --git a/cgogn/core/tests/utils/name_types_test.cpp b/cgogn/core/tests/utils/name_types_test.cpp index 864f15e0..c7447d9f 100644 --- a/cgogn/core/tests/utils/name_types_test.cpp +++ b/cgogn/core/tests/utils/name_types_test.cpp @@ -31,7 +31,7 @@ TEST(NameTypesTest, NumTypes) using signed_char = signed char; using unsigned_char = unsigned char; using unsigned_short = unsigned short; - using uint = unsigned int; + using uint = cgogn::uint32; using ulint = unsigned long; using llint = long long; using ullint = unsigned long long; @@ -44,7 +44,7 @@ TEST(NameTypesTest, NumTypes) #if _MSC_VER == 1800 // VS2013 EXPECT_EQ(cgogn::name_of_type(char16_t()), "unsigned short"); - EXPECT_EQ(cgogn::name_of_type(char32_t()), "unsigned int"); + EXPECT_EQ(cgogn::name_of_type(char32_t()), "uint32"); #else EXPECT_EQ(cgogn::name_of_type(char16_t()), "char16_t"); EXPECT_EQ(cgogn::name_of_type(char32_t()), "char32_t"); @@ -54,7 +54,7 @@ TEST(NameTypesTest, NumTypes) EXPECT_EQ(cgogn::name_of_type(unsigned_short()), "unsigned short"); EXPECT_EQ(cgogn::name_of_type(int()), "int"); - EXPECT_EQ(cgogn::name_of_type(uint()), "unsigned int"); + EXPECT_EQ(cgogn::name_of_type(uint()), "uint32"); EXPECT_EQ(cgogn::name_of_type(long()), "long"); EXPECT_EQ(cgogn::name_of_type(ulint()), "unsigned long"); EXPECT_EQ(cgogn::name_of_type(llint()), "long long"); diff --git a/cgogn/core/utils/buffers.h b/cgogn/core/utils/buffers.h index 4aad31f7..8ba1a051 100644 --- a/cgogn/core/utils/buffers.h +++ b/cgogn/core/utils/buffers.h @@ -38,8 +38,8 @@ template class Buffers { using value_type = T; - static const unsigned int DEFAULT_SIZE = 128u; - static const unsigned int SHRINK_SIZE = 1024u; + static const uint32 DEFAULT_SIZE = 128u; + static const uint32 SHRINK_SIZE = 1024u; protected: @@ -85,8 +85,8 @@ template <> class Buffers { using value_type = Dart; - static const unsigned int DEFAULT_SIZE = 128u; - static const unsigned int SHRINK_SIZE = 1024u; + static const uint32 DEFAULT_SIZE = 128u; + static const uint32 SHRINK_SIZE = 1024u; protected: diff --git a/cgogn/core/utils/definitions.h b/cgogn/core/utils/definitions.h index dbf5ce38..a84fa13a 100644 --- a/cgogn/core/utils/definitions.h +++ b/cgogn/core/utils/definitions.h @@ -24,6 +24,39 @@ #ifndef CORE_UTILS_DEFINITIONS_H_ #define CORE_UTILS_DEFINITIONS_H_ + +#include + +namespace cgogn +{ +namespace numerics +{ + +using int8 = std::int8_t; +using int16 = std::int16_t; +using int32 = std::int32_t; +using int64 = std::int64_t; + +using uint8 = std::uint8_t; +using uint16 = std::uint16_t; +using uint32 = std::uint32_t; +using uint64 = std::uint64_t; + +using float32 = float; +using float64 = double; + +} +using namespace numerics; +} + + +//#define USING_CGOGN_NUMERICS using cgogn::int8; using cgogn::uint8; \ +// using cgogn::int16; using cgogn::uint16;\ +// using cgogn::int32; using cgogn::uint32;\ +// using cgogn::int64; using cgogn::uint64;\ +// using cgogn::float32; using cgogn::float64; + + /** * \brief No execpt declaration for CGOGN symbols. * For a given type T, std::vector will only use move constructor of T if it's marked noexcept. Same for std::swap. diff --git a/cgogn/core/utils/serialization.cpp b/cgogn/core/utils/serialization.cpp index 5a17b8fb..31136504 100644 --- a/cgogn/core/utils/serialization.cpp +++ b/cgogn/core/utils/serialization.cpp @@ -46,12 +46,12 @@ CGOGN_CORE_API void load(std::istream& istream, std::string* dest, char buffer[2048]; for (std::size_t i = 0; i < quantity; ++i) { - unsigned int size; - istream.read(reinterpret_cast(&size), sizeof(unsigned int)); + uint32 size; + istream.read(reinterpret_cast(&size), sizeof(uint32)); cgogn_assert(size < 2048); istream.read((buffer), size); dest[i].resize(size); - for (unsigned int j=0; j(std::ostream& ostream, std::string const* for (std::size_t i = 0; i < quantity; ++i) { - const unsigned int size = static_cast(src[i].length()); - ostream.write(reinterpret_cast(&size), sizeof(unsigned int)); + const uint32 size = static_cast(src[i].length()); + ostream.write(reinterpret_cast(&size), sizeof(uint32)); const char* str = src[i].c_str(); ostream.write(str, size); } @@ -81,7 +81,7 @@ CGOGN_CORE_API std::size_t data_length(std::string const* src, std: std::size_t total = 0; for (std::size_t i = 0; i < quantity; ++i) { - total += sizeof(unsigned int); // for size + total += sizeof(uint32); // for size total += src[i].length(); } return total; diff --git a/cgogn/core/utils/serialization.h b/cgogn/core/utils/serialization.h index 372dcb02..137d436c 100644 --- a/cgogn/core/utils/serialization.h +++ b/cgogn/core/utils/serialization.h @@ -136,8 +136,8 @@ void load(std::istream& istream, std::vector* dest, std::size_t quantity) for (std::size_t i = 0u; i < quantity; ++i) { - unsigned int vecSize; - istream.read(reinterpret_cast(&vecSize), sizeof(unsigned int)); + uint32 vecSize; + istream.read(reinterpret_cast(&vecSize), sizeof(uint32)); dest[i].resize(vecSize); load(istream, &(dest[i][0]), vecSize); } @@ -152,8 +152,8 @@ void save(std::ostream& ostream, std::vector const* src, std::size_t quantity for (std::size_t i = 0u; i < quantity; ++i) { - const unsigned int size = static_cast(src[i].size()); - ostream.write(reinterpret_cast(&size), sizeof(unsigned int)); + const uint32 size = static_cast(src[i].size()); + ostream.write(reinterpret_cast(&size), sizeof(uint32)); save(ostream, &(src[i][0]), size); } } @@ -167,7 +167,7 @@ std::size_t data_length(std::vector const * src, std::size_t quantity) std::size_t total = 0u; for (std::size_t i = 0u; i < quantity; ++i) { - total += sizeof(unsigned int);// for size + total += sizeof(uint32);// for size total += data_length(&(src[i][0]), src[i].size()); } return total; @@ -183,8 +183,8 @@ void load(std::istream& istream, std::list* dest, std::size_t quantity) for (std::size_t i = 0u; i < quantity; ++i) { - unsigned int listSize; - istream.read(reinterpret_cast(&listSize), sizeof(unsigned int)); + uint32 listSize; + istream.read(reinterpret_cast(&listSize), sizeof(uint32)); std::vector temp; temp.resize(listSize); load(istream, &(temp[0]), listSize); @@ -202,8 +202,8 @@ void save(std::ostream& ostream, std::list const* src, std::size_t quantity) for (std::size_t i = 0u; i < quantity; ++i) { - const unsigned int size = static_cast(src[i].size()); - ostream.write(reinterpret_cast(&size), sizeof(unsigned int)); + const uint32 size = static_cast(src[i].size()); + ostream.write(reinterpret_cast(&size), sizeof(uint32)); for (const auto& elem : src[i]) save(ostream, &elem, 1); } @@ -218,7 +218,7 @@ std::size_t data_length(std::list const* src, std::size_t quantity) std::size_t total = 0u; for (std::size_t i = 0u; i < quantity; ++i) { - total += sizeof(unsigned int); // for size + total += sizeof(uint32); // for size for (const auto& elem : src[i]) total += data_length(&elem, 1); } diff --git a/cgogn/core/utils/thread.cpp b/cgogn/core/utils/thread.cpp index ba02f15c..bbe3bcbe 100644 --- a/cgogn/core/utils/thread.cpp +++ b/cgogn/core/utils/thread.cpp @@ -30,10 +30,10 @@ namespace cgogn { -CGOGN_CORE_API unsigned int NB_THREADS = get_nb_threads(); +CGOGN_CORE_API uint32 NB_THREADS = get_nb_threads(); CGOGN_TLS Buffers* dart_buffers_thread = nullptr; -CGOGN_TLS Buffers* uint_buffers_thread = nullptr; +CGOGN_TLS Buffers* uint_buffers_thread = nullptr; CGOGN_CORE_API void thread_start() { @@ -41,7 +41,7 @@ CGOGN_CORE_API void thread_start() dart_buffers_thread = new Buffers(); if (uint_buffers_thread == nullptr) - uint_buffers_thread = new Buffers(); + uint_buffers_thread = new Buffers(); } CGOGN_CORE_API void thread_stop() @@ -57,7 +57,7 @@ CGOGN_CORE_API Buffers* get_dart_buffers() return dart_buffers_thread; } -CGOGN_CORE_API Buffers* get_uint_buffers() +CGOGN_CORE_API Buffers* get_uint_buffers() { return uint_buffers_thread; } diff --git a/cgogn/core/utils/thread.h b/cgogn/core/utils/thread.h index 8a3b329c..50f28a66 100644 --- a/cgogn/core/utils/thread.h +++ b/cgogn/core/utils/thread.h @@ -45,22 +45,22 @@ class Buffers; /** * \brief The maximum nunmber of threads created by the API. */ -const unsigned int MAX_NB_THREADS = 8u; -CGOGN_CORE_API extern unsigned int NB_THREADS; +const uint32 MAX_NB_THREADS = 8u; +CGOGN_CORE_API extern uint32 NB_THREADS; CGOGN_CORE_API ThreadPool* get_thread_pool(); -inline unsigned int get_nb_threads() +inline uint32 get_nb_threads() { - unsigned int c = std::thread::hardware_concurrency(); + uint32 c = std::thread::hardware_concurrency(); return c < MAX_NB_THREADS ? c : MAX_NB_THREADS; } -const unsigned int PARALLEL_BUFFER_SIZE = 1024u; +const uint32 PARALLEL_BUFFER_SIZE = 1024u; -/// buffers of pre-allocated vectors of dart or unsigned int +/// buffers of pre-allocated vectors of dart or uint32 extern CGOGN_TLS Buffers* dart_buffers_thread; -extern CGOGN_TLS Buffers* uint_buffers_thread; +extern CGOGN_TLS Buffers* uint_buffers_thread; /** * @brief function to call at begin of each thread which use a map @@ -73,7 +73,7 @@ CGOGN_CORE_API void thread_start(); CGOGN_CORE_API void thread_stop(); CGOGN_CORE_API Buffers* get_dart_buffers(); -CGOGN_CORE_API Buffers* get_uint_buffers(); +CGOGN_CORE_API Buffers* get_uint_buffers(); template class ThreadFunction @@ -85,7 +85,7 @@ class ThreadFunction Barrier& sync1_; Barrier& sync2_; bool& finished_; - unsigned int thread_order_; + uint32 thread_order_; public: @@ -95,7 +95,7 @@ class ThreadFunction Barrier& sync1, Barrier& sync2, bool& finished, - unsigned int thread_order + uint32 thread_order ) : f_(f), elements_(elements), diff --git a/cgogn/core/utils/thread_barrier.h b/cgogn/core/utils/thread_barrier.h index 5dd9f11f..bad3396b 100644 --- a/cgogn/core/utils/thread_barrier.h +++ b/cgogn/core/utils/thread_barrier.h @@ -40,9 +40,9 @@ class Barrier { private: - unsigned int init_count_; - unsigned int count_; - unsigned int generation_; + uint32 init_count_; + uint32 count_; + uint32 generation_; std::mutex protect_; std::condition_variable cond_; @@ -53,7 +53,7 @@ class Barrier * constructor * @param count number of threads to syncronize */ - inline Barrier(unsigned int count) : + inline Barrier(uint32 count) : init_count_(count), count_(count), generation_(0) @@ -62,7 +62,7 @@ class Barrier inline void wait() { std::unique_lock lock(protect_); - unsigned int gen = generation_; + uint32 gen = generation_; if (--count_ == 0) { diff --git a/cgogn/core/utils/thread_pool.cpp b/cgogn/core/utils/thread_pool.cpp index 53663c3b..a9088f68 100644 --- a/cgogn/core/utils/thread_pool.cpp +++ b/cgogn/core/utils/thread_pool.cpp @@ -52,14 +52,14 @@ ThreadPool::~ThreadPool() ThreadPool::ThreadPool() : stop_(false) { - for(unsigned int i = 0u; i< cgogn::get_nb_threads() -1u;++i) + for(uint32 i = 0u; i< cgogn::get_nb_threads() -1u;++i) workers_.emplace_back( [this,i] { cgogn::thread_start(); for(;;) { - std::function task; + std::function task; { std::unique_lock lock(this->queue_mutex_); diff --git a/cgogn/core/utils/thread_pool.h b/cgogn/core/utils/thread_pool.h index 20c0b081..35c8c0dd 100644 --- a/cgogn/core/utils/thread_pool.h +++ b/cgogn/core/utils/thread_pool.h @@ -81,7 +81,7 @@ class CGOGN_CORE_API ThreadPool { template auto enqueue(const F& f, Args&&... args) - -> std::future::type>; + -> std::future::type>; std::vector get_threads_ids() const; virtual ~ThreadPool(); @@ -95,7 +95,7 @@ class CGOGN_CORE_API ThreadPool { // need to keep track of threads so we can join them std::vector< std::thread > workers_; // the task queue - std::queue< std::function > tasks_; + std::queue< std::function > tasks_; // synchronization std::mutex queue_mutex_; @@ -107,11 +107,11 @@ class CGOGN_CORE_API ThreadPool { // add new work item to the pool template auto ThreadPool::enqueue(const F& f, Args&&... args) --> std::future::type> +-> std::future::type> { - using return_type = typename std::result_of::type; + using return_type = typename std::result_of::type; - auto task = std::make_shared< std::packaged_task >([f,&args...](unsigned int i) + auto task = std::make_shared< std::packaged_task >([f,&args...](uint32 i) { std::bind(std::cref(f),i, std::forward(args)...)(); } @@ -127,7 +127,7 @@ auto ThreadPool::enqueue(const F& f, Args&&... args) cgogn_assert_not_reached("enqueue on stopped ThreadPool"); } // Push work back on the queue - tasks_.emplace([task](unsigned int i){ (*task)(i); }); + tasks_.emplace([task](uint32 i){ (*task)(i); }); } // Notify a thread that there is new work to perform condition_.notify_one(); diff --git a/cgogn/geometry/algos/centroid.h b/cgogn/geometry/algos/centroid.h index 3caeb0e2..6fcbabc2 100644 --- a/cgogn/geometry/algos/centroid.h +++ b/cgogn/geometry/algos/centroid.h @@ -37,7 +37,7 @@ inline T centroid(const MAP& map, Cell c, const typename MAP::template Ve { T result; result.setZero(); - unsigned int count = 0; + uint32 count = 0; map.foreach_incident_vertex(c, [&] (typename MAP::Vertex v) { result += attribute[v]; diff --git a/cgogn/geometry/algos/ear_triangulation.h b/cgogn/geometry/algos/ear_triangulation.h index f6e2d384..ccc6bb34 100644 --- a/cgogn/geometry/algos/ear_triangulation.h +++ b/cgogn/geometry/algos/ear_triangulation.h @@ -99,7 +99,7 @@ class EarTriangulation bool convex_; /// number off vertices - unsigned int nb_verts_; + uint32 nb_verts_; /// initial face Face face_; @@ -274,7 +274,7 @@ class EarTriangulation { // second pass with no test of intersections with polygons vpp = prem; - for (unsigned int i = 0; i < nb_verts_; ++i) + for (uint32 i = 0; i < nb_verts_; ++i) { vpp->ear_ = ears_.insert(vpp); vpp = vpp->next_; @@ -284,7 +284,7 @@ class EarTriangulation { // second pass test intersections with polygons vpp = prem; - for (unsigned int i = 0; i < nb_verts_; ++i) + for (uint32 i = 0; i < nb_verts_; ++i) { if (vpp->value_ < 5.0f) compute_ear_intersection(vpp); @@ -298,7 +298,7 @@ class EarTriangulation * @brief compute table of vertices indices (embeddings) of triangulation * @param table_indices */ - void compute_indices(std::vector& table_indices) + void compute_indices(std::vector& table_indices) { table_indices.reserve((nb_verts_-2)*3); @@ -393,7 +393,7 @@ class EarTriangulation * @param table_indices table of indices (vertex embedding) to fill (append) */ template -static void compute_ear_triangulation(MAP& map, typename MAP::Face f, const typename MAP::template VertexAttributeHandler& position, std::vector& table_indices) +static void compute_ear_triangulation(MAP& map, typename MAP::Face f, const typename MAP::template VertexAttributeHandler& position, std::vector& table_indices) { EarTriangulation tri(map, f, position); tri.compute_indices(table_indices); diff --git a/cgogn/geometry/algos/normal.h b/cgogn/geometry/algos/normal.h index 7ecd74fa..c7d474be 100644 --- a/cgogn/geometry/algos/normal.h +++ b/cgogn/geometry/algos/normal.h @@ -125,7 +125,7 @@ inline VEC3 vertex_normal(const MAP& map, Cell v, const typename M template inline void compute_normal_faces(MAP& map, const typename MAP::template VertexAttributeHandler& position, typename MAP::template AttributeHandler& normal) { - map.parallel_foreach_cell([&] (Cell f, unsigned int) + map.parallel_foreach_cell([&] (Cell f, uint32) { normal[f] = face_normal(map, f, position); }); @@ -134,7 +134,7 @@ inline void compute_normal_faces(MAP& map, const typename MAP::template VertexAt template inline void compute_normal_vertices(MAP& map, const typename MAP::template VertexAttributeHandler& position, typename MAP::template AttributeHandler& normal) { - map.parallel_foreach_cell([&] (Cell v, unsigned int) + map.parallel_foreach_cell([&] (Cell v, uint32) { normal[v] = vertex_normal(map, v, position); }); @@ -143,7 +143,7 @@ inline void compute_normal_vertices(MAP& map, const typename MAP::template Verte template inline void compute_normal_vertices(MAP& map, const typename MAP::template VertexAttributeHandler& position, const typename MAP::template AttributeHandler& fnormal, typename MAP::template AttributeHandler& normal) { - map.parallel_foreach_cell([&] (Cell v, unsigned int) + map.parallel_foreach_cell([&] (Cell v, uint32) { normal[v] = vertex_normal(map, v, position, fnormal); }); diff --git a/cgogn/geometry/algos/picking.h b/cgogn/geometry/algos/picking.h index 0e5132db..521917a4 100644 --- a/cgogn/geometry/algos/picking.h +++ b/cgogn/geometry/algos/picking.h @@ -59,9 +59,9 @@ inline void picking_internal_face(MAP& m, const typename MAP::template VertexAtt // thread data using Triplet = typename std::vector>; std::vector selected_th(cgogn::get_nb_threads()); - std::vector> ear_indices_th(cgogn::get_nb_threads()); + std::vector> ear_indices_th(cgogn::get_nb_threads()); - m.parallel_foreach_cell([&] (Face f, unsigned int th) + m.parallel_foreach_cell([&] (Face f, uint32 th) { VEC3 inter; if (m.has_degree(f,3)) @@ -74,7 +74,7 @@ inline void picking_internal_face(MAP& m, const typename MAP::template VertexAtt } else { - std::vector& ear_indices = ear_indices_th[th]; + std::vector& ear_indices = ear_indices_th[th]; ear_indices.clear(); cgogn::geometry::compute_ear_triangulation(m,f,position,ear_indices); for(std::size_t i=0; i Scalar(0)) ++np ; diff --git a/cgogn/geometry/tests/algos/algos_test.cpp b/cgogn/geometry/tests/algos/algos_test.cpp index 5d4f893c..604207a0 100644 --- a/cgogn/geometry/tests/algos/algos_test.cpp +++ b/cgogn/geometry/tests/algos/algos_test.cpp @@ -37,6 +37,8 @@ #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) +using namespace cgogn::numerics; + using StdArrayf = cgogn::geometry::Vec_T>; using StdArrayd = cgogn::geometry::Vec_T>; using EigenVec3f = Eigen::Vector3f; @@ -161,7 +163,7 @@ TYPED_TEST(Algos_TEST, EarTriangulation) d = this->map2_.phi1(d); vertex_position[Vertex(d)] = TypeParam(Scalar(0), Scalar(10), Scalar(0)); - std::vector indices; + std::vector indices; cgogn::geometry::compute_ear_triangulation(this->map2_, f, vertex_position, indices); EXPECT_TRUE(indices.size() == 9); diff --git a/cgogn/geometry/types/bounding_box.h b/cgogn/geometry/types/bounding_box.h index 3b4ab475..3acd0d2e 100644 --- a/cgogn/geometry/types/bounding_box.h +++ b/cgogn/geometry/types/bounding_box.h @@ -48,7 +48,7 @@ class BoundingBox using Vec = VEC_T; using Scalar = typename vector_traits::Scalar; using Self = BoundingBox; - static const unsigned int dim_ = vector_traits::SIZE; + static const uint32 dim_ = vector_traits::SIZE; private: @@ -100,7 +100,7 @@ class BoundingBox return p_max_; } - Scalar size(unsigned int coord) const + Scalar size(uint32 coord) const { cgogn_assert(initialized_ && coord < dim_); return p_max_[coord] - p_min_[coord]; @@ -110,7 +110,7 @@ class BoundingBox { cgogn_message_assert(initialized_, "Bounding box not initialized"); Scalar max = p_max_[0] - p_min_[0]; - for(unsigned int i = 1; i < dim_; ++i) + for(uint32 i = 1; i < dim_; ++i) { Scalar size = p_max_[i] - p_min_[i]; if(size > max) @@ -123,7 +123,7 @@ class BoundingBox { cgogn_message_assert(initialized_, "Bounding box not initialized"); Scalar min = p_max_[0] - p_min_[0]; - for(unsigned int i = 1; i < dim_; ++i) + for(uint32 i = 1; i < dim_; ++i) { Scalar size = p_max_[i] - p_min_[i]; if(size < min) @@ -174,7 +174,7 @@ class BoundingBox } else { - for(unsigned int i = 0; i < dim_; ++i) + for(uint32 i = 0; i < dim_; ++i) { if(p[i] < p_min_[i]) p_min_[i] = p[i]; @@ -190,7 +190,7 @@ class BoundingBox cgogn_message_assert(initialized_, "Bounding box not initialized"); Vec bbmin = bb.min(); Vec bbmax = bb.max(); - for(unsigned int i = 0; i < dim_; ++i) + for(uint32 i = 0; i < dim_; ++i) { if(p_max_[i] < bbmin[i]) return false; @@ -206,7 +206,7 @@ class BoundingBox cgogn_message_assert(initialized_, "Bounding box not initialized"); Vec bbmin = bb.min(); Vec bbmax = bb.max(); - for(unsigned int i = 0; i < dim_; ++i) + for(uint32 i = 0; i < dim_; ++i) { if(bbmin[i] < p_min_[i]) p_min_[i] = bbmin[i]; @@ -219,7 +219,7 @@ class BoundingBox bool contains(const Vec& p) const { cgogn_message_assert(initialized_, "Bounding box not initialized"); - for(unsigned int i = 0; i < dim_; ++i) + for(uint32 i = 0; i < dim_; ++i) { if(p_min_[i] > p[i]) return false; diff --git a/cgogn/geometry/types/geometry_traits.h b/cgogn/geometry/types/geometry_traits.h index db0878d0..d50a9ed5 100644 --- a/cgogn/geometry/types/geometry_traits.h +++ b/cgogn/geometry/types/geometry_traits.h @@ -80,19 +80,19 @@ struct nb_components_traits template struct nb_components_traits::value || std::is_floating_point::value >::type > { - const static unsigned int value = 1u; + const static uint32 value = 1u; }; template struct nb_components_traits>> { - const static unsigned int value = size; + const static uint32 value = size; }; template struct nb_components_traits> { - const static unsigned int value = Rows; + const static uint32 value = Rows; }; } // namespace geometry diff --git a/cgogn/io/data_io.h b/cgogn/io/data_io.h index 5952b781..d5c45687 100644 --- a/cgogn/io/data_io.h +++ b/cgogn/io/data_io.h @@ -42,13 +42,13 @@ namespace io /** * @brief The BaseDataIO class : used to read numerical values (scalar & vectors) in mesh files */ -template +template class DataInputGen { public: using Self = DataInputGen; using ChunkArrayGen = cgogn::ChunkArrayGen; - using ChunkArrayContainer = cgogn::ChunkArrayContainer; + using ChunkArrayContainer = cgogn::ChunkArrayContainer; virtual void read_n(std::istream& fp, std::size_t n, bool binary, bool big_endian) = 0; virtual void skip_n(std::istream& fp, std::size_t n, bool binary) = 0; @@ -66,24 +66,24 @@ class DataInputGen virtual void to_chunk_array(ChunkArrayGen* ca_gen) const = 0; virtual ChunkArrayGen* add_attribute(ChunkArrayContainer& cac, const std::string& att_name) const = 0; - virtual unsigned int nb_components() const = 0; + virtual uint32 nb_components() const = 0; virtual ~DataInputGen() {} - template + template inline static std::unique_ptr newDataIO(const std::string type_name); - template - inline static std::unique_ptr newDataIO(const std::string type_name, unsigned int nb_components); + template + inline static std::unique_ptr newDataIO(const std::string type_name, uint32 nb_components); // This versions converts the data to the type T (if T is different from the type that has been read in the file) - template + template inline static std::unique_ptr newDataIO(const std::string type_name); // This versions converts the data to the type T (if T is different from the type that has been read in the file) - template - inline static std::unique_ptr newDataIO(const std::string type_name, unsigned int nb_components); + template + inline static std::unique_ptr newDataIO(const std::string type_name, uint32 nb_components); }; -template +template class DataInput : public DataInputGen { public: @@ -224,7 +224,7 @@ class DataInput : public DataInputGen virtual void to_chunk_array(ChunkArrayGen* ca_gen) const override { ChunkArray* ca = dynamic_cast(ca_gen); - unsigned int i = 0u; + uint32 i = 0u; for (auto& x : data_) ca->operator[](i++) = x; } @@ -244,7 +244,7 @@ class DataInput : public DataInputGen return &data_; } - virtual unsigned int nb_components() const override + virtual uint32 nb_components() const override { return geometry::nb_components_traits::value; } @@ -267,8 +267,8 @@ class DataInput : public DataInputGen std::vector data_; }; -template -template +template +template std::unique_ptr> DataInputGen::newDataIO(const std::string type_name) { const DataType type = get_data_type(type_name); @@ -290,8 +290,8 @@ std::unique_ptr> DataInputGen::newDataIO(co } } -template -template +template +template std::unique_ptr> DataInputGen::newDataIO(const std::string type_name) { const DataType type = get_data_type(type_name); @@ -313,9 +313,9 @@ std::unique_ptr> DataInputGen::newDataIO(co } } -template -template -std::unique_ptr> DataInputGen::newDataIO(const std::string type_name, unsigned int nb_components) +template +template +std::unique_ptr> DataInputGen::newDataIO(const std::string type_name, uint32 nb_components) { cgogn_assert(nb_components >=1u && nb_components <= 4u); if (nb_components == 1u) @@ -358,9 +358,9 @@ std::unique_ptr> DataInputGen::newDataIO(co return std::unique_ptr>(); } -template -template -std::unique_ptr> DataInputGen::newDataIO(const std::string type_name, unsigned int nb_components) +template +template +std::unique_ptr> DataInputGen::newDataIO(const std::string type_name, uint32 nb_components) { cgogn_assert(nb_components >=1u && nb_components <= 4u); if (nb_components == 1u) diff --git a/cgogn/io/examples/cmap2_import.cpp b/cgogn/io/examples/cmap2_import.cpp index 3723dd9f..2221bd8f 100644 --- a/cgogn/io/examples/cmap2_import.cpp +++ b/cgogn/io/examples/cmap2_import.cpp @@ -9,9 +9,11 @@ #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) +using namespace cgogn::numerics; + struct MyMapTraits : public cgogn::DefaultMapTraits { - static const unsigned int CHUNK_SIZE = 8192; + static const uint32 CHUNK_SIZE = 8192; }; using Map2 = cgogn::CMap2; @@ -38,23 +40,23 @@ int main(int argc, char** argv) Map2 map; - for (unsigned int k = 0; k < 2; ++k) + for (uint32 k = 0; k < 2; ++k) { cgogn::io::import_surface(map, surfaceMesh); - unsigned int nb_darts = 0; + uint32 nb_darts = 0; map.foreach_dart_nomask([&nb_darts] (cgogn::Dart) { nb_darts++; }); std::cout << "nb darts -> " << nb_darts << std::endl; - unsigned int nb_darts_2 = 0; - std::vector nb_darts_per_thread(cgogn::NB_THREADS - 1); - for (unsigned int& n : nb_darts_per_thread) + uint32 nb_darts_2 = 0; + std::vector nb_darts_per_thread(cgogn::NB_THREADS - 1); + for (uint32& n : nb_darts_per_thread) n = 0; - map.parallel_foreach_dart_nomask([&nb_darts_per_thread] (cgogn::Dart, unsigned int thread_index) + map.parallel_foreach_dart_nomask([&nb_darts_per_thread] (cgogn::Dart, uint32 thread_index) { nb_darts_per_thread[thread_index]++; }); - for (unsigned int n : nb_darts_per_thread) + for (uint32 n : nb_darts_per_thread) nb_darts_2 += n; std::cout << "nb darts // -> " << nb_darts_2 << std::endl; @@ -78,19 +80,19 @@ int main(int argc, char** argv) // std::cout << "Vertex container is well referenced ? -> " << std::boolalpha << cgogn::is_container_well_referenced(map) << std::endl; // std::cout << "Face container is well referenced ? -> " << std::boolalpha << cgogn::is_container_well_referenced(map) << std::endl; - unsigned int nb_faces = 0; + uint32 nb_faces = 0; map.foreach_cell([&nb_faces] (Map2::Face) { nb_faces++; }); std::cout << "nb faces -> " << nb_faces << std::endl; - unsigned int nb_faces_2 = 0; - std::vector nb_faces_per_thread(cgogn::NB_THREADS - 1); - for (unsigned int& n : nb_faces_per_thread) + uint32 nb_faces_2 = 0; + std::vector nb_faces_per_thread(cgogn::NB_THREADS - 1); + for (uint32& n : nb_faces_per_thread) n = 0; - map.parallel_foreach_cell([&nb_faces_per_thread] (Map2::Face, unsigned int thread_index) + map.parallel_foreach_cell([&nb_faces_per_thread] (Map2::Face, uint32 thread_index) { nb_faces_per_thread[thread_index]++; }); - for (unsigned int n : nb_faces_per_thread) + for (uint32 n : nb_faces_per_thread) nb_faces_2 += n; std::cout << "nb faces // -> " << nb_faces_2 << std::endl; @@ -99,9 +101,9 @@ int main(int argc, char** argv) start = std::chrono::system_clock::now(); - for (unsigned int i = 0; i < 10; ++i) + for (uint32 i = 0; i < 10; ++i) { -// map.parallel_foreach_cell([&] (Map2::Face f, unsigned int) +// map.parallel_foreach_cell([&] (Map2::Face f, uint32) // map.foreach_cell([&] (Map2::Face f) // { // Vec3 v1 = vertex_position[map.phi1(f.dart)] - vertex_position[f.dart]; @@ -114,13 +116,13 @@ int main(int argc, char** argv) cgogn::geometry::template compute_normal_faces(map, vertex_position, face_normal); } - for (unsigned int i = 0; i < 10; ++i) + for (uint32 i = 0; i < 10; ++i) { -// map.parallel_foreach_cell([&] (Map2::Vertex v, unsigned int) +// map.parallel_foreach_cell([&] (Map2::Vertex v, uint32) // map.foreach_cell([&] (Map2::Vertex v) // { // Vec3 sum({0, 0, 0}); -// unsigned int nb_incident = 0; +// uint32 nb_incident = 0; // map.foreach_incident_face(v, [&] (Map2::Face f) // { // ++nb_incident; diff --git a/cgogn/io/examples/cmap3_import.cpp b/cgogn/io/examples/cmap3_import.cpp index f1dc1c0f..4661f1a8 100644 --- a/cgogn/io/examples/cmap3_import.cpp +++ b/cgogn/io/examples/cmap3_import.cpp @@ -7,6 +7,7 @@ #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) +using namespace cgogn::numerics; using Map3 = cgogn::CMap3; @@ -34,7 +35,7 @@ int main(int argc, char** argv) Map3 map; - for (unsigned int k = 0; k < 2; ++k) + for (uint32 k = 0; k < 2; ++k) { cgogn::io::import_volume(map, volumeMesh); @@ -48,13 +49,13 @@ int main(int argc, char** argv) map.enable_topo_cache(); map.enable_topo_cache(); - unsigned int nbw = 0u; + uint32 nbw = 0u; map.foreach_cell([&nbw] (Map3::Volume) { ++nbw; }); - unsigned int nbf = 0u; + uint32 nbf = 0u; map.foreach_cell([&] (Map3::Face f) { ++nbf; @@ -62,18 +63,18 @@ int main(int argc, char** argv) Vec3 v2 = vertex_position[Map3::Vertex(map.phi_1(f.dart))] - vertex_position[Map3::Vertex(f.dart)]; }); - unsigned int nbv = 0; + uint32 nbv = 0; map.foreach_cell([&] (Map3::Vertex v) { ++nbv; - unsigned int nb_incident = 0; + uint32 nb_incident = 0; map.foreach_incident_face(v, [&] (Map3::Face /*f*/) { ++nb_incident; }); }); - unsigned int nbe = 0; + uint32 nbe = 0; map.foreach_cell([&nbe] (Map3::Edge) { ++nbe; diff --git a/cgogn/io/io_utils.cpp b/cgogn/io/io_utils.cpp index 82c97c33..42f87489 100644 --- a/cgogn/io/io_utils.cpp +++ b/cgogn/io/io_utils.cpp @@ -46,9 +46,9 @@ CGOGN_IO_API std::vector zlib_decompress(const char* input, DataT std::uint64_t nb_blocks = UINT64_MAX; std::uint64_t uncompressed_block_size = UINT64_MAX; std::uint64_t last_block_size = UINT64_MAX; - std::vector compressed_size; + std::vector compressed_size; - unsigned int word_size = 4u; + uint32 word_size = 4u; std::vector header_data; if (header_type == DataType::UINT64) { @@ -62,9 +62,9 @@ CGOGN_IO_API std::vector zlib_decompress(const char* input, DataT } else { header_data = base64_decode(input, 0, 24); - nb_blocks = *reinterpret_cast(&header_data[0]); - uncompressed_block_size = *reinterpret_cast(&header_data[4]); - last_block_size = *reinterpret_cast(&header_data[8]); + nb_blocks = *reinterpret_cast(&header_data[0]); + uncompressed_block_size = *reinterpret_cast(&header_data[4]); + last_block_size = *reinterpret_cast(&header_data[8]); compressed_size.resize(nb_blocks); } @@ -76,12 +76,12 @@ CGOGN_IO_API std::vector zlib_decompress(const char* input, DataT header_data = base64_decode(input, header_end, length); if (header_type == DataType::UINT64) { - for (unsigned int i = 0; i < nb_blocks; ++i) - compressed_size[i] = static_cast(*reinterpret_cast(&header_data[8u * i])); + for (uint32 i = 0; i < nb_blocks; ++i) + compressed_size[i] = static_cast(*reinterpret_cast(&header_data[8u * i])); } else { - for (unsigned int i = 0; i < nb_blocks; ++i) - compressed_size[i] = static_cast(*reinterpret_cast(&header_data[4u * i])); + for (uint32 i = 0; i < nb_blocks; ++i) + compressed_size[i] = static_cast(*reinterpret_cast(&header_data[4u * i])); } std::vector data = base64_decode(input, header_end +length); @@ -93,19 +93,19 @@ CGOGN_IO_API std::vector zlib_decompress(const char* input, DataT zstream.zalloc = Z_NULL; zstream.zfree = Z_NULL; zstream.opaque = Z_NULL; - unsigned int in_data_it = 0u; - unsigned int out_data_it = 0u; - for (unsigned int i = 0; i < nb_blocks; ++i) + uint32 in_data_it = 0u; + uint32 out_data_it = 0u; + for (uint32 i = 0; i < nb_blocks; ++i) { ret = inflateInit(&zstream); zstream.avail_in = compressed_size[i]; zstream.next_in = &data[in_data_it]; - zstream.avail_out = static_cast( (i == nb_blocks - 1u) ? last_block_size : uncompressed_block_size ); + zstream.avail_out = static_cast( (i == nb_blocks - 1u) ? last_block_size : uncompressed_block_size ); zstream.next_out = &res[out_data_it]; ret = inflate(&zstream, Z_NO_FLUSH); ret = inflateEnd(&zstream); in_data_it += compressed_size[i]; - out_data_it += static_cast(uncompressed_block_size); + out_data_it += static_cast(uncompressed_block_size); } return res; } diff --git a/cgogn/io/io_utils.h b/cgogn/io/io_utils.h index 5ccd007c..aa354999 100644 --- a/cgogn/io/io_utils.h +++ b/cgogn/io/io_utils.h @@ -78,7 +78,7 @@ namespace internal // #1 return default value when U and T don't have the same nb of components. template -inline auto convert(const T&) -> typename std::enable_if::value>, std::integral_constant::value>>::value,U>::type +inline auto convert(const T&) -> typename std::enable_if::value>, std::integral_constant::value>>::value,U>::type { std::cerr << "Cannot convert data of type\"" << name_of_type(T()) << "\" to type \"" << name_of_type(U()) << "\"." << std::endl; return U(); @@ -93,10 +93,10 @@ inline auto convert(const T&x) -> typename std::enable_if<(std::is_arithmetic // #3 copy component by component if both type have the same number of components (>1) template -inline auto convert(const T& x) -> typename std::enable_if::value && !std::is_floating_point::value && std::is_same< std::integral_constant::value>, std::integral_constant::value>>::value, U>::type +inline auto convert(const T& x) -> typename std::enable_if::value && !std::is_floating_point::value && std::is_same< std::integral_constant::value>, std::integral_constant::value>>::value, U>::type { U res; - for(unsigned int i = 0u; i < geometry::nb_components_traits::value ; ++i) + for(uint32 i = 0u; i < geometry::nb_components_traits::value ; ++i) res[i] = typename geometry::vector_traits::Scalar(x[i]); return res; } diff --git a/cgogn/io/lm6_io.h b/cgogn/io/lm6_io.h index 622e92df..464bf8ee 100644 --- a/cgogn/io/lm6_io.h +++ b/cgogn/io/lm6_io.h @@ -85,7 +85,7 @@ class LM6VolumeImport : public VolumeImport GmfGotoKwd(mesh_index, GmfVertices); for (int i = 0 ; i < number_of_vertices; ++i) { - unsigned int idx = this->vertex_attributes_.template insert_lines<1>(); + uint32 idx = this->vertex_attributes_.template insert_lines<1>(); std::array v; (void) GmfGetLin(mesh_index, GmfVertices, &v[0],&v[1], &v[2], &ref); position->operator [](idx)[0] = v[0]; diff --git a/cgogn/io/map_export.h b/cgogn/io/map_export.h index a19c89e6..7eb2f2e0 100644 --- a/cgogn/io/map_export.h +++ b/cgogn/io/map_export.h @@ -72,9 +72,9 @@ bool export_off(MAP& map, const typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); + typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); ids.set_all_container_values(UINT_MAX); - unsigned int count = 0; + uint32 count = 0; map.template foreach_cell([&] (Face f) { map.template foreach_incident_vertex(f, [&] (Vertex v) @@ -89,11 +89,11 @@ bool export_off(MAP& map, const typename MAP::template VertexAttributeHandler prim; + std::vector prim; prim.reserve(20); map.template foreach_cell([&] (Face f) { - unsigned int valence = 0; + uint32 valence = 0; prim.clear(); map.template foreach_incident_vertex(f, [&] (Vertex v) @@ -102,7 +102,7 @@ bool export_off(MAP& map, const typename MAP::template VertexAttributeHandler()); nb_cells[1] = swap_endianness_native_big(map.template nb_cells()); nb_cells[2] = 0; - fp.write(reinterpret_cast(nb_cells),3*sizeof(unsigned int)); + fp.write(reinterpret_cast(nb_cells),3*sizeof(uint32)); // two pass of traversal to avoid huge buffer (with same performance); // first pass to save positions & store contiguous indices - typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); + typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); ids.set_all_container_values(UINT_MAX); - unsigned int count = 0; + uint32 count = 0; - static const unsigned int BUFFER_SZ = 1024*1024; + static const uint32 BUFFER_SZ = 1024*1024; std::vector buffer_pos; buffer_pos.reserve(BUFFER_SZ+3); @@ -167,7 +167,7 @@ bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandle VEC3 P = position[v]; // VEC3 can be double ! float Pf[3]={float(P[0]),float(P[1]),float(P[2])}; - unsigned int* ui_vec = reinterpret_cast(Pf); + uint32* ui_vec = reinterpret_cast(Pf); ui_vec[0] = swap_endianness_native_big(ui_vec[0]); ui_vec[1] = swap_endianness_native_big(ui_vec[1]); ui_vec[2] = swap_endianness_native_big(ui_vec[2]); @@ -192,14 +192,14 @@ bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandle } // second pass to save primitives - std::vector buffer_prims; + std::vector buffer_prims; buffer_prims.reserve(BUFFER_SZ+128);// + 128 to avoid re-allocations - std::vector prim; + std::vector prim; prim.reserve(20); map.template foreach_cell([&] (Face f) { - unsigned int valence = 0; + uint32 valence = 0; prim.clear(); map.template foreach_incident_vertex(f, [&] (Vertex v) @@ -209,18 +209,18 @@ bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandle }); buffer_prims.push_back(swap_endianness_native_big(valence)); - for(unsigned int i: prim) + for(uint32 i: prim) buffer_prims.push_back(swap_endianness_native_big(i)); if (buffer_prims.size() >= BUFFER_SZ) { - fp.write(reinterpret_cast(&(buffer_prims[0])),buffer_prims.size()*sizeof(unsigned int)); + fp.write(reinterpret_cast(&(buffer_prims[0])),buffer_prims.size()*sizeof(uint32)); buffer_prims.clear(); } }); if (!buffer_prims.empty()) { - fp.write(reinterpret_cast(&(buffer_prims[0])),buffer_prims.size()*sizeof(unsigned int)); + fp.write(reinterpret_cast(&(buffer_prims[0])),buffer_prims.size()*sizeof(uint32)); buffer_prims.clear(); buffer_prims.shrink_to_fit(); } @@ -259,9 +259,9 @@ bool export_obj(MAP& map, const typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); + typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); ids.set_all_container_values(UINT_MAX); - unsigned int count = 1; + uint32 count = 1; map.template foreach_cell([&] (Face f) { map.template foreach_incident_vertex(f, [&] (Vertex v) @@ -277,7 +277,7 @@ bool export_obj(MAP& map, const typename MAP::template VertexAttributeHandler prim; + std::vector prim; prim.reserve(20); map.template foreach_cell([&] (Face f) { @@ -322,10 +322,10 @@ bool export_obj(MAP& map, const typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); + typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); ids.set_all_container_values(UINT_MAX); - unsigned int count = 1; - std::vector indices; + uint32 count = 1; + std::vector indices; indices.reserve(map.template nb_cells()); map.template foreach_cell([&] (Face f) { @@ -343,7 +343,7 @@ bool export_obj(MAP& map, const typename MAP::template VertexAttributeHandler prim; + std::vector prim; prim.reserve(20); map.template foreach_cell([&] (Face f) { @@ -388,7 +388,7 @@ bool export_stl_ascii(MAP& map, const typename MAP::template VertexAttributeHand fp << "solid" << filename << std::endl; - std::vector table_indices; + std::vector table_indices; table_indices.reserve(256); map.template foreach_cell([&] (Face f) @@ -410,7 +410,7 @@ bool export_stl_ascii(MAP& map, const typename MAP::template VertexAttributeHand { table_indices.clear(); cgogn::geometry::compute_ear_triangulation(map,f,position,table_indices); - for(unsigned int i=0; i(); - fp.write(reinterpret_cast(header),21*sizeof(unsigned int)); + fp.write(reinterpret_cast(header),21*sizeof(uint32)); // buffer std::array buffer_floats; // +1 for #@! ushort at end of each triangle @@ -472,23 +472,23 @@ bool export_stl_bin(MAP& map, const typename MAP::template VertexAttributeHandle auto write_tri = [&] (const VEC3& A, const VEC3& B, const VEC3& C) { VEC3 N = geometry::triangle_normal(A,B,C); - unsigned int i=0; - for (unsigned int j=0; j<3; ++j) + uint32 i=0; + for (uint32 j=0; j<3; ++j) buffer_floats[i++]= float(N[j]); - for (unsigned int j=0; j<3; ++j) + for (uint32 j=0; j<3; ++j) buffer_floats[i++]= float(A[j]); - for (unsigned int j=0; j<3; ++j) + for (uint32 j=0; j<3; ++j) buffer_floats[i++]= float(B[j]); - for (unsigned int j=0; j<3; ++j) + for (uint32 j=0; j<3; ++j) buffer_floats[i++]= float(C[j]); fp.write(reinterpret_cast(buffer_floats.data()),12*sizeof(float)+2); // +2 for #@! ushort at end of each triangle }; // indices for ear triangulation - std::vector table_indices; + std::vector table_indices; table_indices.reserve(768); - unsigned int nb_tri = 0; + uint32 nb_tri = 0; // write face cutted in triangle if necessary map.template foreach_cell([&] (Face f) @@ -508,7 +508,7 @@ bool export_stl_bin(MAP& map, const typename MAP::template VertexAttributeHandle { table_indices.clear(); cgogn::geometry::compute_ear_triangulation(map,f,position,table_indices); - for(unsigned int i=0; i(&nb_tri),sizeof(unsigned int)); + fp.write(reinterpret_cast(&nb_tri),sizeof(uint32)); } fp.close(); @@ -540,7 +540,7 @@ std::string nameOfTypePly(const T& v) template <> inline std::string nameOfTypePly(const char&) { return "int8"; } template <> inline std::string nameOfTypePly(const short int&) { return "int16"; } template <> inline std::string nameOfTypePly(const int&) { return "int"; } -template <> inline std::string nameOfTypePly(const unsigned int&) { return "uint"; } +template <> inline std::string nameOfTypePly(const uint32&) { return "uint"; } template <> inline std::string nameOfTypePly(const unsigned char&) { return "uint8"; } template <> inline std::string nameOfTypePly(const unsigned short int&) { return "uint16"; } template <> inline std::string nameOfTypePly(const float&) { return "float"; } @@ -575,9 +575,9 @@ bool export_ply(MAP& map, const typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); + typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); ids.set_all_container_values(UINT_MAX); - unsigned int count = 0; + uint32 count = 0; map.template foreach_cell([&] (Face f) { map.template foreach_incident_vertex(f, [&] (Vertex v) @@ -592,11 +592,11 @@ bool export_ply(MAP& map, const typename MAP::template VertexAttributeHandler prim; + std::vector prim; prim.reserve(20); map.template foreach_cell([&] (Face f) { - unsigned int valence = 0; + uint32 valence = 0; prim.clear(); map.template foreach_incident_vertex(f, [&] (Vertex v) @@ -605,7 +605,7 @@ bool export_ply(MAP& map, const typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); + typename MAP::template VertexAttributeHandler ids = map.template add_attribute("indices"); ids.set_all_container_values(UINT_MAX); - unsigned int count = 0; + uint32 count = 0; - static const unsigned int BUFFER_SZ = 1024*1024; + static const uint32 BUFFER_SZ = 1024*1024; std::vector buffer_pos; buffer_pos.reserve(BUFFER_SZ); @@ -682,14 +682,14 @@ bool export_ply_bin(MAP& map, const typename MAP::template VertexAttributeHandle } // second pass to save primitives - std::vector buffer_prims; + std::vector buffer_prims; buffer_prims.reserve(BUFFER_SZ+128);// + 128 to avoid re-allocations - std::vector prim; + std::vector prim; prim.reserve(20); map.template foreach_cell([&] (Face f) { - unsigned int valence = 0; + uint32 valence = 0; prim.clear(); map.template foreach_incident_vertex(f, [&] (Vertex v) @@ -699,18 +699,18 @@ bool export_ply_bin(MAP& map, const typename MAP::template VertexAttributeHandle }); buffer_prims.push_back(valence); - for(unsigned int i: prim) + for(uint32 i: prim) buffer_prims.push_back(i); if (buffer_prims.size() >= BUFFER_SZ) { - fp.write(reinterpret_cast(&(buffer_prims[0])), buffer_prims.size()*sizeof(unsigned int)); + fp.write(reinterpret_cast(&(buffer_prims[0])), buffer_prims.size()*sizeof(uint32)); buffer_prims.clear(); } }); if (!buffer_prims.empty()) { - fp.write(reinterpret_cast(&(buffer_prims[0])), buffer_prims.size()*sizeof(unsigned int)); + fp.write(reinterpret_cast(&(buffer_prims[0])), buffer_prims.size()*sizeof(uint32)); buffer_prims.clear(); buffer_prims.shrink_to_fit(); } diff --git a/cgogn/io/mesh_generation/examples/map3_from_surface.cpp b/cgogn/io/mesh_generation/examples/map3_from_surface.cpp index d8f20098..ffb0fd35 100644 --- a/cgogn/io/mesh_generation/examples/map3_from_surface.cpp +++ b/cgogn/io/mesh_generation/examples/map3_from_surface.cpp @@ -28,6 +28,9 @@ #include #include +using namespace cgogn::numerics; + + using MapTraits = cgogn::DefaultMapTraits; using Map3 = cgogn::CMap3; using Map2 = cgogn::CMap2; @@ -77,13 +80,13 @@ int main(int argc, char** argv) map3.enable_topo_cache(); map3.enable_topo_cache(); - unsigned int nbw = 0u; + uint32 nbw = 0u; map3.foreach_cell([&nbw] (Map3::Volume) { ++nbw; }); - unsigned int nbf = 0u; + uint32 nbf = 0u; map3.foreach_cell([&] (Map3::Face f) { ++nbf; @@ -91,18 +94,18 @@ int main(int argc, char** argv) Vec3 v2 = vertex_position[Map3::Vertex(map3.phi_1(f.dart))] - vertex_position[Map3::Vertex(f.dart)]; }); - unsigned int nbv = 0; + uint32 nbv = 0; map3.foreach_cell([&] (Map3::Vertex v) { ++nbv; - unsigned int nb_incident = 0; + uint32 nb_incident = 0; map3.foreach_incident_face(v, [&] (Map3::Face /*f*/) { ++nb_incident; }); }); - unsigned int nbe = 0; + uint32 nbe = 0; map3.foreach_cell([&nbe] (Map3::Edge) { ++nbe; diff --git a/cgogn/io/mesh_generation/tetgen_io.h b/cgogn/io/mesh_generation/tetgen_io.h index 41d816b7..eb82bb94 100644 --- a/cgogn/io/mesh_generation/tetgen_io.h +++ b/cgogn/io/mesh_generation/tetgen_io.h @@ -51,7 +51,7 @@ // surface.pointlist = new REAL[surface.numberofpoints * 3]; // //for each vertex -// unsigned int i = 0; +// uint32 i = 0; // TraversorV tv(map2); // for(Dart it = tv.begin() ; it != tv.end() ; it = tv.next()) // { @@ -78,7 +78,7 @@ // p->numberofvertices = map2.faceDegree(it); // p->vertexlist = new int[p->numberofvertices] ; -// unsigned int j = 0; +// uint32 j = 0; // Dart dit = it; // do // { @@ -153,14 +153,14 @@ // //create vertices // double* p = volume_->pointlist ; -// std::vector verticesID; +// std::vector verticesID; // verticesID.reserve(volume_->numberofpoints); // AttributeContainer& container = map3.template getAttributeContainer() ; -// for(unsigned int i = 0; i < volume_->numberofpoints; i++) +// for(uint32 i = 0; i < volume_->numberofpoints; i++) // { // typename PFP::VEC3 pos(p[0], p[1], p[2]); -// unsigned int id = container.insertLine(); +// uint32 id = container.insertLine(); // position3[id] = pos; // verticesID.push_back(id); @@ -170,11 +170,11 @@ // //create tetrahedrons // int* t = volume_->tetrahedronlist ; -// for(unsigned int i = 0; i < volume_->numberoftetrahedra; i++) +// for(uint32 i = 0; i < volume_->numberoftetrahedra; i++) // { // Dart d = Algo::Surface::Modelisation::createTetrahedron(map3, false); -// for(unsigned int j = 0; j < 3; j++) +// for(uint32 j = 0; j < 3; j++) // { // FunctorSetEmb fsetemb(map, verticesID[t[j] - volume_->firstnumber]); // map.template foreach_dart_of_orbit(d, fsetemb); @@ -198,7 +198,7 @@ // //create adjacency // int* pn = volume_->neighborlist ; -// for(unsigned int i = 0; i < volume_->numberoftetrahedra; i++) +// for(uint32 i = 0; i < volume_->numberoftetrahedra; i++) // { // for(int j=0; j<4; j++) // { @@ -314,11 +314,11 @@ class TetgenVolumeImport : public VolumeImport ChunkArray* position = this->vertex_attributes_.template add_attribute("position"); //create vertices - std::vector vertices_indices; + std::vector vertices_indices; double* p = volume_->pointlist ; vertices_indices.reserve(this->nb_vertices_); - for(unsigned int i = 0u; i < this->nb_vertices_; ++i) + for(uint32 i = 0u; i < this->nb_vertices_; ++i) { const unsigned id = this->vertex_attributes_.template insert_lines<1>(); position->operator [](id) = VEC3(Scalar(p[0]), Scalar(p[1]), Scalar(p[2])); @@ -328,10 +328,10 @@ class TetgenVolumeImport : public VolumeImport //create tetrahedrons int* t = volume_->tetrahedronlist ; - for(unsigned int i = 0u; i < this->nb_volumes_; ++i) + for(uint32 i = 0u; i < this->nb_volumes_; ++i) { this->volumes_nb_vertices_.push_back(4u); - for(unsigned int j = 0u; j < 3u; j++) + for(uint32 j = 0u; j < 3u; j++) this->volumes_vertex_indices_.push_back(vertices_indices[t[j] - volume_->firstnumber]); t += 4 ; @@ -361,7 +361,7 @@ std::unique_ptr export_tetgen(CMap2& map, const typename C output->pointlist = new TetgenReal[output->numberofpoints * 3]; //for each vertex - unsigned int i = 0u; + uint32 i = 0u; map.foreach_cell([&output,&i,&pos](Vertex v) { const VEC3& vec = pos[v]; @@ -386,7 +386,7 @@ std::unique_ptr export_tetgen(CMap2& map, const typename C p->numberofvertices = map.degree(face); p->vertexlist = new int[p->numberofvertices]; - unsigned int j = 0u; + uint32 j = 0u; map.foreach_incident_vertex(face, [&p,&map,&j](Vertex v) { p->vertexlist[j++] = map.get_embedding(v); diff --git a/cgogn/io/obj_io.h b/cgogn/io/obj_io.h index 1dff2620..5a0fad29 100644 --- a/cgogn/io/obj_io.h +++ b/cgogn/io/obj_io.h @@ -58,10 +58,10 @@ class ObjSurfaceImport : public SurfaceImport { } while (tag != std::string("v")); // lecture des sommets - std::vector vertices_id; + std::vector vertices_id; vertices_id.reserve(102400); - unsigned int i = 0; + uint32 i = 0; do { if (tag == std::string("v")) @@ -75,7 +75,7 @@ class ObjSurfaceImport : public SurfaceImport { VEC3 pos{Scalar(x), Scalar(y), Scalar(z)}; - unsigned int vertex_id = this->vertex_attributes_.template insert_lines<1>(); + uint32 vertex_id = this->vertex_attributes_.template insert_lines<1>(); (*position)[vertex_id] = pos; vertices_id.push_back(vertex_id); @@ -86,7 +86,7 @@ class ObjSurfaceImport : public SurfaceImport { std::getline(fp, line); } while (!fp.eof()); - this->nb_vertices_ = static_cast(vertices_id.size()); + this->nb_vertices_ = static_cast(vertices_id.size()); fp.clear(); fp.seekg(0, std::ios::beg); @@ -100,7 +100,7 @@ class ObjSurfaceImport : public SurfaceImport { this->faces_nb_edges_.reserve(vertices_id.size() * 2); this->faces_vertex_indices_.reserve(vertices_id.size() * 8); - std::vector table; + std::vector table; table.reserve(64); do { @@ -114,25 +114,25 @@ class ObjSurfaceImport : public SurfaceImport { std::string str; oss >> str; - unsigned int ind = 0; + uint32 ind = 0; while ((ind < str.length()) && (str[ind] != '/')) ind++; if (ind > 0) { - unsigned int index; + uint32 index; std::stringstream iss(str.substr(0, ind)); iss >> index; table.push_back(index); } } - unsigned int n = static_cast(table.size()); + uint32 n = static_cast(table.size()); this->faces_nb_edges_.push_back(static_cast(n)); - for (unsigned int j = 0; j < n; ++j) + for (uint32 j = 0; j < n; ++j) { - unsigned int index = table[j] - 1; // indices start at 1 + uint32 index = table[j] - 1; // indices start at 1 this->faces_vertex_indices_.push_back(vertices_id[index]); } this->nb_faces_++; diff --git a/cgogn/io/off_io.h b/cgogn/io/off_io.h index f7920b95..86bf6080 100644 --- a/cgogn/io/off_io.h +++ b/cgogn/io/off_io.h @@ -74,10 +74,10 @@ class OffSurfaceImport : public SurfaceImport { ChunkArray* position = this->vertex_attributes_.template add_attribute("position"); // read vertices position - std::vector vertices_id; + std::vector vertices_id; vertices_id.reserve(this->nb_vertices_); - for (unsigned int i = 0; i < this->nb_vertices_; ++i) + for (uint32 i = 0; i < this->nb_vertices_; ++i) { double x = this->read_double(fp,line); @@ -86,7 +86,7 @@ class OffSurfaceImport : public SurfaceImport { VEC3 pos{Scalar(x), Scalar(y), Scalar(z)}; - unsigned int vertex_id = this->vertex_attributes_.template insert_lines<1>(); + uint32 vertex_id = this->vertex_attributes_.template insert_lines<1>(); (*position)[vertex_id] = pos; vertices_id.push_back(vertex_id); @@ -95,13 +95,13 @@ class OffSurfaceImport : public SurfaceImport { // read faces (vertex indices) this->faces_nb_edges_.reserve(this->nb_faces_); this->faces_vertex_indices_.reserve(this->nb_vertices_ * 8); - for (unsigned int i = 0; i < this->nb_faces_; ++i) + for (uint32 i = 0; i < this->nb_faces_; ++i) { - unsigned int n = this->read_uint(fp,line); + uint32 n = this->read_uint(fp,line); this->faces_nb_edges_.push_back(n); - for (unsigned int j = 0; j < n; ++j) + for (uint32 j = 0; j < n; ++j) { - unsigned int index = this->read_uint(fp,line); + uint32 index = this->read_uint(fp,line); this->faces_vertex_indices_.push_back(vertices_id[index]); } @@ -115,22 +115,22 @@ class OffSurfaceImport : public SurfaceImport { char buffer1[12]; fp.read(buffer1,12); - this->nb_vertices_= swap_endianness_native_big(*(reinterpret_cast(buffer1))); - this->nb_faces_= swap_endianness_native_big(*(reinterpret_cast(buffer1+4))); - this->nb_edges_= swap_endianness_native_big(*(reinterpret_cast(buffer1+8))); + this->nb_vertices_= swap_endianness_native_big(*(reinterpret_cast(buffer1))); + this->nb_faces_= swap_endianness_native_big(*(reinterpret_cast(buffer1+4))); + this->nb_edges_= swap_endianness_native_big(*(reinterpret_cast(buffer1+8))); ChunkArray* position = this->vertex_attributes_.template add_attribute("position"); - static const unsigned int BUFFER_SZ = 1024*1024; + static const uint32 BUFFER_SZ = 1024*1024; float* buff_pos = new float[3*BUFFER_SZ]; - std::vector vertices_id; + std::vector vertices_id; vertices_id.reserve(this->nb_vertices_); { // limit j scope unsigned j = BUFFER_SZ; - for (unsigned int i = 0; i < this->nb_vertices_; ++i, ++j) + for (uint32 i = 0; i < this->nb_vertices_; ++i, ++j) { if (j == BUFFER_SZ) { @@ -142,8 +142,8 @@ class OffSurfaceImport : public SurfaceImport { fp.read(reinterpret_cast(buff_pos), 3 * sizeof(float)*(this->nb_vertices_ - i)); //endian - unsigned int* ptr = reinterpret_cast(buff_pos); - for (unsigned int k = 0; k < 3 * BUFFER_SZ; ++k) + uint32* ptr = reinterpret_cast(buff_pos); + for (uint32 k = 0; k < 3 * BUFFER_SZ; ++k) { *ptr = swap_endianness_native_big(*ptr); ++ptr; @@ -152,7 +152,7 @@ class OffSurfaceImport : public SurfaceImport { VEC3 pos{ buff_pos[3 * j], buff_pos[3 * j + 1], buff_pos[3 * j + 2] }; - unsigned int vertex_id = this->vertex_attributes_.template insert_lines<1>(); + uint32 vertex_id = this->vertex_attributes_.template insert_lines<1>(); (*position)[vertex_id] = pos; vertices_id.push_back(vertex_id); @@ -163,19 +163,19 @@ class OffSurfaceImport : public SurfaceImport { // read faces (vertex indices) - unsigned int* buff_ind = new unsigned int[BUFFER_SZ]; + uint32* buff_ind = new uint32[BUFFER_SZ]; this->faces_nb_edges_.reserve(this->nb_faces_); this->faces_vertex_indices_.reserve(this->nb_vertices_ * 8); - unsigned int* ptr = buff_ind; - unsigned int nb_read = BUFFER_SZ; - for (unsigned int i = 0; i < this->nb_faces_; ++i) + uint32* ptr = buff_ind; + uint32 nb_read = BUFFER_SZ; + for (uint32 i = 0; i < this->nb_faces_; ++i) { if (nb_read == BUFFER_SZ) { - fp.read(reinterpret_cast(buff_ind),BUFFER_SZ*sizeof(unsigned int)); + fp.read(reinterpret_cast(buff_ind),BUFFER_SZ*sizeof(uint32)); ptr = buff_ind; - for (unsigned int k=0; k< BUFFER_SZ;++k) + for (uint32 k=0; k< BUFFER_SZ;++k) { *ptr = swap_endianness_native_big(*ptr); ++ptr; @@ -184,17 +184,17 @@ class OffSurfaceImport : public SurfaceImport { nb_read =0; } - unsigned int n = *ptr++; + uint32 n = *ptr++; nb_read++; this->faces_nb_edges_.push_back(n); - for (unsigned int j = 0; j < n; ++j) + for (uint32 j = 0; j < n; ++j) { if (nb_read == BUFFER_SZ) { - fp.read(reinterpret_cast(buff_ind),BUFFER_SZ*sizeof(unsigned int)); + fp.read(reinterpret_cast(buff_ind),BUFFER_SZ*sizeof(uint32)); ptr = buff_ind; - for (unsigned int k=0; k< BUFFER_SZ;++k) + for (uint32 k=0; k< BUFFER_SZ;++k) { *ptr = swap_endianness_native_big(*ptr); ++ptr; @@ -202,7 +202,7 @@ class OffSurfaceImport : public SurfaceImport { ptr = buff_ind; nb_read=0; } - unsigned int index = *ptr++; + uint32 index = *ptr++; nb_read++; this->faces_vertex_indices_.push_back(vertices_id[index]); } @@ -224,7 +224,7 @@ class OffSurfaceImport : public SurfaceImport { return std::stod(line); } - static inline unsigned int read_uint(std::istream& fp, std::string& line) + static inline uint32 read_uint(std::istream& fp, std::string& line) { fp >> line; while (line[0]=='#') @@ -232,7 +232,7 @@ class OffSurfaceImport : public SurfaceImport { fp.ignore(std::numeric_limits::max(), '\n'); fp >> line; } - return static_cast((std::stoul(line))); + return static_cast((std::stoul(line))); } }; diff --git a/cgogn/io/ply_io.h b/cgogn/io/ply_io.h index 8ad28e61..f3bd8164 100644 --- a/cgogn/io/ply_io.h +++ b/cgogn/io/ply_io.h @@ -68,15 +68,15 @@ class PlySurfaceImport : public SurfaceImport { // read vertices position - std::vector vertices_id; + std::vector vertices_id; vertices_id.reserve(this->nb_vertices_); - for (unsigned int i = 0; i < this->nb_vertices_; ++i) + for (uint32 i = 0; i < this->nb_vertices_; ++i) { VEC3 pos; pid.vertex_position(i, pos); - unsigned int vertex_id = this->vertex_attributes_.template insert_lines<1>(); + uint32 vertex_id = this->vertex_attributes_.template insert_lines<1>(); (*position)[vertex_id] = pos; vertices_id.push_back(vertex_id); @@ -93,14 +93,14 @@ class PlySurfaceImport : public SurfaceImport { // read faces (vertex indices) this->faces_nb_edges_.reserve(this->nb_faces_); this->faces_vertex_indices_.reserve(this->nb_vertices_ * 8); - for (unsigned int i = 0; i < this->nb_faces_; ++i) + for (uint32 i = 0; i < this->nb_faces_; ++i) { - unsigned int n = pid.get_face_valence(i); + uint32 n = pid.get_face_valence(i); this->faces_nb_edges_.push_back(n); int* indices = pid.get_face_indices(i); - for (unsigned int j = 0; j < n; ++j) + for (uint32 j = 0; j < n; ++j) { - unsigned int index = (unsigned int)(indices[j]); + uint32 index = (uint32)(indices[j]); this->faces_vertex_indices_.push_back(vertices_id[index]); } } diff --git a/cgogn/io/surface_import.h b/cgogn/io/surface_import.h index 3e815052..7a6b125c 100644 --- a/cgogn/io/surface_import.h +++ b/cgogn/io/surface_import.h @@ -53,22 +53,22 @@ class SurfaceImport : public MeshImportGen using Inherit = MeshImportGen; using Map = CMap2; - static const unsigned int CHUNK_SIZE = MAP_TRAITS::CHUNK_SIZE; + static const uint32 CHUNK_SIZE = MAP_TRAITS::CHUNK_SIZE; template using ChunkArray = cgogn::ChunkArray; - using ChunkArrayContainer = cgogn::ChunkArrayContainer; + using ChunkArrayContainer = cgogn::ChunkArrayContainer; template using AttributeHandler = AttributeHandler; protected: - unsigned int nb_vertices_; - unsigned int nb_edges_; - unsigned int nb_faces_; + uint32 nb_vertices_; + uint32 nb_edges_; + uint32 nb_faces_; - std::vector faces_nb_edges_; - std::vector faces_vertex_indices_; + std::vector faces_nb_edges_; + std::vector faces_vertex_indices_; ChunkArrayContainer vertex_attributes_; ChunkArrayContainer face_attributes_; @@ -121,20 +121,20 @@ class SurfaceImport : public MeshImportGen typename Map::template VertexAttributeHandler> darts_per_vertex = map.template add_attribute, Vertex::ORBIT>("darts_per_vertex"); - unsigned int faces_vertex_index = 0; - std::vector vertices_buffer; + uint32 faces_vertex_index = 0; + std::vector vertices_buffer; vertices_buffer.reserve(16); - for (unsigned int i = 0; i < this->nb_faces_; ++i) + for (uint32 i = 0; i < this->nb_faces_; ++i) { - unsigned int nbe = this->faces_nb_edges_[i]; + uint32 nbe = this->faces_nb_edges_[i]; vertices_buffer.clear(); - unsigned int prev = std::numeric_limits::max(); + uint32 prev = std::numeric_limits::max(); - for (unsigned int j = 0; j < nbe; ++j) + for (uint32 j = 0; j < nbe; ++j) { - unsigned int idx = this->faces_vertex_indices_[faces_vertex_index++]; + uint32 idx = this->faces_vertex_indices_[faces_vertex_index++]; if (idx != prev) { prev = idx; @@ -148,9 +148,9 @@ class SurfaceImport : public MeshImportGen if (nbe > 2) { Dart d = mbuild.add_face_topo_parent(nbe); - for (unsigned int j = 0u; j < nbe; ++j) + for (uint32 j = 0u; j < nbe; ++j) { - const unsigned int vertex_index = vertices_buffer[j]; + const uint32 vertex_index = vertices_buffer[j]; mbuild.template set_embedding(d, vertex_index); darts_per_vertex[vertex_index].push_back(d); d = map.phi1(d); @@ -159,13 +159,13 @@ class SurfaceImport : public MeshImportGen } bool need_vertex_unicity_check = false; - unsigned int nb_boundary_edges = 0; + uint32 nb_boundary_edges = 0; map.foreach_dart([&] (Dart d) { if (map.phi2(d) == d) { - unsigned int vertex_index = map.get_embedding(Vertex(d)); + uint32 vertex_index = map.get_embedding(Vertex(d)); std::vector& next_vertex_darts = darts_per_vertex[Vertex(map.phi1(d))]; bool phi2_found = false; diff --git a/cgogn/io/volume_import.h b/cgogn/io/volume_import.h index 8f8ecdbd..47c163c2 100644 --- a/cgogn/io/volume_import.h +++ b/cgogn/io/volume_import.h @@ -121,11 +121,11 @@ class VolumeImport : public MeshImportGen using Face = typename Map::Face; using Face2 = typename Map::Face2; - static const unsigned int CHUNK_SIZE = MAP_TRAITS::CHUNK_SIZE; + static const uint32 CHUNK_SIZE = MAP_TRAITS::CHUNK_SIZE; template using ChunkArray = cgogn::ChunkArray; - using ChunkArrayContainer = cgogn::ChunkArrayContainer; + using ChunkArrayContainer = cgogn::ChunkArrayContainer; template using AttributeHandler = AttributeHandler; @@ -134,11 +134,11 @@ class VolumeImport : public MeshImportGen virtual ~VolumeImport() override {} protected: - unsigned int nb_vertices_; - unsigned int nb_volumes_; + uint32 nb_vertices_; + uint32 nb_volumes_; - std::vector volumes_nb_vertices_; - std::vector volumes_vertex_indices_; + std::vector volumes_nb_vertices_; + std::vector volumes_vertex_indices_; ChunkArrayContainer vertex_attributes_; ChunkArrayContainer volume_attributes_; @@ -177,24 +177,24 @@ class VolumeImport : public MeshImportGen typename Map::template VertexAttributeHandler> darts_per_vertex = map.template add_attribute, Vertex::ORBIT>("darts_per_vertex"); - unsigned int index = 0u; + uint32 index = 0u; // buffer for tempo faces (used to remove degenerated edges) - std::vector edgesBuffer; + std::vector edgesBuffer; edgesBuffer.reserve(16u); typename Map::DartMarkerStore m(map); //for each volume of table - for(unsigned int i = 0u; i < this->nb_volumes_; ++i) + for(uint32 i = 0u; i < this->nb_volumes_; ++i) { // store volume in buffer, removing degenated faces - const unsigned int nbv = this->volumes_nb_vertices_[i]; + const uint32 nbv = this->volumes_nb_vertices_[i]; edgesBuffer.clear(); - unsigned int prec = std::numeric_limits::max(); - for (unsigned int j = 0u; j < nbv; ++j) + uint32 prec = std::numeric_limits::max(); + for (uint32 j = 0u; j < nbv; ++j) { - unsigned int em = this->volumes_vertex_indices_[index++]; + uint32 em = this->volumes_vertex_indices_[index++]; if (em != prec) { prec = em; @@ -268,7 +268,7 @@ class VolumeImport : public MeshImportGen std::size_t buffer_id = 0ul; for (Dart dv : vertices_of_prism) { - const unsigned int emb = edgesBuffer[buffer_id++]; + const uint32 emb = edgesBuffer[buffer_id++]; mbuild.init_parent_vertex_embedding(dv,emb); Dart dd = dv; @@ -326,7 +326,7 @@ class VolumeImport : public MeshImportGen //reconstruct neighbourhood - unsigned int nbBoundaryFaces = 0u; + uint32 nbBoundaryFaces = 0u; map.foreach_dart([&] (Dart d) { if (m.is_marked(d)) @@ -354,8 +354,8 @@ class VolumeImport : public MeshImportGen if (!good_dart.is_nil()) //not a boundary faces { - const unsigned int degD = map.degree(Face(d)); - const unsigned int degGD = map.degree(Face(good_dart)); + const uint32 degD = map.degree(Face(d)); + const uint32 degGD = map.degree(Face(good_dart)); if(degD == degGD) // normal case : the two opposite faces have the same degree { @@ -476,7 +476,7 @@ class VolumeImport : public MeshImportGen } template - void add_hexa(ChunkArrayconst& pos,unsigned int p0, unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned int p5, unsigned int p6, unsigned int p7, bool check_orientation) + void add_hexa(ChunkArrayconst& pos,uint32 p0, uint32 p1, uint32 p2, uint32 p3, uint32 p4, uint32 p5, uint32 p6, uint32 p7, bool check_orientation) { if (check_orientation) this->reoriente_hexa(pos, p0, p1, p2, p3, p4, p5, p6, p7); @@ -491,7 +491,7 @@ class VolumeImport : public MeshImportGen this->volumes_vertex_indices_.push_back(p7); } template - inline void reoriente_hexa(ChunkArrayconst& pos, unsigned int& p0, unsigned int& p1, unsigned int& p2, unsigned int& p3, unsigned int& p4, unsigned int& p5, unsigned int& p6, unsigned int& p7) + inline void reoriente_hexa(ChunkArrayconst& pos, uint32& p0, uint32& p1, uint32& p2, uint32& p3, uint32& p4, uint32& p5, uint32& p6, uint32& p7) { if (geometry::test_orientation_3D(pos[p4], pos[p0],pos[p1],pos[p2]) == geometry::Orientation3D::OVER) { @@ -503,7 +503,7 @@ class VolumeImport : public MeshImportGen } template - void add_tetra(ChunkArrayconst& pos,unsigned int p0, unsigned int p1, unsigned int p2, unsigned int p3, bool check_orientation) + void add_tetra(ChunkArrayconst& pos,uint32 p0, uint32 p1, uint32 p2, uint32 p3, bool check_orientation) { if (check_orientation) this->reoriente_tetra(pos,p0,p1,p2,p3); @@ -515,14 +515,14 @@ class VolumeImport : public MeshImportGen } template - inline void reoriente_tetra(ChunkArrayconst& pos, unsigned int& p0, unsigned int& p1, unsigned int& p2, unsigned int& p3) + inline void reoriente_tetra(ChunkArrayconst& pos, uint32& p0, uint32& p1, uint32& p2, uint32& p3) { if (geometry::test_orientation_3D(pos[p0], pos[p1],pos[p2],pos[p3]) == geometry::Orientation3D::OVER) std::swap(p1, p2); } template - void add_pyramid(ChunkArrayconst& pos,unsigned int p0, unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, bool check_orientation) + void add_pyramid(ChunkArrayconst& pos,uint32 p0, uint32 p1, uint32 p2, uint32 p3, uint32 p4, bool check_orientation) { this->volumes_nb_vertices_.push_back(5u); if (check_orientation) @@ -535,14 +535,14 @@ class VolumeImport : public MeshImportGen } template - inline void reoriente_pyramid(ChunkArrayconst& pos, unsigned int& p0, unsigned int& p1, unsigned int& p2, unsigned int& p3, unsigned int& p4) + inline void reoriente_pyramid(ChunkArrayconst& pos, uint32& p0, uint32& p1, uint32& p2, uint32& p3, uint32& p4) { if (geometry::test_orientation_3D(pos[p4], pos[p0],pos[p1],pos[p2]) == geometry::Orientation3D::OVER) std::swap(p1, p3); } template - void add_triangular_prism(ChunkArrayconst& pos,unsigned int p0, unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned int p5, bool check_orientation) + void add_triangular_prism(ChunkArrayconst& pos,uint32 p0, uint32 p1, uint32 p2, uint32 p3, uint32 p4, uint32 p5, bool check_orientation) { if (check_orientation) this->reoriente_triangular_prism(pos,p0,p1,p2,p3,p4,p5); @@ -556,7 +556,7 @@ class VolumeImport : public MeshImportGen } template - inline void reoriente_triangular_prism(ChunkArrayconst& pos, unsigned int& p0, unsigned int& p1, unsigned int& p2, unsigned int& p3, unsigned int& p4, unsigned int& p5) + inline void reoriente_triangular_prism(ChunkArrayconst& pos, uint32& p0, uint32& p1, uint32& p2, uint32& p3, uint32& p4, uint32& p5) { if (geometry::test_orientation_3D(pos[p3], pos[p0],pos[p1],pos[p2]) == geometry::Orientation3D::OVER) { diff --git a/cgogn/io/vtk_io.h b/cgogn/io/vtk_io.h index 47800c1f..b12ed283 100644 --- a/cgogn/io/vtk_io.h +++ b/cgogn/io/vtk_io.h @@ -39,7 +39,7 @@ namespace cgogn namespace io { -template +template class VtkIO { public : @@ -86,9 +86,9 @@ public : protected : DataInput positions_; - DataInput cells_; + DataInput cells_; DataInput cell_types_; - DataInput offsets_; + DataInput offsets_; protected : virtual void add_vertex_attribute(const DataInputGen& attribute_data, const std::string& attribute_name) = 0; @@ -150,8 +150,8 @@ protected : vtk_type = VTK_MESH_TYPE::POLYDATA; } - unsigned int nb_vertices = 0u; - unsigned int nb_cells = 0u; + uint32 nb_vertices = 0u; + uint32 nb_cells = 0u; if (vtk_type == VTK_MESH_TYPE::UNSTRUCTURED_GRID || vtk_type == VTK_MESH_TYPE::POLYDATA) { @@ -175,7 +175,7 @@ protected : } else { if (word == "CELLS" || word == "POLYGONS" || word == "TRIANGLE_STRIPS") { - unsigned int size; + uint32 size; sstream >> nb_cells >> size; cells_.read_n(fp, size, !ascii_file, big_endian); @@ -200,14 +200,14 @@ protected : } else { if (word == "CELL_TYPES") { - unsigned int nbc; + uint32 nbc; sstream >> nbc; cell_types_.read_n(fp, nbc, !ascii_file, big_endian); } else { if (word == "POINT_DATA" || word == "CELL_DATA") { const bool cell_data = (word == "CELL_DATA"); - unsigned int nb_data; + uint32 nb_data; sstream >> nb_data; if (!cell_data) @@ -228,7 +228,7 @@ protected : const bool is_vector = !(word == "SCALARS"); std::string att_name; std::string att_type; - unsigned int num_comp = is_vector? 3u : 1u; + uint32 num_comp = is_vector? 3u : 1u; sstream >> att_name >> att_type >> num_comp; std::cout << "reading attribute \"" << att_name << "\" of type " << att_type << " (" << num_comp << " components)." << std::endl; @@ -256,9 +256,9 @@ protected : if (word == "FIELD") { std::string field_name; - unsigned int num_arrays = 0u; + uint32 num_arrays = 0u; sstream >> field_name >> num_arrays; - for (unsigned int i = 0u ; i< num_arrays; ++i) + for (uint32 i = 0u ; i< num_arrays; ++i) { do { std::getline(fp,line); @@ -267,8 +267,8 @@ protected : sstream.str(line); sstream.clear(); std::string data_name; - unsigned int nb_comp; - //unsigned int nb_data; already declared + uint32 nb_comp; + //uint32 nb_data; already declared std::string data_type; sstream >> data_name >> nb_comp >> nb_data >> data_type; std::cout << "reading field \"" << data_name << "\" of type " << data_type << " (" << nb_comp << " components)." << std::endl; @@ -283,7 +283,7 @@ protected : if (word == "LOOKUP_TABLE") { std::string table_name; - /*unsigned int*/ nb_data = 0u; + /*uint32*/ nb_data = 0u; sstream >> table_name >> nb_data; std::cout << "ignoring the definition of the lookuptable named \"" << table_name << "\"" << std::endl; if (ascii_file) @@ -337,7 +337,7 @@ protected : cgogn_assert(root_node != nullptr); const bool little_endian = (to_lower(std::string(root_node->Attribute("byte_order"))) == "littleendian"); - std::string header_type("unsigned int"); + std::string header_type("uint32"); if (root_node->Attribute("header_type")) header_type = vtk_data_type_to_cgogn_name_of_type(root_node->Attribute("header_type")); @@ -350,8 +350,8 @@ protected : XMLElement* piece_node = grid_node->FirstChildElement("Piece"); cgogn_assert(piece_node != nullptr); - unsigned int nb_vertices = 0u; - unsigned int nb_cells = 0u; + uint32 nb_vertices = 0u; + uint32 nb_cells = 0u; piece_node->QueryUnsignedAttribute("NumberOfPoints",&nb_vertices); piece_node->QueryUnsignedAttribute("NumberOfCells",&nb_cells); @@ -384,7 +384,7 @@ protected : if (vertex_data->Attribute("Name")) data_name = to_lower(std::string(vertex_data->Attribute("Name"))); const bool binary = (to_lower(std::string(vertex_data->Attribute("format", nullptr))) == "binary"); - unsigned int nb_comp = 1; + uint32 nb_comp = 1; vertex_data->QueryUnsignedAttribute("NumberOfComponents", &nb_comp); const std::string type = vtk_data_type_to_cgogn_name_of_type(std::string(vertex_data->Attribute("type", nullptr))); @@ -451,7 +451,7 @@ protected : { const std::string& data_name = to_lower(std::string(cell_data->Attribute("Name"))); const bool binary = (to_lower(std::string(cell_data->Attribute("format", nullptr))) == "binary"); - unsigned int nb_comp = 1; + uint32 nb_comp = 1; cell_data->QueryUnsignedAttribute("NumberOfComponents", &nb_comp); std::string type = vtk_data_type_to_cgogn_name_of_type(std::string(cell_data->Attribute("type", nullptr))); @@ -470,17 +470,17 @@ protected : mem_stream = make_unique(ascii_data); if (data_name == "connectivity") { - const unsigned int last_offset = this->offsets_.get_vec()->back(); - auto cells = DataInputGen::template newDataIO(type); + const uint32 last_offset = this->offsets_.get_vec()->back(); + auto cells = DataInputGen::template newDataIO(type); cells->read_n(*mem_stream, last_offset,binary,!little_endian); - this->cells_ = *dynamic_cast_unique_ptr>(cells->simplify()); + this->cells_ = *dynamic_cast_unique_ptr>(cells->simplify()); } else { if (data_name == "offsets") { - auto offsets = DataInputGen::template newDataIO(type); + auto offsets = DataInputGen::template newDataIO(type); offsets->read_n(*mem_stream, nb_cells,binary,!little_endian); - this->offsets_ = *dynamic_cast_unique_ptr>(offsets->simplify()); + this->offsets_ = *dynamic_cast_unique_ptr>(offsets->simplify()); } else { if (data_name == "types") @@ -525,7 +525,7 @@ protected : { const std::string& data_name = to_lower(std::string(poly_data_array->Attribute("Name"))); const bool binary = (poly_data_array->Attribute("format") && to_lower(std::string(poly_data_array->Attribute("format", nullptr))) == "binary"); - unsigned int nb_comp = 1; + uint32 nb_comp = 1; poly_data_array->QueryUnsignedAttribute("NumberOfComponents", &nb_comp); std::string type; if (poly_data_array->Attribute("type", nullptr)) @@ -546,17 +546,17 @@ protected : mem_stream = make_unique(ascii_data); if (data_name == "connectivity") { - const unsigned int last_offset = this->offsets_.get_vec()->back(); - auto cells = DataInputGen::template newDataIO(type); + const uint32 last_offset = this->offsets_.get_vec()->back(); + auto cells = DataInputGen::template newDataIO(type); cells->read_n(*mem_stream, last_offset,binary,!little_endian); - this->cells_ = *dynamic_cast_unique_ptr>(cells->simplify()); + this->cells_ = *dynamic_cast_unique_ptr>(cells->simplify()); } else { if (data_name == "offsets") { - auto offsets = DataInputGen::template newDataIO(type); + auto offsets = DataInputGen::template newDataIO(type); offsets->read_n(*mem_stream, nb_cells,binary,!little_endian); - this->offsets_ = *dynamic_cast_unique_ptr>(offsets->simplify()); + this->offsets_ = *dynamic_cast_unique_ptr>(offsets->simplify()); } else std::cout << "Ignoring cell attribute \"" << data_name << "\" of type " << type << "." << std::endl; @@ -635,17 +635,17 @@ class VtkSurfaceImport : public VtkIO: return false; this->fill_surface_import(); - this->nb_vertices_ = static_cast(this->positions_.size()); - this->nb_faces_ = static_cast(this->offsets_.size()); + this->nb_vertices_ = static_cast(this->positions_.size()); + this->nb_faces_ = static_cast(this->offsets_.size()); auto cells_it = this->cells_.get_vec()->begin(); - unsigned int last_offset = 0u; + uint32 last_offset = 0u; for(auto offset_it =this->offsets_.get_vec()->begin(), offset_end = this->offsets_.get_vec()->end() ; offset_it != offset_end; ++offset_it) { - const unsigned int curr_offset = *offset_it; - const unsigned int nb_vertices = curr_offset - last_offset; + const uint32 curr_offset = *offset_it; + const uint32 nb_vertices = curr_offset - last_offset; this->faces_nb_edges_.push_back(nb_vertices); - for (unsigned int i = 0u ; i < nb_vertices; ++i) + for (uint32 i = 0u ; i < nb_vertices; ++i) this->faces_vertex_indices_.push_back(*cells_it++); last_offset = *offset_it; } @@ -685,10 +685,10 @@ class VtkSurfaceImport : public VtkIO: private: inline void fill_surface_import() { - this->nb_vertices_ = static_cast(this->positions_.size()); - this->nb_faces_ = static_cast(this->cell_types_.size()); + this->nb_vertices_ = static_cast(this->positions_.size()); + this->nb_faces_ = static_cast(this->cell_types_.size()); - auto cells_it = static_cast*>(this->cells_.get_data())->begin(); + auto cells_it = static_cast*>(this->cells_.get_data())->begin(); const std::vector* cell_types_vec = static_cast*>(this->cell_types_.get_data()); for(auto cell_types_it = cell_types_vec->begin(); cell_types_it != cell_types_vec->end() ; ) { @@ -697,20 +697,20 @@ class VtkSurfaceImport : public VtkIO: if (cell_type != VTK_CELL_TYPES::VTK_TRIANGLE_STRIP) { - this->faces_nb_edges_.push_back(static_cast(nb_vert)); + this->faces_nb_edges_.push_back(static_cast(nb_vert)); for (std::size_t i = 0ul ; i < nb_vert;++i) { this->faces_vertex_indices_.push_back(*cells_it++); } } else { - std::vector vertexIDS; + std::vector vertexIDS; vertexIDS.reserve(nb_vert); for (std::size_t i = 0ul ; i < nb_vert;++i) { vertexIDS.push_back(*cells_it++); } - for (unsigned int i = 0u ; i < nb_vert -2u; ++i) + for (uint32 i = 0u ; i < nb_vert -2u; ++i) { if (i != 0u) ++this->nb_faces_; @@ -749,12 +749,12 @@ class VtkVolumeImport : public VtkIO:: if (!Inherit_Vtk::parse_vtk_legacy_file(fp)) return false; - this->nb_vertices_ = static_cast(this->positions_.size()); - this->nb_volumes_ = static_cast(this->cell_types_.size()); + this->nb_vertices_ = static_cast(this->positions_.size()); + this->nb_volumes_ = static_cast(this->cell_types_.size()); const std::vector* cell_types_vec = this->cell_types_.get_vec(); - const std::vector* cells_vec = this->cells_.get_vec(); - std::vector cells_buffer; + const std::vector* cells_vec = this->cells_.get_vec(); + std::vector cells_buffer; cells_buffer.reserve(cells_vec->size()); // in the legacy file , the first number of each line is the number of vertices. We need to remove it. @@ -762,7 +762,7 @@ class VtkVolumeImport : public VtkIO:: for (std::vector::const_iterator type_it = cell_types_vec->begin(), end = cell_types_vec->end(); type_it != end; ++type_it) { ++cells_it; - unsigned int vol_nb_verts = 0u; + uint32 vol_nb_verts = 0u; if (*type_it == VTK_CELL_TYPES::VTK_TETRA) vol_nb_verts = 4u; else { @@ -777,7 +777,7 @@ class VtkVolumeImport : public VtkIO:: } } } - for (unsigned int i = 0u ; i < vol_nb_verts;++i) + for (uint32 i = 0u ; i < vol_nb_verts;++i) { cells_buffer.push_back(*cells_it++); } @@ -794,11 +794,11 @@ class VtkVolumeImport : public VtkIO:: if (!Inherit_Vtk::parse_xml_vtu(filename)) return false; - this->nb_vertices_ = static_cast(this->positions_.size()); - this->nb_volumes_ = static_cast(this->cell_types_.size()); + this->nb_vertices_ = static_cast(this->positions_.size()); + this->nb_volumes_ = static_cast(this->cell_types_.size()); const std::vector* cell_types_vec = this->cell_types_.get_vec(); - const std::vector* cells_vec = this->cells_.get_vec(); + const std::vector* cells_vec = this->cells_.get_vec(); ChunkArray* pos = this->vertex_attributes_.template get_attribute("position"); cgogn_assert(pos != nullptr); @@ -833,10 +833,10 @@ class VtkVolumeImport : public VtkIO:: } - inline void add_vtk_volumes(std::vector ids, const std::vector& type_vol, ChunkArray const& pos) + inline void add_vtk_volumes(std::vector ids, const std::vector& type_vol, ChunkArray const& pos) { - unsigned int curr_offset = 0; - for (unsigned int i=0u; i< this->nb_volumes_; ++i) + uint32 curr_offset = 0; + for (uint32 i=0u; i< this->nb_volumes_; ++i) { if (type_vol[i]== VTK_CELL_TYPES::VTK_HEXAHEDRON || type_vol[i]== VTK_CELL_TYPES::VTK_VOXEL) { diff --git a/cgogn/multiresolution/cph/attribute_handler_cph.h b/cgogn/multiresolution/cph/attribute_handler_cph.h index 9f0aea26..7d4da360 100644 --- a/cgogn/multiresolution/cph/attribute_handler_cph.h +++ b/cgogn/multiresolution/cph/attribute_handler_cph.h @@ -90,16 +90,16 @@ class AttributeHandlerCPH : public AttributeHandler // cgogn_message_assert(m->vertexInsertionLevel(d) <= m->m_curLevel, // "Access to the embedding of a vertex inserted after current level") ; -// unsigned int orbit = this->getOrbit() ; -// unsigned int nbSteps = m->m_curLevel - m->vertexInsertionLevel(d) ; -// unsigned int index = m->getEmbedding(d) ; +// uint32 orbit = this->getOrbit() ; +// uint32 nbSteps = m->m_curLevel - m->vertexInsertionLevel(d) ; +// uint32 index = m->getEmbedding(d) ; // AttributeContainer& cont = m->getAttributeContainer() ; -// unsigned int step = 0 ; +// uint32 step = 0 ; // while(step < nbSteps) // { // step++ ; -// unsigned int nextIdx = m->m_nextLevelCell[orbit]->operator[](index) ; +// uint32 nextIdx = m->m_nextLevelCell[orbit]->operator[](index) ; // if (nextIdx == EMBNULL) // { // nextIdx = m->newCell() ; @@ -120,27 +120,27 @@ class AttributeHandlerCPH : public AttributeHandler // cgogn_message_assert(m->vertexInsertionLevel(d) <= m->m_curLevel, // "Access to the embedding of a vertex inserted after current level") ; -// unsigned int orbit = this->getOrbit() ; -// unsigned int nbSteps = m->m_curLevel - m->vertexInsertionLevel(d) ; -// unsigned int index = m->getEmbedding(d) ; +// uint32 orbit = this->getOrbit() ; +// uint32 nbSteps = m->m_curLevel - m->vertexInsertionLevel(d) ; +// uint32 index = m->getEmbedding(d) ; -// unsigned int step = 0 ; +// uint32 step = 0 ; // while(step < nbSteps) // { // step++ ; -// unsigned int next = m->m_nextLevelCell[orbit]->operator[](index) ; +// uint32 next = m->m_nextLevelCell[orbit]->operator[](index) ; // if(next != EMBNULL) index = next ; // else break ; // } // return this->m_attrib->operator[](index); } - T& operator[](unsigned int a) + T& operator[](uint32 a) { return AttributeHandler::operator[](a) ; } - const T& operator[](unsigned int a) const + const T& operator[](uint32 a) const { return AttributeHandler::operator[](a) ; } diff --git a/cgogn/multiresolution/cph/cph2.h b/cgogn/multiresolution/cph/cph2.h index 1c83cb23..55fe5d6f 100644 --- a/cgogn/multiresolution/cph/cph2.h +++ b/cgogn/multiresolution/cph/cph2.h @@ -45,13 +45,13 @@ class CPH2 : public CPHBase protected: - ChunkArray* edge_id_; + ChunkArray* edge_id_; public: CPH2(ChunkArrayContainer& topology): Inherit(topology) { - edge_id_ = topology.template add_attribute("edgeId"); + edge_id_ = topology.template add_attribute("edgeId"); } ~CPH2() override @@ -67,22 +67,22 @@ class CPH2 : public CPHBase * EDGE ID MANAGEMENT * ***************************************************/ - inline unsigned int get_edge_id(Dart d) const + inline uint32 get_edge_id(Dart d) const { return (*edge_id_)[d.index] ; } - inline void set_edge_id(Dart d, unsigned int i) + inline void set_edge_id(Dart d, uint32 i) { (*edge_id_)[d.index] = i ; } - inline unsigned int get_tri_refinement_edge_id(Dart d, Dart e) const + inline uint32 get_tri_refinement_edge_id(Dart d, Dart e) const { - unsigned int d_id = get_edge_id(d); - unsigned int e_id = get_edge_id(e); + uint32 d_id = get_edge_id(d); + uint32 e_id = get_edge_id(e); - unsigned int id = d_id + e_id; + uint32 id = d_id + e_id; if(id == 0u) return 1u; @@ -99,9 +99,9 @@ class CPH2 : public CPHBase return 0u; } - inline unsigned int get_quad_refinement_edge_id(Dart d) const + inline uint32 get_quad_refinement_edge_id(Dart d) const { - unsigned int e_id = get_edge_id(d); + uint32 e_id = get_edge_id(d); if(e_id == 0u) return 1u; diff --git a/cgogn/multiresolution/cph/cph3.h b/cgogn/multiresolution/cph/cph3.h index d4f5a425..2b2fbd0f 100644 --- a/cgogn/multiresolution/cph/cph3.h +++ b/cgogn/multiresolution/cph/cph3.h @@ -42,12 +42,12 @@ class CPH3 : public CPH2 using ChunkArrayContainer = typename Inherit::template ChunkArrayContainer; protected: - ChunkArray* face_id_; + ChunkArray* face_id_; public: CPH3(ChunkArrayContainer& topology): Inherit(topology) { - face_id_ = topology.template add_attribute("faceId"); + face_id_ = topology.template add_attribute("faceId"); } ~CPH3() override @@ -63,22 +63,22 @@ class CPH3 : public CPH2 * FACE ID MANAGEMENT * ***************************************************/ - inline unsigned int get_face_id(Dart d) const + inline uint32 get_face_id(Dart d) const { return (*face_id_)[d.index] ; } - inline void set_face_id(Dart d, unsigned int i) + inline void set_face_id(Dart d, uint32 i) { (*face_id_)[d.index] = i ; } - inline unsigned int get_tri_refinement_face_id(Dart /*d*/, Dart /*e*/) const + inline uint32 get_tri_refinement_face_id(Dart /*d*/, Dart /*e*/) const { return 0u; } - inline unsigned int get_quad_refinement_face_id(Dart /*d*/) const + inline uint32 get_quad_refinement_face_id(Dart /*d*/) const { return 0u; } diff --git a/cgogn/multiresolution/cph/cph_base.h b/cgogn/multiresolution/cph/cph_base.h index 99bb4d1d..f4ae71ec 100644 --- a/cgogn/multiresolution/cph/cph_base.h +++ b/cgogn/multiresolution/cph/cph_base.h @@ -49,8 +49,8 @@ class CPHBase protected: - unsigned int current_level_; - unsigned int maximum_level_; + uint32 current_level_; + uint32 maximum_level_; /*! * \brief Store the current number of darts per resolution level. @@ -58,9 +58,9 @@ class CPHBase * becomes empty (contains no more dart) and that the maximum_level * of the hierarchy should be decremented. */ - std::vector nb_darts_per_level_; + std::vector nb_darts_per_level_; - ChunkArray* dart_level_; + ChunkArray* dart_level_; public: @@ -70,7 +70,7 @@ class CPHBase { nb_darts_per_level_.reserve(32u); nb_darts_per_level_.push_back(0); - dart_level_ = topology.template add_attribute("dartLevel") ; + dart_level_ = topology.template add_attribute("dartLevel") ; } virtual ~CPHBase() @@ -88,32 +88,32 @@ class CPHBase * LEVELS MANAGEMENT * ***************************************************/ - inline unsigned int get_current_level() const + inline uint32 get_current_level() const { return current_level_ ; } - inline void set_current_level(unsigned int l) + inline void set_current_level(uint32 l) { current_level_ = l ; } - inline unsigned int get_maximum_level() const + inline uint32 get_maximum_level() const { return maximum_level_ ; } - inline void set_maximum_level(unsigned int l) + inline void set_maximum_level(uint32 l) { maximum_level_ = l; } - inline unsigned int get_dart_level(Dart d) const + inline uint32 get_dart_level(Dart d) const { return (*dart_level_)[d.index] ; } - inline void set_dart_level(Dart d, unsigned int l) + inline void set_dart_level(Dart d, uint32 l) { (*dart_level_)[d.index] = l ; } diff --git a/cgogn/multiresolution/cph/ihcmap2.h b/cgogn/multiresolution/cph/ihcmap2.h index e9c7d000..8a68618f 100644 --- a/cgogn/multiresolution/cph/ihcmap2.h +++ b/cgogn/multiresolution/cph/ihcmap2.h @@ -38,15 +38,15 @@ class ContainerCPHBrowser : public ContainerBrowser public: ContainerCPHBrowser(const CONTAINER& cac, const MAP* map) : cac_(cac), map_(map) {} - virtual unsigned int begin() const { return cac_.real_begin(); } - virtual unsigned int end() const { return cac_.real_end(); } - virtual void next(unsigned int &it) const + virtual uint32 begin() const { return cac_.real_begin(); } + virtual uint32 end() const { return cac_.real_end(); } + virtual void next(uint32 &it) const { cac_.real_next(it); if(map_->get_dart_level(Dart(it)) > map_->get_current_level()) it = cac_.real_end(); } - virtual void next_primitive(unsigned int &it, unsigned int primSz) const { cac_.real_next_primitive(it,primSz); } + virtual void next_primitive(uint32 &it, uint32 primSz) const { cac_.real_next_primitive(it,primSz); } virtual void enable() {} virtual void disable() {} virtual ~ContainerCPHBrowser() {} @@ -104,7 +104,7 @@ class IHCMap2_T : public CMap2_T, public CPH2 using DartMarker = typename cgogn::DartMarker; using DartMarkerStore = typename cgogn::DartMarkerStore; - ChunkArray* next_level_cell[NB_ORBITS]; + ChunkArray* next_level_cell[NB_ORBITS]; protected: @@ -163,7 +163,7 @@ class IHCMap2_T : public CMap2_T, public CPH2 "Access to a dart introduced after current level") ; bool finished = false ; - unsigned int edge_id = Inherit_CPH::get_edge_id(d) ; + uint32 edge_id = Inherit_CPH::get_edge_id(d) ; Dart it = d ; do { @@ -185,7 +185,7 @@ class IHCMap2_T : public CMap2_T, public CPH2 bool finished = false ; Dart it = Inherit_CMAP::phi_1(d) ; - unsigned int edge_id = Inherit_CPH::get_edge_id(d) ; + uint32 edge_id = Inherit_CPH::get_edge_id(d) ; do { if(Inherit_CPH::get_dart_level(it) <= Inherit_CPH::get_current_level()) @@ -219,19 +219,19 @@ class IHCMap2_T : public CMap2_T, public CPH2 *******************************************************************************/ // template -// inline unsigned int get_embedding_cph(Cell c) const +// inline uint32 get_embedding_cph(Cell c) const // { // static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); // cgogn_message_assert(Inherit::is_embedded>(), "Invalid parameter: orbit not embedded"); -// unsigned int nb_steps = Inherit::get_current_level() - Inherit::get_dart_level(c.dart); -// unsigned int index = Inherit::get_embedding(c); +// uint32 nb_steps = Inherit::get_current_level() - Inherit::get_dart_level(c.dart); +// uint32 index = Inherit::get_embedding(c); -// unsigned int step = 0; +// uint32 step = 0; // while(step < nb_steps) // { // step++; -// unsigned int next = next_level_cell_[ORBIT]->operator[](index); +// uint32 next = next_level_cell_[ORBIT]->operator[](index); // //index = next; // if(next != EMBNULL) index = next; // else break; @@ -248,7 +248,7 @@ class IHCMap2_T : public CMap2_T, public CPH2 * the inserted darts are automatically embedded on new attribute elements. * Actually a FACE attribute is created, if needed, for the new face. */ - Face add_face(unsigned int size) + Face add_face(uint32 size) { Face f(this->add_face_topo(size)); @@ -282,9 +282,9 @@ class IHCMap2_T : public CMap2_T, public CPH2 return f; } - inline unsigned int face_degree(Dart d) + inline uint32 face_degree(Dart d) { - unsigned int count = 0 ; + uint32 count = 0 ; Dart it = d ; do { @@ -329,7 +329,7 @@ class IHCMap2_T : public CMap2_T, public CPH2 visited_faces->push_back(d); // Start with the face of d // For every face added to the list - for(unsigned int i = 0; i < visited_faces->size(); ++i) + for(uint32 i = 0; i < visited_faces->size(); ++i) { Dart e = (*visited_faces)[i] ; if (!marker.is_marked(e)) // Face has not been visited yet diff --git a/cgogn/multiresolution/cph/ihcmap2_adaptive.h b/cgogn/multiresolution/cph/ihcmap2_adaptive.h index 31dceeb1..7ca88016 100644 --- a/cgogn/multiresolution/cph/ihcmap2_adaptive.h +++ b/cgogn/multiresolution/cph/ihcmap2_adaptive.h @@ -86,7 +86,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T * its darts. As phi1(d) and phi2(d) are from the same level we can * optimize by checking phi1(d) instead of phi2(d) */ - unsigned int edge_level(Dart d) + uint32 edge_level(Dart d) { cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), "Access to a dart introduced after current level"); @@ -100,7 +100,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T * face with all neighboring faces are regularly subdivided * but not the face itself */ - unsigned int face_level(Dart d) + uint32 face_level(Dart d) { cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), "Access to a dart introduced after current level"); @@ -110,12 +110,12 @@ class IHCMap2Adaptive_T : public IHCMap2_T Dart it = d; Dart old = it; - unsigned int l_old = Inherit::get_dart_level(old); - unsigned int fLevel = edge_level(it); + uint32 l_old = Inherit::get_dart_level(old); + uint32 fLevel = edge_level(it); do { it = Inherit::phi1(it); - unsigned int dl = Inherit::get_dart_level(it); + uint32 dl = Inherit::get_dart_level(it); // compute the oldest dart of the face in the same time if(dl < l_old) @@ -123,16 +123,16 @@ class IHCMap2Adaptive_T : public IHCMap2_T old = it; l_old = dl; } - unsigned int l = edge_level(it); + uint32 l = edge_level(it); fLevel = l < fLevel ? l : fLevel; } while(it != d); - unsigned int cur = Inherit::get_current_level(); + uint32 cur = Inherit::get_current_level(); Inherit::set_current_level(fLevel); - unsigned int nbSubd = 0; + uint32 nbSubd = 0; it = old; - unsigned int eId = Inherit::get_edge_id(old); + uint32 eId = Inherit::get_edge_id(old); do { ++nbSubd; @@ -158,9 +158,9 @@ class IHCMap2Adaptive_T : public IHCMap2_T cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), "Access to a dart introduced after current level"); - unsigned int cur = Inherit::get_current_level(); + uint32 cur = Inherit::get_current_level(); Dart p = d; - unsigned int pLevel = Inherit::get_dart_level(p); + uint32 pLevel = Inherit::get_dart_level(p); while(pLevel > 0) { p = face_oldest_dart(p); @@ -181,10 +181,10 @@ class IHCMap2Adaptive_T : public IHCMap2_T Dart it = d ; Dart oldest = it ; - unsigned int l_old = Inherit::get_dart_level(oldest); + uint32 l_old = Inherit::get_dart_level(oldest); do { - unsigned int l = Inherit::get_dart_level(it); + uint32 l = Inherit::get_dart_level(it); if(l == 0) return it; @@ -214,7 +214,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T return false ; Dart d1 = Inherit::phi1(d); - unsigned int cur = Inherit::get_current_level(); + uint32 cur = Inherit::get_current_level(); Inherit::set_current_level(cur + 1); Dart d1_l = Inherit::phi1(d); Inherit::set_current_level(cur); @@ -242,7 +242,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T { subd = true ; Dart d2 = Inherit::phi2(d) ; - unsigned int cur = Inherit::get_current_level(); + uint32 cur = Inherit::get_current_level(); Inherit::set_current_level(cur + 1); if(this->degree(typename Inherit::Vertex(Inherit::phi1(d))) == 2) { @@ -265,13 +265,13 @@ class IHCMap2Adaptive_T : public IHCMap2_T cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), "Access to a dart introduced after current level"); - unsigned int fLevel = face_level(d) ; + uint32 fLevel = face_level(d) ; if(fLevel <= Inherit::get_current_level()) return false ; bool subd = false ; - unsigned int cur = Inherit::get_current_level(); + uint32 cur = Inherit::get_current_level(); Inherit::set_current_level(cur + 1); if(Inherit::get_dart_level(Inherit::phi1(d)) == Inherit::get_current_level() && Inherit::get_edge_id(Inherit::phi1(d)) != Inherit::get_edge_id(d)) @@ -294,23 +294,23 @@ class IHCMap2Adaptive_T : public IHCMap2_T cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), "Access to a dart introduced after current level"); - unsigned int fLevel = face_level(d); + uint32 fLevel = face_level(d); if(fLevel < Inherit::get_current_level()) return false; - unsigned int degree = 0 ; + uint32 degree = 0 ; bool subd = false ; bool subdOnce = true ; Dart fit = d ; do { - unsigned int cur = Inherit::get_current_level(); + uint32 cur = Inherit::get_current_level(); Inherit::set_current_level(cur + 1); if(Inherit::get_dart_level(Inherit::phi1(fit)) == Inherit::get_current_level() && Inherit::get_edge_id(Inherit::phi1(fit)) != Inherit::get_edge_id(fit)) { subd = true ; - unsigned int cur2 = Inherit::get_current_level(); + uint32 cur2 = Inherit::get_current_level(); Inherit::set_current_level(cur2 + 1); if(Inherit::get_dart_level(Inherit::phi1(fit)) == Inherit::get_current_level() && Inherit::get_edge_id(this->phi1(fit)) != Inherit::get_edge_id(fit)) @@ -324,10 +324,10 @@ class IHCMap2Adaptive_T : public IHCMap2_T if(degree == 3 && subd) { - unsigned int cur = Inherit::get_current_level(); + uint32 cur = Inherit::get_current_level(); Inherit::set_current_level(cur + 1); Dart cf = Inherit::phi2(Inherit::phi1(d)) ; - unsigned int cur2 = Inherit::get_current_level(); + uint32 cur2 = Inherit::get_current_level(); Inherit::set_current_level(cur2 + 1); if(Inherit::get_dart_level(Inherit::phi1(cf)) == Inherit::get_current_level() && Inherit::get_edge_id(Inherit::phi1(cf)) != Inherit::get_edge_id(cf)) @@ -366,9 +366,9 @@ class IHCMap2Adaptive_T : public IHCMap2_T "subdivideEdge : called with a dart inserted after current level") ; cgogn_message_assert(!edge_is_subdivided(d), "Trying to subdivide an already subdivided edge"); - unsigned int eLevel = edge_level(d); + uint32 eLevel = edge_level(d); - unsigned int cur = Inherit::get_current_level(); + uint32 cur = Inherit::get_current_level(); Inherit::set_current_level(eLevel); Dart dd = Inherit::phi2(d); @@ -376,7 +376,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T Inherit::set_current_level(eLevel + 1); this->cut_edge_topo(d); - unsigned int eId = Inherit::get_edge_id(d); + uint32 eId = Inherit::get_edge_id(d); Inherit::set_edge_id(Inherit::phi1(d), eId); Inherit::set_edge_id(Inherit::phi1(dd), eId); @@ -403,10 +403,10 @@ class IHCMap2Adaptive_T : public IHCMap2_T cgogn_message_assert(edge_can_be_coarsened(d), "Trying to coarsen an edge that can not be coarsened"); - unsigned int cur = Inherit::get_current_level(); + uint32 cur = Inherit::get_current_level(); // Dart e = Inherit::phi2(d); Inherit::set_current_level(cur + 1); - // unsigned int dl = Inherit::get_dart_level(e); + // uint32 dl = Inherit::get_dart_level(e); // Inherit::set_dart_level(Inherit::phi1(e), dl); // Inherit::collapseEdge(e); this->merge_adjacent_edges_topo(d); @@ -417,19 +417,19 @@ class IHCMap2Adaptive_T : public IHCMap2_T /** * subdivide the face of d to the next level */ - unsigned int subdivide_face(Dart d, bool triQuad = true, bool OneLevelDifference = true) + uint32 subdivide_face(Dart d, bool triQuad = true, bool OneLevelDifference = true) { cgogn_message_assert(Inherit::get_dart_level(d) <= Inherit::get_current_level(), "coarsenEdge : called with a dart inserted after current level"); cgogn_message_assert(!face_is_subdivided(d), "Trying to coarsen an edge that can not be coarsened"); - unsigned int fLevel = face_level(d); + uint32 fLevel = face_level(d); Dart old = face_oldest_dart(d); - unsigned int cur = Inherit::get_current_level(); + uint32 cur = Inherit::get_current_level(); Inherit::set_current_level(fLevel); // go to the level of the face to subdivide its edges - unsigned int degree = 0; + uint32 degree = 0; Dart it = old; do { @@ -458,7 +458,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T e = Inherit::phi1(e); this->cut_face_topo(dd,e); - unsigned int id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); + uint32 id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id); // set the edge id of the inserted Inherit::set_edge_id(Inherit::phi_1(e), id); // edge to the next available id @@ -491,7 +491,7 @@ class IHCMap2Adaptive_T : public IHCMap2_T Dart ne2 = Inherit::phi2(ne); this->cut_edge_topo(ne); // cut the new edge to insert the central vertex - unsigned int id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(ne))); + uint32 id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(ne))); Inherit::set_edge_id(ne, id); Inherit::set_edge_id(Inherit::phi2(ne), id); // set the edge id of the inserted @@ -534,9 +534,9 @@ class IHCMap2Adaptive_T : public IHCMap2_T "coarsenEdge : called with a dart inserted after current level"); cgogn_message_assert(face_is_subdivided_once(d), "Trying to coarsen an edge that can not be coarsened"); - unsigned int cur = Inherit::get_current_level(); + uint32 cur = Inherit::get_current_level(); - unsigned int degree = 0; + uint32 degree = 0; Dart fit = d; do { diff --git a/cgogn/multiresolution/cph/ihcmap2_regular.h b/cgogn/multiresolution/cph/ihcmap2_regular.h index 68719fa3..14b9ceb6 100644 --- a/cgogn/multiresolution/cph/ihcmap2_regular.h +++ b/cgogn/multiresolution/cph/ihcmap2_regular.h @@ -72,7 +72,7 @@ class IHCMap2Regular_T : public IHCMap2_T inline void add_triangular_level() { - unsigned int cur = Inherit::get_current_level() ; + uint32 cur = Inherit::get_current_level() ; Inherit::set_current_level(Inherit::get_maximum_level() + 1) ; @@ -82,7 +82,7 @@ class IHCMap2Regular_T : public IHCMap2_T Dart dd = Inherit::phi2(e); // Inherit::cut_edge(e); - unsigned int eid = Inherit::get_edge_id(e); + uint32 eid = Inherit::get_edge_id(e); Inherit::set_edge_id(Inherit::phi1(e), eid); Inherit::set_edge_id(Inherit::phi1(dd), eid); }); @@ -100,7 +100,7 @@ class IHCMap2Regular_T : public IHCMap2_T // insert a new edge // Inherit::cut_face(dd, e) ; - unsigned int id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); + uint32 id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id) ; // set the edge id of the inserted Inherit::set_edge_id(Inherit::phi_1(e), id) ; // edge to the next available id @@ -124,7 +124,7 @@ class IHCMap2Regular_T : public IHCMap2_T inline void add_quadrangular_level() { - unsigned int cur = Inherit::get_current_level() ; + uint32 cur = Inherit::get_current_level() ; Inherit::set_current_level(Inherit::get_maximum_level() + 1) ; @@ -134,7 +134,7 @@ class IHCMap2Regular_T : public IHCMap2_T Dart dd = Inherit::phi2(e); // Inherit::cut_edge(e); - unsigned int eid = Inherit::get_edge_id(e); + uint32 eid = Inherit::get_edge_id(e); Inherit::set_edge_id(Inherit::phi1(e), eid); Inherit::set_edge_id(Inherit::phi1(dd), eid); }); @@ -155,7 +155,7 @@ class IHCMap2Regular_T : public IHCMap2_T Dart ne2 = Inherit::phi2(ne) ; // Inherit::cut_edge(ne) ; // cut the new edge to insert the central vertex - unsigned int id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(ne))); + uint32 id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(ne))); Inherit::set_edge_id(ne, id) ; Inherit::set_edge_id(Inherit::phi2(ne), id) ; // set the edge id of the inserted @@ -183,7 +183,7 @@ class IHCMap2Regular_T : public IHCMap2_T inline void add_mixed_level() { - unsigned int cur = Inherit::get_current_level() ; + uint32 cur = Inherit::get_current_level() ; Inherit::set_current_level(Inherit::get_maximum_level() + 1) ; @@ -193,7 +193,7 @@ class IHCMap2Regular_T : public IHCMap2_T Dart dd = Inherit::phi2(e); // Inherit::cut_edge(e); - unsigned int eid = Inherit::get_edge_id(e); + uint32 eid = Inherit::get_edge_id(e); Inherit::set_edge_id(Inherit::phi1(e), eid); Inherit::set_edge_id(Inherit::phi1(dd), eid); }); @@ -206,9 +206,9 @@ class IHCMap2Regular_T : public IHCMap2_T if(Inherit::get_dart_level(old) == Inherit::get_maximum_level()) old = Inherit::phi1(old) ; - unsigned int cur = Inherit::get_current_level(); + uint32 cur = Inherit::get_current_level(); Inherit::set_current_level(cur - 1); - unsigned int degree = Inherit::face_degree(old) ; + uint32 degree = Inherit::face_degree(old) ; Inherit::set_current_level(cur); if(degree == 3) @@ -218,7 +218,7 @@ class IHCMap2Regular_T : public IHCMap2_T // insert a new edge // Inherit::cut_face(dd, e) ; - unsigned int id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); + uint32 id = Inherit::get_tri_refinement_edge_id(Inherit::phi_1(Inherit::phi_1(dd)), Inherit::phi1(Inherit::phi_1(dd))); Inherit::set_edge_id(Inherit::phi_1(dd), id) ; // set the edge id of the inserted Inherit::set_edge_id(Inherit::phi_1(e), id) ; // edge to the next available id @@ -246,7 +246,7 @@ class IHCMap2Regular_T : public IHCMap2_T Dart ne2 = Inherit::phi2(ne) ; // Inherit::cut_edge(ne) ; // cut the new edge to insert the central vertex - unsigned int id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(ne))); + uint32 id = Inherit::get_quad_refinement_edge_id(Inherit::phi1(Inherit::phi2(ne))); Inherit::set_edge_id(ne, id) ; Inherit::set_edge_id(Inherit::phi2(ne), id) ; // set the edge id of the inserted diff --git a/cgogn/multiresolution/cph/ihcmap3.h b/cgogn/multiresolution/cph/ihcmap3.h index 6c1c27c2..1c39676d 100644 --- a/cgogn/multiresolution/cph/ihcmap3.h +++ b/cgogn/multiresolution/cph/ihcmap3.h @@ -77,7 +77,7 @@ class IHCMap3_T :public CMap3_T, public CPH3 using DartMarker = typename cgogn::DartMarker; using DartMarkerStore = typename cgogn::DartMarkerStore; - ChunkArray* next_level_cell[NB_ORBITS]; + ChunkArray* next_level_cell[NB_ORBITS]; template class ContainerCPHBrowser : public ContainerBrowser @@ -87,15 +87,15 @@ class IHCMap3_T :public CMap3_T, public CPH3 public: ContainerCPHBrowser(const CONTAINER& cac, const MAP* map) : cac_(cac), map_(map) {} - virtual unsigned int begin() const { return cac_.real_begin(); } - virtual unsigned int end() const { return cac_.real_end(); } - virtual void next(unsigned int &it) const + virtual uint32 begin() const { return cac_.real_begin(); } + virtual uint32 end() const { return cac_.real_end(); } + virtual void next(uint32 &it) const { cac_.real_next(it); if(map_->get_dart_level(Dart(it)) > map_->get_current_level()) it = cac_.real_end(); } - virtual void next_primitive(unsigned int &it, unsigned int primSz) const { cac_.real_next_primitive(it,primSz); } + virtual void next_primitive(uint32 &it, uint32 primSz) const { cac_.real_next_primitive(it,primSz); } virtual void enable() {} virtual void disable() {} virtual ~ContainerCPHBrowser() {} @@ -135,7 +135,7 @@ class IHCMap3_T :public CMap3_T, public CPH3 cgogn_message_assert(Inherit_CPH::get_dart_level(d) <= Inherit_CPH::get_current_level(), "Access to a dart introduced after current level") ; bool finished = false ; - unsigned int edge_id = Inherit_CPH::get_edge_id(d) ; + uint32 edge_id = Inherit_CPH::get_edge_id(d) ; Dart it = d ; do { @@ -157,7 +157,7 @@ class IHCMap3_T :public CMap3_T, public CPH3 bool finished = false ; Dart it = Inherit_CMAP::phi_1(d) ; - unsigned int edge_id = Inherit_CPH::get_edge_id(d) ; + uint32 edge_id = Inherit_CPH::get_edge_id(d) ; do { if(Inherit_CPH::get_dart_level(it) <= Inherit_CPH::get_current_level()) @@ -218,7 +218,7 @@ class IHCMap3_T :public CMap3_T, public CPH3 inline Dart phi2bis(Dart d) const { - unsigned int face_id = Inherit_CPH::get_face_id(d); + uint32 face_id = Inherit_CPH::get_face_id(d); Dart it = d; it = Inherit_CMAP::phi2(it); @@ -281,7 +281,7 @@ class IHCMap3_T :public CMap3_T, public CPH3 visited_faces->push_back(d); // Start with the face of d // For every face added to the list - for(unsigned int i = 0; i < visited_faces->size(); ++i) + for(uint32 i = 0; i < visited_faces->size(); ++i) { if (!marker.is_marked((*visited_faces)[i])) // Face has not been visited yet { @@ -310,7 +310,7 @@ class IHCMap3_T :public CMap3_T, public CPH3 const std::vector* marked_darts = marker.get_marked_darts(); marker.mark(d); - for(unsigned int i = 0; i < marked_darts->size(); ++i) + for(uint32 i = 0; i < marked_darts->size(); ++i) { f((*marked_darts)[i]); diff --git a/cgogn/multiresolution/mrcmap/mr_base.h b/cgogn/multiresolution/mrcmap/mr_base.h index a5349d96..967d1034 100644 --- a/cgogn/multiresolution/mrcmap/mr_base.h +++ b/cgogn/multiresolution/mrcmap/mr_base.h @@ -50,23 +50,23 @@ class MRBase * pointers to attributs that stores next level * correspondance indices for each dart */ - std::deque*> next_level_indices_; + std::deque*> next_level_indices_; /** * pointers to attributs that stores previous level * correspondance indices for each dart */ - std::deque*> previous_level_indices_; + std::deque*> previous_level_indices_; /** * stack for current level temporary storage */ - std::stack> levels_stack_ ; + std::stack> levels_stack_ ; /** * current level in multiresolution map */ - unsigned int current_level_; + uint32 current_level_; //TODO le niveau courant doit etre par thread //appele sur la carte et non plus un champs de @@ -112,17 +112,17 @@ class MRBase //1 thread par niveau = 1 thread par carte //n thread par niveau = n thread par carte - inline unsigned int get_maximum_level() const + inline uint32 get_maximum_level() const { - return static_cast(maps_.size()); + return static_cast(maps_.size()); } - inline unsigned int get_current_level() const + inline uint32 get_current_level() const { return current_level_; } - inline void set_current_level(unsigned int l) + inline void set_current_level(uint32 l) { current_level_ = l; } @@ -140,7 +140,7 @@ class MRBase } //TODO - inline unsigned int get_dart_level(Dart d) + inline uint32 get_dart_level(Dart d) { return 0; } diff --git a/cgogn/rendering/drawer.cpp b/cgogn/rendering/drawer.cpp index 110454d0..388d5d8c 100644 --- a/cgogn/rendering/drawer.cpp +++ b/cgogn/rendering/drawer.cpp @@ -40,7 +40,7 @@ ShaderColorPerVertex* Drawer::shader_cpv_ = nullptr; ShaderBoldLine* Drawer::shader_bl_ = nullptr; ShaderRoundPoint* Drawer::shader_rp_ = nullptr; ShaderPointSprite* Drawer::shader_ps_ = nullptr; -int Drawer::nb_instances_ = 0; +int32 Drawer::nb_instances_ = 0; Drawer::Drawer(QOpenGLFunctions_3_3_Core* ogl33): current_size_(1.0f), @@ -156,7 +156,7 @@ void Drawer::begin(GLenum mode) void Drawer::end() { - current_begin_->back().nb = static_cast(data_pos_.size() - current_begin_->back().begin); + current_begin_->back().nb = static_cast(data_pos_.size() - current_begin_->back().begin); } @@ -184,7 +184,7 @@ void Drawer::color3f(float r, float g, float b) void Drawer::end_list() { - unsigned int nb_elts = static_cast(data_pos_.size()); + uint32 nb_elts = static_cast(data_pos_.size()); if (nb_elts == 0) return; diff --git a/cgogn/rendering/drawer.h b/cgogn/rendering/drawer.h index de03cffb..26847748 100644 --- a/cgogn/rendering/drawer.h +++ b/cgogn/rendering/drawer.h @@ -45,12 +45,12 @@ class CGOGN_RENDERING_API Drawer { struct PrimParam { - unsigned int begin; + uint32 begin; GLenum mode; float width; - unsigned int nb; + uint32 nb; bool aa; - PrimParam(std::size_t b, GLenum m, float w, bool a) : begin(static_cast(b)), mode(m), width(w), nb(0), aa(a){} + PrimParam(std::size_t b, GLenum m, float w, bool a) : begin(static_cast(b)), mode(m), width(w), nb(0), aa(a){} }; using Vec3f = std::array; @@ -61,7 +61,7 @@ class CGOGN_RENDERING_API Drawer static ShaderBoldLine* shader_bl_; static ShaderRoundPoint* shader_rp_; static ShaderPointSprite* shader_ps_; - static int nb_instances_; + static int32 nb_instances_; VBO* vbo_pos_; VBO* vbo_col_; @@ -78,10 +78,10 @@ class CGOGN_RENDERING_API Drawer std::vector begins_face_; std::vector* current_begin_; - unsigned int vao_cpv_; - unsigned int vao_bl_; - unsigned int vao_rp_; - unsigned int vao_ps_; + uint32 vao_cpv_; + uint32 vao_bl_; + uint32 vao_rp_; + uint32 vao_ps_; float current_size_; bool current_aa_; diff --git a/cgogn/rendering/examples/picking_viewer.cpp b/cgogn/rendering/examples/picking_viewer.cpp index bd0ae989..ae66b6b4 100644 --- a/cgogn/rendering/examples/picking_viewer.cpp +++ b/cgogn/rendering/examples/picking_viewer.cpp @@ -44,6 +44,8 @@ #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) +using namespace cgogn::numerics; + using Map2 = cgogn::CMap2; //using Vec3 = Eigen::Vector3d; using Vec3 = cgogn::geometry::Vec_T>; @@ -233,7 +235,7 @@ void Viewer::mousePressEvent(QMouseEvent* event) drawer_->vertex3fv(vertex_position_[selected[0]]); // others in yellow drawer_->color3f(1.0,1.0,0.0); - for(unsigned int i=1u;ivertex3fv(vertex_position_[selected[i]]); drawer_->end(); } @@ -253,7 +255,7 @@ void Viewer::mousePressEvent(QMouseEvent* event) cgogn::rendering::add_edge_to_drawer(map_,selected[0],vertex_position_,drawer_); // others in yellow drawer_->color3f(1.0,1.0,0.0); - for(unsigned int i=1u;i(map_,selected[i],vertex_position_,drawer_); drawer_->end(); } @@ -273,7 +275,7 @@ void Viewer::mousePressEvent(QMouseEvent* event) cgogn::rendering::add_face_to_drawer(map_,selected[0],vertex_position_,drawer_); // others in yellow drawer_->color3f(1.0,1.0,0.0); - for(unsigned int i=1u;i(map_,selected[i],vertex_position_,drawer_); drawer_->end(); } @@ -293,7 +295,7 @@ void Viewer::mousePressEvent(QMouseEvent* event) cgogn::rendering::add_volume_to_drawer(map_,selected[0],vertex_position_,drawer_); // others in yellow drawer_->color3f(1.0,1.0,0.0); - for(unsigned int i=1u;i(map_,selected[i],vertex_position_,drawer_); drawer_->end(); } diff --git a/cgogn/rendering/examples/viewer_per_face.cpp b/cgogn/rendering/examples/viewer_per_face.cpp index 9606f428..2702eda7 100644 --- a/cgogn/rendering/examples/viewer_per_face.cpp +++ b/cgogn/rendering/examples/viewer_per_face.cpp @@ -42,6 +42,10 @@ #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) + +//USING_CGOGN_NUMERICS; +using namespace cgogn::numerics; + using Map2 = cgogn::CMap2; using Vec3 = Eigen::Vector3d; //using Vec3 = cgogn::geometry::Vec_T>; @@ -193,9 +197,9 @@ void Viewer::init() vbo_color_ = new cgogn::rendering::VBO(3); // indices of vertices emb (f1_v1,f1_v2,f1_v3, f2_v1,f2_v2,f2_v3, f3_v1...) - std::vector ind_v; + std::vector ind_v; // indices of faces emb (f1,f1,f1, f2,f2,f2, f3,f3,f3...) - std::vector ind_f; + std::vector ind_f; // create indices ( need to be done only after topo modifications cgogn::rendering::create_indices_vertices_faces(map_,vertex_position_,ind_v,ind_f); diff --git a/cgogn/rendering/examples/viewer_topo3.cpp b/cgogn/rendering/examples/viewer_topo3.cpp index d3eb8c9b..0cf6de90 100644 --- a/cgogn/rendering/examples/viewer_topo3.cpp +++ b/cgogn/rendering/examples/viewer_topo3.cpp @@ -41,6 +41,7 @@ #define DEFAULT_MESH_PATH CGOGN_STR(CGOGN_TEST_MESHES_PATH) +using namespace cgogn::numerics; using Map3 = cgogn::CMap3; using Vec3 = Eigen::Vector3d; //using Vec3 = cgogn::geometry::Vec_T>; @@ -197,7 +198,7 @@ void Viewer::mousePressEvent(QMouseEvent* event) cgogn::rendering::add_volume_to_drawer(map_, selected[0], vertex_position_, drawer_); // others in yellow drawer_->color3f(1.0, 1.0, 0.0); - for (unsigned int i = 1u; i(map_, selected[i], vertex_position_, drawer_); drawer_->end(); } diff --git a/cgogn/rendering/map_render.h b/cgogn/rendering/map_render.h index 06f5069a..7bea5176 100644 --- a/cgogn/rendering/map_render.h +++ b/cgogn/rendering/map_render.h @@ -54,13 +54,13 @@ class MapRender QOpenGLBuffer* indices_buffers_[SIZE_BUFFER]; bool indices_buffers_uptodate_[SIZE_BUFFER]; - unsigned int nb_indices_[SIZE_BUFFER]; + uint32 nb_indices_[SIZE_BUFFER]; public: inline MapRender() { - for (unsigned int i = 0u; i < SIZE_BUFFER; ++i) + for (uint32 i = 0u; i < SIZE_BUFFER; ++i) { indices_buffers_[i] = new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer); indices_buffers_[i]->setUsagePattern(QOpenGLBuffer::StaticDraw); @@ -69,14 +69,14 @@ class MapRender inline ~MapRender() { - for (unsigned int i = 0u; i < SIZE_BUFFER; ++i) + for (uint32 i = 0u; i < SIZE_BUFFER; ++i) delete indices_buffers_[i]; } inline bool is_primitive_uptodate(DrawingType prim) { return indices_buffers_uptodate_[prim]; } template - void init_points(MAP& m, std::vector& table_indices) + void init_points(MAP& m, std::vector& table_indices) { // table_indices.reserve(m.get_nb_darts()/6); m.foreach_cell([&] (typename MAP::Vertex v) @@ -86,7 +86,7 @@ class MapRender } template - void init_lines(MAP& m, std::vector& table_indices) + void init_lines(MAP& m, std::vector& table_indices) { using Vertex = typename MAP::Vertex; using Edge = typename MAP::Edge; @@ -99,7 +99,7 @@ class MapRender } template - void init_triangles(MAP& m, std::vector& table_indices, const typename MAP::template VertexAttributeHandler& position) + void init_triangles(MAP& m, std::vector& table_indices, const typename MAP::template VertexAttributeHandler& position) { using Vertex = typename MAP::Vertex; using Face = typename MAP::Face; @@ -123,7 +123,7 @@ class MapRender template void init_primitives(MAP& m, DrawingType prim, const typename MAP::template VertexAttributeHandler& position) { - std::vector table_indices; + std::vector table_indices; switch (prim) { @@ -144,9 +144,9 @@ class MapRender indices_buffers_[prim]->create(); indices_buffers_uptodate_[prim] = true; - nb_indices_[prim] = static_cast(table_indices.size()); + nb_indices_[prim] = static_cast(table_indices.size()); indices_buffers_[prim]->bind(); - indices_buffers_[prim]->allocate(&(table_indices[0]), nb_indices_[prim] * sizeof(unsigned int)); + indices_buffers_[prim]->allocate(&(table_indices[0]), nb_indices_[prim] * sizeof(uint32)); indices_buffers_[prim]->release(); } @@ -184,7 +184,7 @@ class MapRender * @param indices2 embedding indices of faces */ template -void create_indices_vertices_faces(MAP& m, const typename MAP::template VertexAttributeHandler& position, std::vector& indices1, std::vector& indices2) +void create_indices_vertices_faces(MAP& m, const typename MAP::template VertexAttributeHandler& position, std::vector& indices1, std::vector& indices2) { using Vertex = typename MAP::Vertex; using Face = typename MAP::Face; @@ -195,12 +195,12 @@ void create_indices_vertices_faces(MAP& m, const typename MAP::template VertexAt indices2.clear(); //local vector for ear triangulation - std::vector local_vert_indices; + std::vector local_vert_indices; local_vert_indices.reserve(256); m.foreach_cell([&] (Face f) { - unsigned int ef = m.get_embedding(Face(f.dart)); + uint32 ef = m.get_embedding(Face(f.dart)); if (m.has_degree(f,3)) { indices1.push_back(m.get_embedding(Vertex(f.dart))); @@ -214,7 +214,7 @@ void create_indices_vertices_faces(MAP& m, const typename MAP::template VertexAt else { cgogn::geometry::compute_ear_triangulation(m,f,position,local_vert_indices); - for (unsigned int i : local_vert_indices) + for (uint32 i : local_vert_indices) { indices1.push_back(i); indices2.push_back(ef); diff --git a/cgogn/rendering/shaders/shader_bold_line.cpp b/cgogn/rendering/shaders/shader_bold_line.cpp index 007d61e6..a96f2d90 100644 --- a/cgogn/rendering/shaders/shader_bold_line.cpp +++ b/cgogn/rendering/shaders/shader_bold_line.cpp @@ -218,13 +218,13 @@ void ShaderBoldLine::set_color(const QColor& rgb) void ShaderBoldLine::set_width(float wpix) { QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); - int viewport[4]; + GLint viewport[4]; ogl->glGetIntegerv(GL_VIEWPORT, viewport); QSizeF wd(wpix / float(viewport[2]), wpix / float(viewport[3])); prg_.setUniformValue(unif_width_, wd); } -bool ShaderBoldLine::set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color) +bool ShaderBoldLine::set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_color) { if (i >= vaos_.size()) { diff --git a/cgogn/rendering/shaders/shader_bold_line.h b/cgogn/rendering/shaders/shader_bold_line.h index 95389328..72272756 100644 --- a/cgogn/rendering/shaders/shader_bold_line.h +++ b/cgogn/rendering/shaders/shader_bold_line.h @@ -51,8 +51,8 @@ class CGOGN_RENDERING_API ShaderBoldLine : public ShaderProgram }; // uniform ids - int unif_color_; - int unif_width_; + GLint unif_color_; + GLint unif_width_; public: @@ -77,7 +77,7 @@ class CGOGN_RENDERING_API ShaderBoldLine : public ShaderProgram * @param vbo_color pointer on color vbo * @return true if ok */ - bool set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color=NULL); + bool set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_color=NULL); }; } // namespace rendering diff --git a/cgogn/rendering/shaders/shader_color_per_vertex.cpp b/cgogn/rendering/shaders/shader_color_per_vertex.cpp index 5eb2ce10..926f6990 100644 --- a/cgogn/rendering/shaders/shader_color_per_vertex.cpp +++ b/cgogn/rendering/shaders/shader_color_per_vertex.cpp @@ -66,7 +66,7 @@ ShaderColorPerVertex::ShaderColorPerVertex() get_matrices_uniforms(); } -bool ShaderColorPerVertex::set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color) +bool ShaderColorPerVertex::set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_color) { if (i >= vaos_.size()) { diff --git a/cgogn/rendering/shaders/shader_color_per_vertex.h b/cgogn/rendering/shaders/shader_color_per_vertex.h index 9926482d..4edc8b6c 100644 --- a/cgogn/rendering/shaders/shader_color_per_vertex.h +++ b/cgogn/rendering/shaders/shader_color_per_vertex.h @@ -56,7 +56,7 @@ class CGOGN_RENDERING_API ShaderColorPerVertex : public ShaderProgram * @param vbo_col pointer on color vbo (RGB) * @return true if ok */ - bool set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_col); + bool set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_col); }; } // namespace rendering diff --git a/cgogn/rendering/shaders/shader_explode_volumes.cpp b/cgogn/rendering/shaders/shader_explode_volumes.cpp index 517e08bb..9f5fe628 100644 --- a/cgogn/rendering/shaders/shader_explode_volumes.cpp +++ b/cgogn/rendering/shaders/shader_explode_volumes.cpp @@ -194,7 +194,7 @@ void ShaderExplodeVolumes::set_plane_clip(const QVector4D& plane) prg_.setUniformValue(unif_plane_clip_, plane); } -bool ShaderExplodeVolumes::set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color) +bool ShaderExplodeVolumes::set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_color) { if (i >= vaos_.size()) { diff --git a/cgogn/rendering/shaders/shader_explode_volumes.h b/cgogn/rendering/shaders/shader_explode_volumes.h index d49bd71e..ccc42d49 100644 --- a/cgogn/rendering/shaders/shader_explode_volumes.h +++ b/cgogn/rendering/shaders/shader_explode_volumes.h @@ -53,10 +53,10 @@ class CGOGN_RENDERING_API ShaderExplodeVolumes : public ShaderProgram }; // uniform ids - int unif_expl_v_; - int unif_light_position_; - int unif_plane_clip_; - int unif_color_; + GLint unif_expl_v_; + GLint unif_light_position_; + GLint unif_plane_clip_; + GLint unif_color_; public: @@ -78,7 +78,7 @@ class CGOGN_RENDERING_API ShaderExplodeVolumes : public ShaderProgram * @param vbo_color pointer on color vbo * @return true if ok */ - bool set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color = nullptr); + bool set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_color = nullptr); }; } // namespace rendering diff --git a/cgogn/rendering/shaders/shader_explode_volumes_line.cpp b/cgogn/rendering/shaders/shader_explode_volumes_line.cpp index d89ff992..d483ae09 100644 --- a/cgogn/rendering/shaders/shader_explode_volumes_line.cpp +++ b/cgogn/rendering/shaders/shader_explode_volumes_line.cpp @@ -112,7 +112,7 @@ void ShaderExplodeVolumesLine::set_plane_clip(const QVector4D& plane) prg_.setUniformValue(unif_plane_clip_, plane); } -bool ShaderExplodeVolumesLine::set_vao(unsigned int i, VBO* vbo_pos) +bool ShaderExplodeVolumesLine::set_vao(uint32 i, VBO* vbo_pos) { if (i >= vaos_.size()) { diff --git a/cgogn/rendering/shaders/shader_explode_volumes_line.h b/cgogn/rendering/shaders/shader_explode_volumes_line.h index d13a2dcc..3144c647 100644 --- a/cgogn/rendering/shaders/shader_explode_volumes_line.h +++ b/cgogn/rendering/shaders/shader_explode_volumes_line.h @@ -48,9 +48,9 @@ class CGOGN_RENDERING_API ShaderExplodeVolumesLine : public ShaderProgram }; // uniform ids - int unif_expl_v_; - int unif_plane_clip_; - int unif_color_; + GLint unif_expl_v_; + GLint unif_plane_clip_; + GLint unif_color_; public: @@ -69,7 +69,7 @@ class CGOGN_RENDERING_API ShaderExplodeVolumesLine : public ShaderProgram * @param vbo_pos pointer on position vbo (XYZ) * @return true if ok */ - bool set_vao(unsigned int i, VBO* vbo_pos); + bool set_vao(uint32 i, VBO* vbo_pos); }; } // namespace rendering diff --git a/cgogn/rendering/shaders/shader_flat.cpp b/cgogn/rendering/shaders/shader_flat.cpp index 1cf9c295..f0aa1792 100644 --- a/cgogn/rendering/shaders/shader_flat.cpp +++ b/cgogn/rendering/shaders/shader_flat.cpp @@ -163,7 +163,7 @@ void ShaderFlat::set_ambiant_color(const QColor& rgb) } -bool ShaderFlat::set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color) +bool ShaderFlat::set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_color) { if (i >= vaos_.size()) { diff --git a/cgogn/rendering/shaders/shader_flat.h b/cgogn/rendering/shaders/shader_flat.h index 40cc11a0..2b37bcc0 100644 --- a/cgogn/rendering/shaders/shader_flat.h +++ b/cgogn/rendering/shaders/shader_flat.h @@ -51,10 +51,10 @@ class CGOGN_RENDERING_API ShaderFlat : public ShaderProgram }; // uniform ids - int unif_front_color_; - int unif_back_color_; - int unif_ambiant_color_; - int unif_light_position_; + GLint unif_front_color_; + GLint unif_back_color_; + GLint unif_ambiant_color_; + GLint unif_light_position_; public: @@ -99,7 +99,7 @@ class CGOGN_RENDERING_API ShaderFlat : public ShaderProgram * @param vbo_color pointer on color vbo (RGB) * @return true if ok */ - bool set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_col = NULL); + bool set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_col = NULL); }; diff --git a/cgogn/rendering/shaders/shader_phong.cpp b/cgogn/rendering/shaders/shader_phong.cpp index 03d55343..2e8e463d 100644 --- a/cgogn/rendering/shaders/shader_phong.cpp +++ b/cgogn/rendering/shaders/shader_phong.cpp @@ -231,7 +231,7 @@ void ShaderPhong::set_double_side(bool ts) prg_.setUniformValue(unif_double_side_,ts); } -bool ShaderPhong::set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_norm, VBO* vbo_color) +bool ShaderPhong::set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_norm, VBO* vbo_color) { if (i >= vaos_.size()) { diff --git a/cgogn/rendering/shaders/shader_phong.h b/cgogn/rendering/shaders/shader_phong.h index 85eae2b1..bd934e48 100644 --- a/cgogn/rendering/shaders/shader_phong.h +++ b/cgogn/rendering/shaders/shader_phong.h @@ -53,13 +53,13 @@ class CGOGN_RENDERING_API ShaderPhong : public ShaderProgram }; // uniform ids - int unif_front_color_; - int unif_back_color_; - int unif_ambiant_color_; - int unif_spec_color_; - int unif_spec_coef_; - int unif_double_side_; - int unif_light_position_; + GLint unif_front_color_; + GLint unif_back_color_; + GLint unif_ambiant_color_; + GLint unif_spec_color_; + GLint unif_spec_coef_; + GLint unif_double_side_; + GLint unif_light_position_; public: @@ -122,7 +122,7 @@ class CGOGN_RENDERING_API ShaderPhong : public ShaderProgram * @param vbo_color pointer on normal vbo (RGB) only used when color per vertex rendering * @return true if ok */ - bool set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_norm, VBO* vbo_color=NULL); + bool set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_norm, VBO* vbo_color=NULL); }; } // namespace rendering diff --git a/cgogn/rendering/shaders/shader_point_sprite.cpp b/cgogn/rendering/shaders/shader_point_sprite.cpp index b13bbfef..3d07f2dc 100644 --- a/cgogn/rendering/shaders/shader_point_sprite.cpp +++ b/cgogn/rendering/shaders/shader_point_sprite.cpp @@ -354,7 +354,7 @@ void ShaderPointSprite::set_local_light_position(const QVector3D& l, const QMatr -bool ShaderPointSprite::set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color, VBO* vbo_size) +bool ShaderPointSprite::set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_color, VBO* vbo_size) { if (i >= vaos_.size()) { diff --git a/cgogn/rendering/shaders/shader_point_sprite.h b/cgogn/rendering/shaders/shader_point_sprite.h index 3a26eda4..560e53dc 100644 --- a/cgogn/rendering/shaders/shader_point_sprite.h +++ b/cgogn/rendering/shaders/shader_point_sprite.h @@ -52,10 +52,10 @@ class CGOGN_RENDERING_API ShaderPointSprite : public ShaderProgram }; // uniform ids - int unif_color_; - int unif_size_; - int unif_ambiant_; - int unif_light_pos_; + GLint unif_color_; + GLint unif_size_; + GLint unif_ambiant_; + GLint unif_light_pos_; public: @@ -102,7 +102,7 @@ class CGOGN_RENDERING_API ShaderPointSprite : public ShaderProgram * @param vbo_size pointer on size (diameters of spheres) vbo * @return true if ok */ - bool set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color=NULL, VBO* vbo_size=NULL); + bool set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_color=NULL, VBO* vbo_size=NULL); }; } // namespace rendering diff --git a/cgogn/rendering/shaders/shader_program.h b/cgogn/rendering/shaders/shader_program.h index 11028cfc..b1dbb985 100644 --- a/cgogn/rendering/shaders/shader_program.h +++ b/cgogn/rendering/shaders/shader_program.h @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -38,7 +39,7 @@ namespace rendering { //convenient conversion function -inline void* void_ptr(unsigned int x) +inline void* void_ptr(uint32 x) { return reinterpret_cast(uint64_t(x)); } @@ -52,9 +53,9 @@ class CGOGN_RENDERING_API ShaderProgram : protected QOpenGLFunctions_3_3_Core std::vector vaos_; - int unif_mv_matrix_; - int unif_projection_matrix_; - int unif_normal_matrix_; + GLint unif_mv_matrix_; + GLint unif_projection_matrix_; + GLint unif_normal_matrix_; public: @@ -82,18 +83,18 @@ class CGOGN_RENDERING_API ShaderProgram : protected QOpenGLFunctions_3_3_Core * @brief add a vao (vbo configuration) * @return the id of vao */ - inline unsigned int add_vao() + inline uint32 add_vao() { vaos_.push_back(new QOpenGLVertexArrayObject); vaos_.back()->create(); - return static_cast(vaos_.size() - 1); + return static_cast(vaos_.size() - 1); } /** * @brief allocate new vaos until total nb is reached * @param nb number of vaos to reach */ - void alloc_vao(unsigned int nb) + void alloc_vao(uint32 nb) { while (vaos_.size() < nb) vaos_.push_back(new QOpenGLVertexArrayObject); @@ -103,16 +104,16 @@ class CGOGN_RENDERING_API ShaderProgram : protected QOpenGLFunctions_3_3_Core * @brief number of allocated vaos * @return the number of allocated vaos */ - inline unsigned int nb_vaos() + inline uint32 nb_vaos() { - return (unsigned int)(vaos_.size()); + return (uint32)(vaos_.size()); } /** * @brief bind a vao * @param i vao id (0,1,...) */ - inline void bind_vao(unsigned int i) + inline void bind_vao(uint32 i) { // assert(i < vaos_.size()); // if (!vaos_[i]->isCreated()) @@ -124,7 +125,7 @@ class CGOGN_RENDERING_API ShaderProgram : protected QOpenGLFunctions_3_3_Core * @brief release the vao * @param i id */ - inline void release_vao(unsigned int i) + inline void release_vao(uint32 i) { // assert(i < vaos_.size()); vaos_[i]->release(); diff --git a/cgogn/rendering/shaders/shader_round_point.cpp b/cgogn/rendering/shaders/shader_round_point.cpp index 4ea0f482..4140c110 100644 --- a/cgogn/rendering/shaders/shader_round_point.cpp +++ b/cgogn/rendering/shaders/shader_round_point.cpp @@ -184,7 +184,7 @@ void ShaderRoundPoint::set_width(float wpix) prg_.setUniformValue(unif_width_, wd); } -bool ShaderRoundPoint::set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color, unsigned int stride, unsigned first) +bool ShaderRoundPoint::set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_color, uint32 stride, unsigned first) { if (i >= vaos_.size()) { diff --git a/cgogn/rendering/shaders/shader_round_point.h b/cgogn/rendering/shaders/shader_round_point.h index 85137431..2db4b0b3 100644 --- a/cgogn/rendering/shaders/shader_round_point.h +++ b/cgogn/rendering/shaders/shader_round_point.h @@ -51,8 +51,8 @@ class CGOGN_RENDERING_API ShaderRoundPoint : public ShaderProgram }; // uniform ids - int unif_color_; - int unif_width_; + GLint unif_color_; + GLint unif_width_; public: @@ -77,7 +77,7 @@ class CGOGN_RENDERING_API ShaderRoundPoint : public ShaderProgram * @param vbo_color pointer on color vbo * @return true if ok */ - bool set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_color=NULL, unsigned int stride=0, unsigned first=0); + bool set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_color=NULL, uint32 stride=0, unsigned first=0); }; } // namespace rendering diff --git a/cgogn/rendering/shaders/shader_simple_color.cpp b/cgogn/rendering/shaders/shader_simple_color.cpp index f162e600..9b7857d4 100644 --- a/cgogn/rendering/shaders/shader_simple_color.cpp +++ b/cgogn/rendering/shaders/shader_simple_color.cpp @@ -73,7 +73,7 @@ void ShaderSimpleColor::set_color(const QColor& rgb) } -bool ShaderSimpleColor::set_vao(unsigned int i, VBO* vbo_pos, unsigned int stride, unsigned first) +bool ShaderSimpleColor::set_vao(uint32 i, VBO* vbo_pos, uint32 stride, unsigned first) { if (i >= vaos_.size()) { diff --git a/cgogn/rendering/shaders/shader_simple_color.h b/cgogn/rendering/shaders/shader_simple_color.h index 2e8a5ad2..f62874b1 100644 --- a/cgogn/rendering/shaders/shader_simple_color.h +++ b/cgogn/rendering/shaders/shader_simple_color.h @@ -46,7 +46,7 @@ class CGOGN_RENDERING_API ShaderSimpleColor : public ShaderProgram }; // uniform ids - int unif_color_; + GLint unif_color_; public: @@ -64,7 +64,7 @@ class CGOGN_RENDERING_API ShaderSimpleColor : public ShaderProgram * @param vbo_pos pointer on position vbo (XYZ) * @return true if ok */ - bool set_vao(unsigned int i, VBO* vbo_pos, unsigned int stride=0, unsigned first=0); + bool set_vao(uint32 i, VBO* vbo_pos, uint32 stride=0, unsigned first=0); }; } // namespace rendering diff --git a/cgogn/rendering/shaders/shader_vector_per_vertex.cpp b/cgogn/rendering/shaders/shader_vector_per_vertex.cpp index cb775e04..eb190d5d 100644 --- a/cgogn/rendering/shaders/shader_vector_per_vertex.cpp +++ b/cgogn/rendering/shaders/shader_vector_per_vertex.cpp @@ -99,7 +99,7 @@ void ShaderVectorPerVertex::set_length(float l) prg_.setUniformValue(unif_length_, l); } -bool ShaderVectorPerVertex::set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_normal) +bool ShaderVectorPerVertex::set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_normal) { if (i >= vaos_.size()) { diff --git a/cgogn/rendering/shaders/shader_vector_per_vertex.h b/cgogn/rendering/shaders/shader_vector_per_vertex.h index 3a728bd4..82dfd8c4 100644 --- a/cgogn/rendering/shaders/shader_vector_per_vertex.h +++ b/cgogn/rendering/shaders/shader_vector_per_vertex.h @@ -47,8 +47,8 @@ class CGOGN_RENDERING_API ShaderVectorPerVertex : public ShaderProgram }; // uniform ids - int unif_color_; - int unif_length_; + GLint unif_color_; + GLint unif_length_; public: @@ -73,7 +73,7 @@ class CGOGN_RENDERING_API ShaderVectorPerVertex : public ShaderProgram * @param vbo_norm pointer on normal vbo * @return true if ok */ - bool set_vao(unsigned int i, VBO* vbo_pos, VBO* vbo_norm); + bool set_vao(uint32 i, VBO* vbo_pos, VBO* vbo_norm); }; } // namespace rendering diff --git a/cgogn/rendering/shaders/vbo.h b/cgogn/rendering/shaders/vbo.h index 47815ded..29a3f5fb 100644 --- a/cgogn/rendering/shaders/vbo.h +++ b/cgogn/rendering/shaders/vbo.h @@ -40,13 +40,13 @@ class VBO { protected: - unsigned int nb_vectors_; - unsigned int vector_dimension_; + uint32 nb_vectors_; + uint32 vector_dimension_; QOpenGLBuffer buffer_; public: - inline VBO(unsigned int vec_dim) : + inline VBO(uint32 vec_dim) : nb_vectors_(), vector_dimension_(vec_dim) { @@ -75,10 +75,10 @@ class VBO * @param nb_vectors number of vectors * @param vector_dimension_ number of component of each vector */ - inline void allocate(int nb_vectors, unsigned int vector_dimension) + inline void allocate(uint32 nb_vectors, uint32 vector_dimension) { buffer_.bind(); - unsigned int total = nb_vectors * vector_dimension; + uint32 total = nb_vectors * vector_dimension; if (total != nb_vectors_ * vector_dimension_) // only allocate when > ? buffer_.allocate(total * sizeof(float)); nb_vectors_ = nb_vectors; @@ -114,7 +114,7 @@ class VBO * @param nb number of bytes to copy * @param src source pointer */ - inline void copy_data(unsigned int offset, unsigned int nb, void* src) + inline void copy_data(uint32 offset, uint32 nb, void* src) { buffer_.write(offset, src, nb); } @@ -122,12 +122,12 @@ class VBO /** * @brief dimension of vectors stored in buffer */ - inline int vector_dimension() const + inline uint32 vector_dimension() const { return vector_dimension_; } - unsigned int size() const + uint32 size() const { return nb_vectors_; } @@ -147,19 +147,19 @@ void update_vbo(const ATTR& attr, VBO& vbo) const typename ATTR::TChunkArray* ca = attr.get_data(); std::vector chunk_addr; - unsigned int byte_chunk_size; - unsigned int nb_chunks = ca->get_chunks_pointers(chunk_addr, byte_chunk_size); - const unsigned int vec_dim = geometry::nb_components_traits::value; + uint32 byte_chunk_size; + uint32 nb_chunks = ca->get_chunks_pointers(chunk_addr, byte_chunk_size); + const uint32 vec_dim = geometry::nb_components_traits::value; vbo.allocate(nb_chunks * ATTR::CHUNKSIZE, vec_dim); - const unsigned int vbo_blk_bytes = ATTR::CHUNKSIZE * vec_dim * sizeof(float); + const uint32 vbo_blk_bytes = ATTR::CHUNKSIZE * vec_dim * sizeof(float); if (std::is_same::Scalar, float>::value) { // copy vbo.bind(); - for (unsigned int i = 0; i < nb_chunks; ++i) + for (uint32 i = 0; i < nb_chunks; ++i) vbo.copy_data(i* vbo_blk_bytes, vbo_blk_bytes, chunk_addr[i]); vbo.release(); } @@ -167,12 +167,12 @@ void update_vbo(const ATTR& attr, VBO& vbo) { // copy (after conversion to float) float* float_buffer = new float[ATTR::CHUNKSIZE * vec_dim]; - for (unsigned int i = 0; i < nb_chunks; ++i) + for (uint32 i = 0; i < nb_chunks; ++i) { // transform double into float float* fit = float_buffer; double* src = reinterpret_cast(chunk_addr[i]); - for (unsigned int j = 0; j < ATTR::CHUNKSIZE * vec_dim; ++j) + for (uint32 j = 0; j < ATTR::CHUNKSIZE * vec_dim; ++j) *fit++ = *src++; vbo.bind(); vbo.copy_data(i* ATTR::CHUNKSIZE * vec_dim * sizeof(float), ATTR::CHUNKSIZE * vec_dim * sizeof(float),float_buffer); @@ -202,8 +202,8 @@ void update_vbo(const ATTR& attr, VBO& vbo, const FUNC& convert) // get chunk data pointers const typename ATTR::TChunkArray* ca = attr.get_data(); std::vector chunk_addr; - unsigned int byte_chunk_size; - unsigned int nb_chunks = ca->get_chunks_pointers(chunk_addr, byte_chunk_size); + uint32 byte_chunk_size; + uint32 nb_chunks = ca->get_chunks_pointers(chunk_addr, byte_chunk_size); // check that out of convert is float or std::array using Vec2f = std::array; @@ -212,7 +212,7 @@ void update_vbo(const ATTR& attr, VBO& vbo, const FUNC& convert) static_assert(check_func_return_type(FUNC,float) || check_func_return_type(FUNC,Vec2f) || check_func_return_type(FUNC,Vec3f) ||check_func_return_type(FUNC,Vec4f), "convert output must be float or std::array" ); // set vec dimension - unsigned int vec_dim = 0; + uint32 vec_dim = 0; if (check_func_return_type(FUNC,float) ) vec_dim = 1; else if (check_func_return_type(FUNC,Vec2f) ) @@ -227,10 +227,10 @@ void update_vbo(const ATTR& attr, VBO& vbo, const FUNC& convert) // copy (after conversion) using OutputConvert = typename function_traits::result_type; OutputConvert* dst = reinterpret_cast(vbo.lock_pointer()); - for (unsigned int i = 0; i < nb_chunks; ++i) + for (uint32 i = 0; i < nb_chunks; ++i) { InputConvert* typed_chunk = static_cast(chunk_addr[i]); - for (unsigned int j = 0; j < ATTR::CHUNKSIZE; ++j) + for (uint32 j = 0; j < ATTR::CHUNKSIZE; ++j) *dst++ = convert(typed_chunk[j]); } vbo.release_pointer(); @@ -264,8 +264,8 @@ void update_vbo(const ATTR& attr, const ATTR2& attr2, VBO& vbo, const FUNC& conv // get chunk data pointers const typename ATTR::TChunkArray* ca = attr.get_data(); std::vector chunk_addr; - unsigned int byte_chunk_size; - unsigned int nb_chunks = ca->get_chunks_pointers(chunk_addr, byte_chunk_size); + uint32 byte_chunk_size; + uint32 nb_chunks = ca->get_chunks_pointers(chunk_addr, byte_chunk_size); const typename ATTR::TChunkArray* ca2 = attr2.get_data(); std::vector chunk_addr2; @@ -278,7 +278,7 @@ void update_vbo(const ATTR& attr, const ATTR2& attr2, VBO& vbo, const FUNC& conv static_assert(check_func_return_type(FUNC,float) || check_func_return_type(FUNC,Vec2f) || check_func_return_type(FUNC,Vec3f) ||check_func_return_type(FUNC,Vec4f), "convert output must be float or std::array" ); // set vec dimension - unsigned int vec_dim = 0; + uint32 vec_dim = 0; if (check_func_return_type(FUNC,float) ) vec_dim = 1; else if (check_func_return_type(FUNC,Vec2f) ) @@ -295,11 +295,11 @@ void update_vbo(const ATTR& attr, const ATTR2& attr2, VBO& vbo, const FUNC& conv // out type conversion using OutputConvert = typename function_traits::result_type; OutputConvert* dst = reinterpret_cast(vbo.lock_pointer()); - for (unsigned int i = 0; i < nb_chunks; ++i) + for (uint32 i = 0; i < nb_chunks; ++i) { InputConvert* typed_chunk = static_cast(chunk_addr[i]); InputConvert2* typed_chunk2 = static_cast(chunk_addr2[i]); - for (unsigned int j = 0; j < ATTR::CHUNKSIZE; ++j) + for (uint32 j = 0; j < ATTR::CHUNKSIZE; ++j) *dst++ = convert(typed_chunk[j],typed_chunk2[j]); } vbo.release_pointer(); @@ -315,7 +315,7 @@ void update_vbo(const ATTR& attr, const ATTR2& attr2, VBO& vbo, const FUNC& conv * @param convert conversion lambda -> float or std::array */ template -void generate_vbo(const ATTR& attr, const std::vector& indices, VBO& vbo, const FUNC& convert) +void generate_vbo(const ATTR& attr, const std::vector& indices, VBO& vbo, const FUNC& convert) { // check that convert has 1 param static_assert(function_traits::arity == 1, "convert lambda function must have only one arg"); @@ -331,7 +331,7 @@ void generate_vbo(const ATTR& attr, const std::vector& indices, VB static_assert(check_func_return_type(FUNC,float) || check_func_return_type(FUNC,Vec2f) || check_func_return_type(FUNC,Vec3f) ||check_func_return_type(FUNC,Vec4f), "convert output must be float or std::array" ); // set vec dimension - unsigned int vec_dim = 0; + uint32 vec_dim = 0; if (check_func_return_type(FUNC,float) ) vec_dim = 1; else if (check_func_return_type(FUNC,Vec2f) ) @@ -342,13 +342,13 @@ void generate_vbo(const ATTR& attr, const std::vector& indices, VB vec_dim = 4; // allocate vbo - vbo.allocate(static_cast(indices.size()), vec_dim); + vbo.allocate(static_cast(indices.size()), vec_dim); // copy (after conversion) using OutputConvert = typename function_traits::result_type; OutputConvert* dst = reinterpret_cast(vbo.lock_pointer()); - for (unsigned int i: indices) + for (uint32 i: indices) *dst++ = convert(attr[i]); vbo.release_pointer(); diff --git a/cgogn/rendering/topo_render.cpp b/cgogn/rendering/topo_render.cpp index c71f0154..4eb40fc7 100644 --- a/cgogn/rendering/topo_render.cpp +++ b/cgogn/rendering/topo_render.cpp @@ -39,7 +39,7 @@ namespace rendering ShaderSimpleColor* TopoRender::shader_cpv_ = nullptr; ShaderBoldLine* TopoRender::shader_bl_ = nullptr; ShaderRoundPoint* TopoRender::shader_rp_ = nullptr; -int TopoRender::nb_instances_ = 0; +int32 TopoRender::nb_instances_ = 0; TopoRender::TopoRender(QOpenGLFunctions_3_3_Core* ogl33): ogl33_(ogl33), @@ -87,7 +87,7 @@ TopoRender::~TopoRender() void TopoRender::draw(const QMatrix4x4& projection, const QMatrix4x4& modelview, bool with_blending) { - unsigned int lw = 2.0; + uint32 lw = 2.0; if(with_blending) { ogl33_->glEnable(GL_BLEND); diff --git a/cgogn/rendering/topo_render.h b/cgogn/rendering/topo_render.h index fae70458..6dd2be73 100644 --- a/cgogn/rendering/topo_render.h +++ b/cgogn/rendering/topo_render.h @@ -50,14 +50,14 @@ class CGOGN_RENDERING_API TopoRender static ShaderSimpleColor* shader_cpv_; static ShaderBoldLine* shader_bl_; static ShaderRoundPoint* shader_rp_; - static int nb_instances_; + static int32 nb_instances_; VBO* vbo_darts_; VBO* vbo_relations_; - unsigned int vao_bl_; - unsigned int vao_bl2_; - unsigned int vao_rp_; + uint32 vao_bl_; + uint32 vao_bl2_; + uint32 vao_rp_; QOpenGLFunctions_3_3_Core* ogl33_; @@ -122,7 +122,7 @@ void TopoRender::update_map2(MAP& m, const typename MAP::template VertexAttribut local_vertices.clear(); VEC3 center; center.setZero(); - unsigned int count = 0u; + uint32 count = 0u; m.foreach_incident_vertex(f, [&] (Vertex v) { local_vertices.push_back(position[v]); @@ -132,22 +132,22 @@ void TopoRender::update_map2(MAP& m, const typename MAP::template VertexAttribut center /= Scalar(count); // phi2 mid-edge: N -> 2N-1 - for (unsigned int i=0; i N-1 - for (unsigned int i=0; i 3N-1 - for (unsigned int i=0; i 4N-1 - for (unsigned int i=0; iallocate(nbvec,3); vbo_darts_->bind(); vbo_darts_->copy_data(0, nbvec*12, out_pos[0].data()); @@ -209,7 +209,7 @@ void TopoRender::update_map3(MAP& m, const typename MAP::template VertexAttribut local_vertices.clear(); VEC3 center; center.setZero(); - unsigned int count = 0u; + uint32 count = 0u; m.foreach_incident_vertex(f, [&] (Vertex v) { local_vertices.push_back(position[v]); @@ -219,26 +219,26 @@ void TopoRender::update_map3(MAP& m, const typename MAP::template VertexAttribut center /= Scalar(count); // phi2 mid-edge: N -> 2N-1 - for (unsigned int i=0; i 3N-1 - for (unsigned int i=0; i N-1 - for (unsigned int i=0; i 4N-1 - for (unsigned int i=0; i 5N-1 - for (unsigned int i=0; iallocate(nbvec,3); vbo_darts_->bind(); vbo_darts_->copy_data(0, nbvec*12, out_pos[0].data()); diff --git a/cgogn/rendering/volume_render.h b/cgogn/rendering/volume_render.h index 9579064b..bea9550e 100644 --- a/cgogn/rendering/volume_render.h +++ b/cgogn/rendering/volume_render.h @@ -53,12 +53,12 @@ class CGOGN_RENDERING_API VolumeRender VBO* vbo_pos_; VBO* vbo_col_; - unsigned int vao1_; + uint32 vao1_; QColor face_color_; VBO* vbo_pos2_; - unsigned int vao2_; + uint32 vao2_; QColor edge_color_; @@ -123,7 +123,7 @@ void VolumeRender::update_face(MAP& m, const typename MAP::template VertexAttrib std::vector> out_pos; out_pos.reserve(1024*1024); - std::vector ear_indices; + std::vector ear_indices; ear_indices.reserve(256); m.foreach_cell([&] (Volume v) @@ -159,7 +159,7 @@ void VolumeRender::update_face(MAP& m, const typename MAP::template VertexAttrib }); }); - unsigned int nbvec = std::uint32_t(out_pos.size()); + uint32 nbvec = std::uint32_t(out_pos.size()); vbo_pos_->allocate(nbvec,3); vbo_pos_->bind(); vbo_pos_->copy_data(0, nbvec*12, out_pos[0].data()); @@ -184,7 +184,7 @@ void VolumeRender::update_face(MAP& m, const typename MAP::template VertexAttrib std::vector> out_color; out_color.reserve(1024*1024); - std::vector ear_indices; + std::vector ear_indices; ear_indices.reserve(256); m.foreach_cell([&] (Volume v) @@ -266,7 +266,7 @@ void VolumeRender::update_edge(MAP& m, const typename MAP::template VertexAttrib std::vector> out_pos; out_pos.reserve(1024*1024); - std::vector ear_indices; + std::vector ear_indices; ear_indices.reserve(256); m.foreach_cell([&] (Volume v) @@ -282,7 +282,7 @@ void VolumeRender::update_edge(MAP& m, const typename MAP::template VertexAttrib }); }); - unsigned int nbvec = std::uint32_t(out_pos.size()); + uint32 nbvec = std::uint32_t(out_pos.size()); vbo_pos2_->allocate(nbvec,3); vbo_pos2_->bind(); vbo_pos2_->copy_data(0, nbvec*12, out_pos[0].data()); From 3660fff5e8301e9d89e5ba6817805d965920988f Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Mon, 21 Mar 2016 22:09:43 +0100 Subject: [PATCH 377/402] fix wrong variable name --- cgogn/core/cmap/cmap3.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 1fd4a985..74c9e0d5 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -1009,14 +1009,14 @@ class CMap3_T : public CMap2_T inline void foreach_adjacent_vertex_through_face(Vertex2 v, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Vertex2), "Wrong function cell parameter type"); - foreach_dart_of_orbit(v, [this, &f] (Dart vd) + foreach_dart_of_orbit(v, [this, &func] (Dart vd) { Dart vd1 = this->phi1(vd); - this->foreach_dart_of_orbit(Face2(vd), [&f, vd, vd1] (Dart fd) + this->foreach_dart_of_orbit(Face2(vd), [&func, vd, vd1] (Dart fd) { // skip Vertex2 v itself and its first successor around current face if (fd != vd && fd != vd1) - f(Vertex2(fd)); + func(Vertex2(fd)); }); }); } @@ -1031,13 +1031,13 @@ class CMap3_T : public CMap2_T inline void foreach_adjacent_edge_through_face(Edge2 e, const FUNC& func) const { static_assert(check_func_parameter_type(FUNC, Edge2), "Wrong function cell parameter type"); - foreach_dart_of_orbit(e, [&f, this] (Dart ed) + foreach_dart_of_orbit(e, [this, &func] (Dart ed) { - this->foreach_dart_of_orbit(Face2(ed), [&f, ed] (Dart fd) + this->foreach_dart_of_orbit(Face2(ed), [&func, ed] (Dart fd) { // skip Edge2 e itself if (fd != ed) - f(Edge2(fd)); + func(Edge2(fd)); }); }); } From 644cfd0759b9952c6a0a3a024ba1e21b996be906 Mon Sep 17 00:00:00 2001 From: Sylvain Thery Date: Tue, 22 Mar 2016 11:07:56 +0100 Subject: [PATCH 378/402] int32 --- cgogn/core/cmap/cmap0.h | 2 +- cgogn/core/cmap/cmap1.h | 2 +- cgogn/core/cmap/cmap2.h | 2 +- cgogn/core/cmap/cmap3.h | 2 +- cgogn/core/cmap/map_base.h | 6 ++-- cgogn/core/container/chunk_array.h | 19 ++++++----- cgogn/core/container/chunk_array_container.h | 6 ++-- cgogn/core/container/chunk_array_factory.h | 25 +++++++++----- .../chunk_array/bench_chunk_array.cpp | 10 +++--- .../core/examples/chunk_array/chunk_array.cpp | 30 ++++++++-------- .../examples/chunk_array/chunk_array2.cpp | 2 +- cgogn/core/examples/map/map.cpp | 4 +-- cgogn/core/tests/cmap/cmap0_test.cpp | 6 ++-- cgogn/core/tests/cmap/cmap0_topo_test.cpp | 4 +-- cgogn/core/tests/cmap/cmap1_test.cpp | 8 ++--- cgogn/core/tests/cmap/cmap1_topo_test.cpp | 2 +- cgogn/core/tests/cmap/cmap2_test.cpp | 12 +++---- cgogn/core/tests/cmap/cmap2_topo_test.cpp | 12 +++---- cgogn/core/tests/utils/name_types_test.cpp | 27 +++++++-------- cgogn/core/utils/serialization.cpp | 2 +- cgogn/core/utils/serialization.h | 4 +-- cgogn/geometry/algos/ear_triangulation.h | 2 +- cgogn/geometry/types/geometry_traits.h | 4 +-- cgogn/io/import_ply_data.cpp | 14 ++++---- cgogn/io/import_ply_data.h | 27 ++++++++------- cgogn/io/io_utils.cpp | 8 ++--- cgogn/io/obj_io.h | 4 +-- cgogn/io/off_io.h | 2 +- cgogn/io/vtk_io.h | 18 +++++----- cgogn/multiresolution/cph/ihcmap2.h | 2 +- cgogn/multiresolution/mrcmap/mr_base.h | 2 +- cgogn/rendering/drawer.cpp | 4 +-- cgogn/rendering/drawer.h | 2 +- cgogn/rendering/examples/picking_viewer.cpp | 2 +- cgogn/rendering/map_render.h | 2 +- cgogn/rendering/shaders/shader_program.h | 2 +- cgogn/rendering/shaders/vbo.h | 2 +- thirdparty/OffBinConverter/off_ascii2bin.cpp | 34 ++++++++++--------- 38 files changed, 163 insertions(+), 155 deletions(-) diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index d79b67f2..7da1e744 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -34,7 +34,7 @@ class CMap0_T : public MapBase { public: - static const int PRIM_SIZE = 1; + static const int32 PRIM_SIZE = 1; using MapTraits = MAP_TRAITS; using MapType = MAP_TYPE; diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 776744a3..4c179504 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -34,7 +34,7 @@ class CMap1_T : public CMap0_T { public: - static const int PRIM_SIZE = 1; + static const int32 PRIM_SIZE = 1; using MapTraits = MAP_TRAITS; using MapType = MAP_TYPE ; diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index b3ff0295..1d8cc79d 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -37,7 +37,7 @@ class CMap2_T : public CMap1_T { public: - static const int PRIM_SIZE = 1; + static const int32 PRIM_SIZE = 1; using MapTraits = MAP_TRAITS; using MapType = MAP_TYPE; diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index ddddfde9..7d360287 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -37,7 +37,7 @@ class CMap3_T : public CMap2_T { public: - static const int PRIM_SIZE = 1; + static const int32 PRIM_SIZE = 1; using MapTraits = MAP_TRAITS; using MapType = MAP_TYPE; diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 6d325345..db521a56 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -1249,9 +1249,9 @@ class MapBase : public MapBaseData uint32 nbc = PARALLEL_BUFFER_SIZE; // do block of PARALLEL_BUFFER_SIZE only if nb cells is huge else just divide - if ( (static_cast(last - it) < 16*nb_threads_pool*PARALLEL_BUFFER_SIZE ) - && (static_cast(last - it) > nb_threads_pool)) - nbc = static_cast((last - it) / nb_threads_pool); + if ( (uint32(last - it) < 16*nb_threads_pool*PARALLEL_BUFFER_SIZE ) + && (uint32(last - it) > nb_threads_pool)) + nbc = uint32((last - it) / nb_threads_pool); uint32 local_end = std::min(it+nbc, last); diff --git a/cgogn/core/container/chunk_array.h b/cgogn/core/container/chunk_array.h index 8a80b420..4c23ce86 100644 --- a/cgogn/core/container/chunk_array.h +++ b/cgogn/core/container/chunk_array.h @@ -131,7 +131,7 @@ class ChunkArray : public ChunkArrayGen */ uint32 get_nb_chunks() const override { - return static_cast(table_data_.size()); + return uint32(table_data_.size()); } /** @@ -140,7 +140,7 @@ class ChunkArray : public ChunkArrayGen */ uint32 capacity() const override { - return static_cast(table_data_.size())*CHUNKSIZE; + return uint32(table_data_.size())*CHUNKSIZE; } /** @@ -169,7 +169,7 @@ class ChunkArray : public ChunkArrayGen for (typename std::vector::const_iterator it = table_data_.begin(); it != table_data_.end(); ++it) addr.push_back(*it); - return static_cast(addr.size()); + return uint32(addr.size()); } /** @@ -475,7 +475,7 @@ class ChunkArray : public ChunkArrayGen */ uint32 get_nb_chunks() const override { - return static_cast(table_data_.size()); + return uint32(table_data_.size()); } /** @@ -484,7 +484,7 @@ class ChunkArray : public ChunkArrayGen */ uint32 capacity() const override { - return static_cast(table_data_.size())*CHUNKSIZE/32u; + return uint32(table_data_.size())*CHUNKSIZE/32u; } /** @@ -513,7 +513,7 @@ class ChunkArray : public ChunkArrayGen for (typename std::vector::const_iterator it = table_data_.begin(); it != table_data_.end(); ++it) addr.push_back(*it); - return static_cast(addr.size()); + return uint32(addr.size()); } /** @@ -692,9 +692,10 @@ class ChunkArray : public ChunkArrayGen { for (uint32 * const ptr : table_data_) { -#pragma omp for - for (int j = 0; j < int(CHUNKSIZE/32); ++j) - ptr[j] = 0u; +//#pragma omp for +// for (int32 j = 0; j < int32(CHUNKSIZE/32); ++j) +// ptr[j] = 0u; + std::fill_n(ptr,CHUNKSIZE/32,0u); } } diff --git a/cgogn/core/container/chunk_array_container.h b/cgogn/core/container/chunk_array_container.h index 961ee8e8..f87271e6 100644 --- a/cgogn/core/container/chunk_array_container.h +++ b/cgogn/core/container/chunk_array_container.h @@ -850,14 +850,14 @@ class ChunkArrayContainer // save info (size+used_lines+max_lines+sizeof names) std::vector buffer; buffer.reserve(1024); - buffer.push_back(static_cast(table_arrays_.size())); + buffer.push_back(uint32(table_arrays_.size())); buffer.push_back(nb_used_lines_); buffer.push_back(nb_max_lines_); for(uint32 i = 0u; i < table_arrays_.size(); ++i) { - buffer.push_back(static_cast(names_[i].size()+1)); - buffer.push_back(static_cast(type_names_[i].size()+1)); + buffer.push_back(uint32(names_[i].size()+1)); + buffer.push_back(uint32(type_names_[i].size()+1)); } fs.write(reinterpret_cast(&(buffer[0])), std::streamsize(buffer.size()*sizeof(uint32))); diff --git a/cgogn/core/container/chunk_array_factory.h b/cgogn/core/container/chunk_array_factory.h index b11325b0..2022dc14 100644 --- a/cgogn/core/container/chunk_array_factory.h +++ b/cgogn/core/container/chunk_array_factory.h @@ -75,16 +75,23 @@ class ChunkArrayFactory register_CA(); register_CA(); - register_CA(); - register_CA(); - register_CA(); - register_CA(); - register_CA(); - register_CA(); - register_CA(); + register_CA(); + register_CA(); + register_CA(); + register_CA(); + register_CA(); + register_CA(); register_CA(); - register_CA(); - register_CA(); + register_CA(); +// register_CA(); +// register_CA(); +// register_CA(); +// register_CA(); +// register_CA(); +// register_CA(); +// register_CA(); +// register_CA(); +// register_CA(); register_CA(); register_CA(); register_CA(); diff --git a/cgogn/core/examples/chunk_array/bench_chunk_array.cpp b/cgogn/core/examples/chunk_array/bench_chunk_array.cpp index 3ad48ac4..2d89b213 100644 --- a/cgogn/core/examples/chunk_array/bench_chunk_array.cpp +++ b/cgogn/core/examples/chunk_array/bench_chunk_array.cpp @@ -43,7 +43,7 @@ int test1() std::cout << "= TEST 1 = ref unsigned char" << std::endl; ChunkArrayContainer container; - ChunkArray* att1 = container.add_attribute("entier"); + ChunkArray* att1 = container.add_attribute("entier"); ChunkArray* att2 = container.add_attribute("reel"); ChunkArray* att3 = container.add_attribute("Vec3f"); @@ -52,7 +52,7 @@ int test1() for(uint32 i = container.begin(); i != container.end(); container.next(i)) { - (*att1)[i] = 1+int(i); + (*att1)[i] = 1+int32(i); (*att2)[i] = 3.0f + 0.1f*float(i); (*att3)[i] = Vec3f(float(i), float(i), float(i)); } @@ -79,7 +79,7 @@ int test2() std::cout << "= TEST 2 = ref bool" << std::endl; ChunkArrayContainer container; - ChunkArray* att1 = container.add_attribute("entier"); + ChunkArray* att1 = container.add_attribute("entier"); ChunkArray* att2 = container.add_attribute("reel"); ChunkArray* att3 = container.add_attribute("Vec3f"); @@ -88,7 +88,7 @@ int test2() for(uint32 i = container.begin(); i != container.end(); container.next(i)) { - (*att1)[i] = 1+int(i); + (*att1)[i] = 1+int32(i); (*att2)[i] = 3.0f + 0.1f*float(i); (*att3)[i] = Vec3f(float(i), float(i), float(i)); } @@ -182,7 +182,7 @@ int test5() for(uint32 i = container.begin(); i < container.end(); i += 9) container.remove_lines<1>(i); - int total = 0; + int32 total = 0; for (uint32 j = 0; j < 50; ++j) { for(uint32 i = container.begin(); i != container.end(); container.next(i)) diff --git a/cgogn/core/examples/chunk_array/chunk_array.cpp b/cgogn/core/examples/chunk_array/chunk_array.cpp index ce23bfe4..8ae8dac3 100644 --- a/cgogn/core/examples/chunk_array/chunk_array.cpp +++ b/cgogn/core/examples/chunk_array/chunk_array.cpp @@ -22,7 +22,7 @@ int test1() std::cout << "############### TEST 1 ###############" << std::endl; ChunkArrayContainer container; - ChunkArray* att1 = container.add_attribute("entier"); + ChunkArray* att1 = container.add_attribute("entier"); ChunkArray* att2 = container.add_attribute("reel"); for (uint32 i = 0; i < 41; ++i) @@ -30,7 +30,7 @@ int test1() for(uint32 i = container.begin(); i != container.end(); container.next(i)) { - (*att1)[i] = 1+int(i); + (*att1)[i] = 1+int32(i); (*att2)[i] = 3.0f + 0.1f*float(i); } @@ -87,13 +87,13 @@ int test2() std::cout << "############### TEST 2 ###############" << std::endl; ChunkArrayContainer container; - ChunkArray* att1 = container.add_attribute("entier"); + ChunkArray* att1 = container.add_attribute("entier"); - for (int i = 0; i < 13; ++i) + for (uint32 i = 0; i < 13; ++i) container.insert_lines<3>(); for(uint32 i = container.begin(); i != container.end(); container.next(i)) - (*att1)[i] = 1+int(i); + (*att1)[i] = 1+int32(i); for(uint32 i = container.begin(); i != container.end(); container.next(i)) { @@ -158,22 +158,22 @@ int test3() std::cout << "############### TEST 3 ###############" << std::endl; ChunkArrayContainer container; - ChunkArray* att1 = container.add_attribute("entier"); - ChunkArray >* att2 = container.add_attribute >("V_entier"); - ChunkArray >* att3 = container.add_attribute >("L_entier"); + ChunkArray* att1 = container.add_attribute("entier"); + ChunkArray >* att2 = container.add_attribute >("V_entier"); + ChunkArray >* att3 = container.add_attribute >("L_entier"); for (uint32 i = 0; i < 13; ++i) container.insert_lines<3>(); - std::vector vect = (*att2)[0]; + std::vector vect = (*att2)[0]; for(uint32 i = container.begin(); i != container.end(); container.next(i)) { - (*att1)[i] = 1+int(i); + (*att1)[i] = 1+int32(i); for (uint32 j = 0; j < i; ++j) - (*att2)[i].push_back(int(j)); + (*att2)[i].push_back(int32(j)); for (uint32 j = 0; j < i/2; ++j) - (*att3)[i].push_front(int(j)); + (*att3)[i].push_front(int32(j)); } container.remove_lines<3>(3); @@ -215,7 +215,7 @@ int test4() using vecvecdouble = std::vector< std::vector< double > >; using veclistdouble = std::vector< std::list< double > >; ChunkArrayContainer container; - ChunkArray* att1 = container.add_attribute("entier"); + ChunkArray* att1 = container.add_attribute("entier"); ChunkArray* att2 = container.add_attribute("reel"); ChunkArray* att3 = container.add_attribute("bools"); ChunkArray* att4 = container.add_attribute("vecvecdouble"); @@ -226,7 +226,7 @@ int test4() for(uint32 i = container.begin(); i != container.end(); container.next(i)) { - (*att1)[i] = 1+int(i); + (*att1)[i] = 1+int32(i); (*att2)[i] = 3.0f + 0.1f*float(i); (*att3).set_value(i, static_cast(i%2 != 0)); (*att4)[i] = {{3.0 + 0.1*double(i),15.0 + 0.1*double(i)}, {103.0 + 0.1*double(i), 203.0 + 0.1*double(i), 303.0 + 0.1*double(i)}}; @@ -245,7 +245,7 @@ int test4() cont2.load(ifi); ifi.close(); - ChunkArray* load_att1 = cont2.get_attribute("entier"); + ChunkArray* load_att1 = cont2.get_attribute("entier"); ChunkArray* load_att2 = cont2.get_attribute("reel"); ChunkArray* load_att3 = cont2.get_attribute("bools"); ChunkArray* load_att4 = cont2.get_attribute("vecvecdouble"); diff --git a/cgogn/core/examples/chunk_array/chunk_array2.cpp b/cgogn/core/examples/chunk_array/chunk_array2.cpp index 090e9924..cfc2646e 100644 --- a/cgogn/core/examples/chunk_array/chunk_array2.cpp +++ b/cgogn/core/examples/chunk_array/chunk_array2.cpp @@ -10,7 +10,7 @@ using namespace cgogn::numerics; const uint32 SIZE = 32u; template using ChunkArray = cgogn::ChunkArray; -using ChunkArrayContainer = cgogn::ChunkArrayContainer; +using ChunkArrayContainer = cgogn::ChunkArrayContainer; using ChunkArrayFactory = cgogn::ChunkArrayFactory; using DoubleVecList = std::list< std::vector< double > >; diff --git a/cgogn/core/examples/map/map.cpp b/cgogn/core/examples/map/map.cpp index 8952e8d7..ddfec119 100644 --- a/cgogn/core/examples/map/map.cpp +++ b/cgogn/core/examples/map/map.cpp @@ -7,7 +7,7 @@ #include using namespace cgogn; - +using namespace cgogn::numerics; using Map1 = CMap1; using Map2 = CMap2; @@ -65,7 +65,7 @@ int test1(MAP& map) typename MAP::template FaceAttributeHandler ahf = map.template add_attribute("floats"); // get attribute and change type (dangerous!) - typename MAP::template VertexAttributeHandler ahf2 = map.template get_attribute_force_type("floats"); + typename MAP::template VertexAttributeHandler ahf2 = map.template get_attribute_force_type("floats"); map.remove_attribute(ahf); std::cout << "ahf valid : " << std::boolalpha << ahf.is_valid() << std::endl; diff --git a/cgogn/core/tests/cmap/cmap0_test.cpp b/cgogn/core/tests/cmap/cmap0_test.cpp index 07fcf840..80a92547 100644 --- a/cgogn/core/tests/cmap/cmap0_test.cpp +++ b/cgogn/core/tests/cmap/cmap0_test.cpp @@ -45,7 +45,7 @@ class CMap0Test : public ::testing::Test public: using testCMap0 = CMap0; - using VertexAttributeHandler = testCMap0::VertexAttributeHandler; + using VertexAttributeHandler = testCMap0::VertexAttributeHandler; using Vertex = testCMap0::Vertex; protected: @@ -63,8 +63,8 @@ class CMap0Test : public ::testing::Test CMap0Test() { darts_.reserve(NB_MAX); - std::srand(static_cast(std::time(0))); - cmap_.add_attribute("vertices"); + std::srand(uint32(std::time(0))); + cmap_.add_attribute("vertices"); } /*! diff --git a/cgogn/core/tests/cmap/cmap0_topo_test.cpp b/cgogn/core/tests/cmap/cmap0_topo_test.cpp index b000c7e4..6c1057b6 100644 --- a/cgogn/core/tests/cmap/cmap0_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap0_topo_test.cpp @@ -58,7 +58,7 @@ class CMap0TopoTest : public ::testing::Test CMap0TopoTest() { darts_.reserve(NB_MAX); - std::srand(static_cast(std::time(0))); + std::srand(uint32(std::time(0))); } /*! @@ -108,7 +108,7 @@ TEST_F(CMap0TopoTest, add_vertex) TEST_F(CMap0TopoTest, remove_vertex) { add_vertices(NB_MAX); - int count_vertices = NB_MAX; + int32 count_vertices = NB_MAX; cmap_.remove_vertex(Vertex(darts_.back())); --count_vertices; diff --git a/cgogn/core/tests/cmap/cmap1_test.cpp b/cgogn/core/tests/cmap/cmap1_test.cpp index 7b3a9d16..f49df7d9 100644 --- a/cgogn/core/tests/cmap/cmap1_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_test.cpp @@ -60,10 +60,10 @@ class CMap1Test : public ::testing::Test CMap1Test() { darts_.reserve(NB_MAX); - std::srand(static_cast(std::time(0))); + std::srand(uint32(std::time(0))); - cmap_.add_attribute("vertices"); - cmap_.add_attribute("faces"); + cmap_.add_attribute("vertices"); + cmap_.add_attribute("faces"); } /*! @@ -118,7 +118,7 @@ TEST_F(CMap1Test, add_face) TEST_F(CMap1Test, remove_face) { uint32 count_vertices = add_faces(NB_MAX); - int count_faces = NB_MAX; + int32 count_faces = NB_MAX; for (Dart d : darts_) { diff --git a/cgogn/core/tests/cmap/cmap1_topo_test.cpp b/cgogn/core/tests/cmap/cmap1_topo_test.cpp index 48526eaa..8fa280b1 100644 --- a/cgogn/core/tests/cmap/cmap1_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap1_topo_test.cpp @@ -56,7 +56,7 @@ class CMap1TopoTest : public CMap1, public ::testing::Test CMap1TopoTest() { darts_.reserve(NB_MAX); - std::srand(static_cast(std::time(0))); + std::srand(uint32(std::time(0))); } /*! diff --git a/cgogn/core/tests/cmap/cmap2_test.cpp b/cgogn/core/tests/cmap/cmap2_test.cpp index 29224b3a..a96d4424 100644 --- a/cgogn/core/tests/cmap/cmap2_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_test.cpp @@ -64,13 +64,13 @@ class CMap2Test : public ::testing::Test CMap2Test() { darts_.reserve(NB_MAX); - std::srand(static_cast(std::time(0))); + std::srand(uint32(std::time(0))); - cmap_.add_attribute("darts"); - cmap_.add_attribute("vertices"); - cmap_.add_attribute("edges"); - cmap_.add_attribute("faces"); - cmap_.add_attribute("volumes"); + cmap_.add_attribute("darts"); + cmap_.add_attribute("vertices"); + cmap_.add_attribute("edges"); + cmap_.add_attribute("faces"); + cmap_.add_attribute("volumes"); } /*! diff --git a/cgogn/core/tests/cmap/cmap2_topo_test.cpp b/cgogn/core/tests/cmap/cmap2_topo_test.cpp index 6968e2a7..006c7214 100644 --- a/cgogn/core/tests/cmap/cmap2_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_topo_test.cpp @@ -65,7 +65,7 @@ class CMap2TopoTest : public CMap2, public ::testing::Test CMap2TopoTest() { darts_.reserve(NB_MAX); - std::srand(static_cast(std::time(0))); + std::srand(uint32(std::time(0))); } /*! @@ -351,11 +351,11 @@ TEST_F(CMap2TopoTest, close_map) add_closed_surfaces(); // add attributes to initialize the indexation - add_attribute("darts"); - add_attribute("vertices"); - add_attribute("edges"); - add_attribute("faces"); - add_attribute("volumes"); + add_attribute("darts"); + add_attribute("vertices"); + add_attribute("edges"); + add_attribute("faces"); + add_attribute("volumes"); EXPECT_TRUE(check_map_integrity()); // create some random holes (full removal or partial unsewing of faces) diff --git a/cgogn/core/tests/utils/name_types_test.cpp b/cgogn/core/tests/utils/name_types_test.cpp index c7447d9f..79900c8f 100644 --- a/cgogn/core/tests/utils/name_types_test.cpp +++ b/cgogn/core/tests/utils/name_types_test.cpp @@ -25,40 +25,37 @@ #include #include +using namespace cgogn::numerics; + TEST(NameTypesTest, NumTypes) { - - using signed_char = signed char; - using unsigned_char = unsigned char; - using unsigned_short = unsigned short; - using uint = cgogn::uint32; - using ulint = unsigned long; using llint = long long; using ullint = unsigned long long; EXPECT_EQ(cgogn::name_of_type(bool()), "bool"); EXPECT_EQ(cgogn::name_of_type(char()), "char"); - EXPECT_EQ(cgogn::name_of_type(signed_char()), "signed char"); - EXPECT_EQ(cgogn::name_of_type(unsigned_char()), "unsigned char"); + EXPECT_EQ(cgogn::name_of_type(int8()), "signed char"); + EXPECT_EQ(cgogn::name_of_type(uint8()), "unsigned char"); EXPECT_EQ(cgogn::name_of_type(wchar_t()), "wchar_t"); #if _MSC_VER == 1800 // VS2013 EXPECT_EQ(cgogn::name_of_type(char16_t()), "unsigned short"); - EXPECT_EQ(cgogn::name_of_type(char32_t()), "uint32"); + EXPECT_EQ(cgogn::name_of_type(char32_t()), "unsigned int"); #else EXPECT_EQ(cgogn::name_of_type(char16_t()), "char16_t"); EXPECT_EQ(cgogn::name_of_type(char32_t()), "char32_t"); #endif // VS2013 - EXPECT_EQ(cgogn::name_of_type(short()), "short"); - EXPECT_EQ(cgogn::name_of_type(unsigned_short()), "unsigned short"); - EXPECT_EQ(cgogn::name_of_type(int()), "int"); + EXPECT_EQ(cgogn::name_of_type(int16()), "short"); + EXPECT_EQ(cgogn::name_of_type(uint16()), "unsigned short"); + EXPECT_EQ(cgogn::name_of_type(int32()), "int"); - EXPECT_EQ(cgogn::name_of_type(uint()), "uint32"); - EXPECT_EQ(cgogn::name_of_type(long()), "long"); - EXPECT_EQ(cgogn::name_of_type(ulint()), "unsigned long"); + EXPECT_EQ(cgogn::name_of_type(uint32()), "unsigned int"); + EXPECT_EQ(cgogn::name_of_type(int64()), "long"); + EXPECT_EQ(cgogn::name_of_type(uint64()), "unsigned long"); EXPECT_EQ(cgogn::name_of_type(llint()), "long long"); EXPECT_EQ(cgogn::name_of_type(ullint()), "unsigned long long"); + EXPECT_EQ(cgogn::name_of_type(float()), "float"); EXPECT_EQ(cgogn::name_of_type(double()), "double"); diff --git a/cgogn/core/utils/serialization.cpp b/cgogn/core/utils/serialization.cpp index 31136504..b54f9fbe 100644 --- a/cgogn/core/utils/serialization.cpp +++ b/cgogn/core/utils/serialization.cpp @@ -65,7 +65,7 @@ CGOGN_CORE_API void save(std::ostream& ostream, std::string const* for (std::size_t i = 0; i < quantity; ++i) { - const uint32 size = static_cast(src[i].length()); + const uint32 size = uint32(src[i].length()); ostream.write(reinterpret_cast(&size), sizeof(uint32)); const char* str = src[i].c_str(); ostream.write(str, size); diff --git a/cgogn/core/utils/serialization.h b/cgogn/core/utils/serialization.h index 137d436c..4d467cb3 100644 --- a/cgogn/core/utils/serialization.h +++ b/cgogn/core/utils/serialization.h @@ -152,7 +152,7 @@ void save(std::ostream& ostream, std::vector const* src, std::size_t quantity for (std::size_t i = 0u; i < quantity; ++i) { - const uint32 size = static_cast(src[i].size()); + const uint32 size = uint32(src[i].size()); ostream.write(reinterpret_cast(&size), sizeof(uint32)); save(ostream, &(src[i][0]), size); } @@ -202,7 +202,7 @@ void save(std::ostream& ostream, std::list const* src, std::size_t quantity) for (std::size_t i = 0u; i < quantity; ++i) { - const uint32 size = static_cast(src[i].size()); + const uint32 size = uint32(src[i].size()); ostream.write(reinterpret_cast(&size), sizeof(uint32)); for (const auto& elem : src[i]) save(ostream, &elem, 1); diff --git a/cgogn/geometry/algos/ear_triangulation.h b/cgogn/geometry/algos/ear_triangulation.h index fb29c8af..8e9556d5 100644 --- a/cgogn/geometry/algos/ear_triangulation.h +++ b/cgogn/geometry/algos/ear_triangulation.h @@ -49,7 +49,7 @@ class EarTriangulation public: using VPMS = std::multiset; - int id; + int32 id; Vertex vert_; Scalar value_; Scalar length_; diff --git a/cgogn/geometry/types/geometry_traits.h b/cgogn/geometry/types/geometry_traits.h index d50a9ed5..fd4dee3f 100644 --- a/cgogn/geometry/types/geometry_traits.h +++ b/cgogn/geometry/types/geometry_traits.h @@ -49,7 +49,7 @@ struct vector_traits>> }; // specialization 2 : Eigen::Vector -template +template struct vector_traits> { static const std::size_t SIZE = Rows; @@ -89,7 +89,7 @@ struct nb_components_traits>> const static uint32 value = size; }; -template +template struct nb_components_traits> { const static uint32 value = Rows; diff --git a/cgogn/io/import_ply_data.cpp b/cgogn/io/import_ply_data.cpp index a6b22c49..3679c39b 100644 --- a/cgogn/io/import_ply_data.cpp +++ b/cgogn/io/import_ply_data.cpp @@ -81,7 +81,7 @@ PlyImportData::~PlyImportData() { // if (vlist!= NULL) // { -// for (int i=0; inum_elem_types; i++) + for (int32 i = 0; i < in_ply->num_elem_types; i++) { - int elem_count; + int32 elem_count; /* prepare to read the i'th list of elements */ char *elem_name = setup_element_read_ply (in_ply, i, &elem_count); @@ -155,7 +155,7 @@ bool PlyImportData::read_file(const std::string& filename) setup_property_ply (in_ply, &vert_props[1]); setup_property_ply (in_ply, &vert_props[2]); - for (int j = 0; j < in_ply->elems[i]->nprops; j++) + for (int32 j = 0; j < in_ply->elems[i]->nprops; j++) { PlyProperty *prop; prop = in_ply->elems[i]->props[j]; @@ -201,7 +201,7 @@ bool PlyImportData::read_file(const std::string& filename) offsetof(VertexPly,other_props)); /* grab all the vertex elements */ - for (int j = 0; j < elem_count; j++) { + for (int32 j = 0; j < elem_count; j++) { vlist[j] = (VertexPly *) malloc (sizeof (VertexPly)); vlist[j]->r = 1; vlist[j]->g = 1; @@ -222,7 +222,7 @@ bool PlyImportData::read_file(const std::string& filename) offsetof(FacePly,other_props)); /* grab all the face elements */ - for (int j = 0; j < elem_count; j++) { + for (int32 j = 0; j < elem_count; j++) { flist[j] = (FacePly *) malloc (sizeof (FacePly)); get_element_ply (in_ply, (void *) flist[j]); } diff --git a/cgogn/io/import_ply_data.h b/cgogn/io/import_ply_data.h index 88340f79..3defe9bc 100644 --- a/cgogn/io/import_ply_data.h +++ b/cgogn/io/import_ply_data.h @@ -30,6 +30,7 @@ #include #include +#include #include namespace cgogn @@ -43,21 +44,21 @@ class CGOGN_IO_API PlyImportData public: template - void vertex_position(int i, VEC& P) { P[0] = vlist[i]->x; P[1] = vlist[i]->y; P[2] = vlist[i]->z;} + void vertex_position(int32 i, VEC& P) { P[0] = vlist[i]->x; P[1] = vlist[i]->y; P[2] = vlist[i]->z;} template - void vertex_normal(int i, VEC& N) { N[0] = vlist[i]->nx; N[1] = vlist[i]->ny; N[2] = vlist[i]->nz;} + void vertex_normal(int32 i, VEC& N) { N[0] = vlist[i]->nx; N[1] = vlist[i]->ny; N[2] = vlist[i]->nz;} template - void vertexColorUint8(int i, VEC& C) { C[0] = vlist[i]->red; C[1] = vlist[i]->green; C[2] = vlist[i]->blue;} + void vertexColorUint8(int32 i, VEC& C) { C[0] = vlist[i]->red; C[1] = vlist[i]->green; C[2] = vlist[i]->blue;} template - void vertex_color_float32(int i, VEC& C) { C[0] = vlist[i]->r; C[1] = vlist[i]->g; C[2] = vlist[i]->b;} + void vertex_color_float32(int32 i, VEC& C) { C[0] = vlist[i]->r; C[1] = vlist[i]->g; C[2] = vlist[i]->b;} - inline int nb_vertices() { return nverts;} + inline int32 nb_vertices() { return nverts;} - inline int nb_faces() { return nfaces;} + inline int32 nb_faces() { return nfaces;} /** * each vertex has a normal vector @@ -74,12 +75,12 @@ class CGOGN_IO_API PlyImportData /** * get the number of edges of a face */ - int get_face_valence(int i) { return flist[i]->nverts;} + int32 get_face_valence(int32 i) { return flist[i]->nverts;} /** - * get a table (pointer) of int of vertex indices of + * get a table (pointer) of int32 of vertex indices of */ - int* get_face_indices(int i) { return flist[i]->verts;} + int32* get_face_indices(int32 i) { return flist[i]->verts;} PlyImportData(); @@ -102,7 +103,7 @@ class CGOGN_IO_API PlyImportData typedef struct FacePly { unsigned char nverts; /* number of vertex indices in list */ - int *verts; /* vertex index list */ + int32 *verts; /* vertex index list */ void *other_props; /* other properties */ } FacePly; @@ -115,14 +116,14 @@ class CGOGN_IO_API PlyImportData /*** the PLY object ***/ - int nverts,nfaces; + int32 nverts,nfaces; VertexPly **vlist; FacePly **flist; PlyOtherProp *vert_other,*face_other; - int per_vertex_color_float32, per_vertex_color_uint8 ; - int has_normals_; + int32 per_vertex_color_float32, per_vertex_color_uint8 ; + int32 has_normals_; }; } // namespace io diff --git a/cgogn/io/io_utils.cpp b/cgogn/io/io_utils.cpp index 42f87489..6632d359 100644 --- a/cgogn/io/io_utils.cpp +++ b/cgogn/io/io_utils.cpp @@ -77,11 +77,11 @@ CGOGN_IO_API std::vector zlib_decompress(const char* input, DataT if (header_type == DataType::UINT64) { for (uint32 i = 0; i < nb_blocks; ++i) - compressed_size[i] = static_cast(*reinterpret_cast(&header_data[8u * i])); + compressed_size[i] = uint32(*reinterpret_cast(&header_data[8u * i])); } else { for (uint32 i = 0; i < nb_blocks; ++i) - compressed_size[i] = static_cast(*reinterpret_cast(&header_data[4u * i])); + compressed_size[i] = uint32(*reinterpret_cast(&header_data[4u * i])); } std::vector data = base64_decode(input, header_end +length); @@ -100,12 +100,12 @@ CGOGN_IO_API std::vector zlib_decompress(const char* input, DataT ret = inflateInit(&zstream); zstream.avail_in = compressed_size[i]; zstream.next_in = &data[in_data_it]; - zstream.avail_out = static_cast( (i == nb_blocks - 1u) ? last_block_size : uncompressed_block_size ); + zstream.avail_out = uint32( (i == nb_blocks - 1u) ? last_block_size : uncompressed_block_size ); zstream.next_out = &res[out_data_it]; ret = inflate(&zstream, Z_NO_FLUSH); ret = inflateEnd(&zstream); in_data_it += compressed_size[i]; - out_data_it += static_cast(uncompressed_block_size); + out_data_it += uint32(uncompressed_block_size); } return res; } diff --git a/cgogn/io/obj_io.h b/cgogn/io/obj_io.h index 5a0fad29..973c3fc8 100644 --- a/cgogn/io/obj_io.h +++ b/cgogn/io/obj_io.h @@ -86,7 +86,7 @@ class ObjSurfaceImport : public SurfaceImport { std::getline(fp, line); } while (!fp.eof()); - this->nb_vertices_ = static_cast(vertices_id.size()); + this->nb_vertices_ = uint32(vertices_id.size()); fp.clear(); fp.seekg(0, std::ios::beg); @@ -128,7 +128,7 @@ class ObjSurfaceImport : public SurfaceImport { } } - uint32 n = static_cast(table.size()); + uint32 n = uint32(table.size()); this->faces_nb_edges_.push_back(static_cast(n)); for (uint32 j = 0; j < n; ++j) { diff --git a/cgogn/io/off_io.h b/cgogn/io/off_io.h index 86bf6080..25771319 100644 --- a/cgogn/io/off_io.h +++ b/cgogn/io/off_io.h @@ -232,7 +232,7 @@ class OffSurfaceImport : public SurfaceImport { fp.ignore(std::numeric_limits::max(), '\n'); fp >> line; } - return static_cast((std::stoul(line))); + return uint32((std::stoul(line))); } }; diff --git a/cgogn/io/vtk_io.h b/cgogn/io/vtk_io.h index b12ed283..a3b0ef44 100644 --- a/cgogn/io/vtk_io.h +++ b/cgogn/io/vtk_io.h @@ -635,8 +635,8 @@ class VtkSurfaceImport : public VtkIO: return false; this->fill_surface_import(); - this->nb_vertices_ = static_cast(this->positions_.size()); - this->nb_faces_ = static_cast(this->offsets_.size()); + this->nb_vertices_ = uint32(this->positions_.size()); + this->nb_faces_ = uint32(this->offsets_.size()); auto cells_it = this->cells_.get_vec()->begin(); uint32 last_offset = 0u; @@ -685,8 +685,8 @@ class VtkSurfaceImport : public VtkIO: private: inline void fill_surface_import() { - this->nb_vertices_ = static_cast(this->positions_.size()); - this->nb_faces_ = static_cast(this->cell_types_.size()); + this->nb_vertices_ = uint32(this->positions_.size()); + this->nb_faces_ = uint32(this->cell_types_.size()); auto cells_it = static_cast*>(this->cells_.get_data())->begin(); const std::vector* cell_types_vec = static_cast*>(this->cell_types_.get_data()); @@ -697,7 +697,7 @@ class VtkSurfaceImport : public VtkIO: if (cell_type != VTK_CELL_TYPES::VTK_TRIANGLE_STRIP) { - this->faces_nb_edges_.push_back(static_cast(nb_vert)); + this->faces_nb_edges_.push_back(uint32(nb_vert)); for (std::size_t i = 0ul ; i < nb_vert;++i) { this->faces_vertex_indices_.push_back(*cells_it++); @@ -749,8 +749,8 @@ class VtkVolumeImport : public VtkIO:: if (!Inherit_Vtk::parse_vtk_legacy_file(fp)) return false; - this->nb_vertices_ = static_cast(this->positions_.size()); - this->nb_volumes_ = static_cast(this->cell_types_.size()); + this->nb_vertices_ = uint32(this->positions_.size()); + this->nb_volumes_ = uint32(this->cell_types_.size()); const std::vector* cell_types_vec = this->cell_types_.get_vec(); const std::vector* cells_vec = this->cells_.get_vec(); @@ -794,8 +794,8 @@ class VtkVolumeImport : public VtkIO:: if (!Inherit_Vtk::parse_xml_vtu(filename)) return false; - this->nb_vertices_ = static_cast(this->positions_.size()); - this->nb_volumes_ = static_cast(this->cell_types_.size()); + this->nb_vertices_ = uint32(this->positions_.size()); + this->nb_volumes_ = uint32(this->cell_types_.size()); const std::vector* cell_types_vec = this->cell_types_.get_vec(); const std::vector* cells_vec = this->cells_.get_vec(); diff --git a/cgogn/multiresolution/cph/ihcmap2.h b/cgogn/multiresolution/cph/ihcmap2.h index 8a68618f..422006aa 100644 --- a/cgogn/multiresolution/cph/ihcmap2.h +++ b/cgogn/multiresolution/cph/ihcmap2.h @@ -58,7 +58,7 @@ class IHCMap2_T : public CMap2_T, public CPH2 { public: - static const int PRIM_SIZE = 1; + static const int32 PRIM_SIZE = 1; using MapTraits = MAP_TRAITS; using MapType = MAP_TYPE; diff --git a/cgogn/multiresolution/mrcmap/mr_base.h b/cgogn/multiresolution/mrcmap/mr_base.h index 967d1034..478a227a 100644 --- a/cgogn/multiresolution/mrcmap/mr_base.h +++ b/cgogn/multiresolution/mrcmap/mr_base.h @@ -114,7 +114,7 @@ class MRBase inline uint32 get_maximum_level() const { - return static_cast(maps_.size()); + return uint32(maps_.size()); } inline uint32 get_current_level() const diff --git a/cgogn/rendering/drawer.cpp b/cgogn/rendering/drawer.cpp index 388d5d8c..5ce0d2bd 100644 --- a/cgogn/rendering/drawer.cpp +++ b/cgogn/rendering/drawer.cpp @@ -156,7 +156,7 @@ void Drawer::begin(GLenum mode) void Drawer::end() { - current_begin_->back().nb = static_cast(data_pos_.size() - current_begin_->back().begin); + current_begin_->back().nb = uint32(data_pos_.size() - current_begin_->back().begin); } @@ -184,7 +184,7 @@ void Drawer::color3f(float r, float g, float b) void Drawer::end_list() { - uint32 nb_elts = static_cast(data_pos_.size()); + uint32 nb_elts = uint32(data_pos_.size()); if (nb_elts == 0) return; diff --git a/cgogn/rendering/drawer.h b/cgogn/rendering/drawer.h index 26847748..50ddf2f3 100644 --- a/cgogn/rendering/drawer.h +++ b/cgogn/rendering/drawer.h @@ -50,7 +50,7 @@ class CGOGN_RENDERING_API Drawer float width; uint32 nb; bool aa; - PrimParam(std::size_t b, GLenum m, float w, bool a) : begin(static_cast(b)), mode(m), width(w), nb(0), aa(a){} + PrimParam(std::size_t b, GLenum m, float w, bool a) : begin(uint32(b)), mode(m), width(w), nb(0), aa(a){} }; using Vec3f = std::array; diff --git a/cgogn/rendering/examples/picking_viewer.cpp b/cgogn/rendering/examples/picking_viewer.cpp index ae66b6b4..d6690ba2 100644 --- a/cgogn/rendering/examples/picking_viewer.cpp +++ b/cgogn/rendering/examples/picking_viewer.cpp @@ -93,7 +93,7 @@ class Viewer : public QOGLViewer cgogn::rendering::Drawer* drawer_; - int cell_picking; + int32 cell_picking; }; diff --git a/cgogn/rendering/map_render.h b/cgogn/rendering/map_render.h index 93af8c39..383861ec 100644 --- a/cgogn/rendering/map_render.h +++ b/cgogn/rendering/map_render.h @@ -144,7 +144,7 @@ class MapRender indices_buffers_[prim]->create(); indices_buffers_uptodate_[prim] = true; - nb_indices_[prim] = static_cast(table_indices.size()); + nb_indices_[prim] = uint32(table_indices.size()); indices_buffers_[prim]->bind(); indices_buffers_[prim]->allocate(&(table_indices[0]), nb_indices_[prim] * sizeof(uint32)); indices_buffers_[prim]->release(); diff --git a/cgogn/rendering/shaders/shader_program.h b/cgogn/rendering/shaders/shader_program.h index b1dbb985..590d58df 100644 --- a/cgogn/rendering/shaders/shader_program.h +++ b/cgogn/rendering/shaders/shader_program.h @@ -87,7 +87,7 @@ class CGOGN_RENDERING_API ShaderProgram : protected QOpenGLFunctions_3_3_Core { vaos_.push_back(new QOpenGLVertexArrayObject); vaos_.back()->create(); - return static_cast(vaos_.size() - 1); + return uint32(vaos_.size() - 1); } /** diff --git a/cgogn/rendering/shaders/vbo.h b/cgogn/rendering/shaders/vbo.h index 29a3f5fb..c88bbdda 100644 --- a/cgogn/rendering/shaders/vbo.h +++ b/cgogn/rendering/shaders/vbo.h @@ -342,7 +342,7 @@ void generate_vbo(const ATTR& attr, const std::vector& indices, VBO& vbo vec_dim = 4; // allocate vbo - vbo.allocate(static_cast(indices.size()), vec_dim); + vbo.allocate(uint32(indices.size()), vec_dim); // copy (after conversion) using OutputConvert = typename function_traits::result_type; diff --git a/thirdparty/OffBinConverter/off_ascii2bin.cpp b/thirdparty/OffBinConverter/off_ascii2bin.cpp index 0539d047..ea5db530 100644 --- a/thirdparty/OffBinConverter/off_ascii2bin.cpp +++ b/thirdparty/OffBinConverter/off_ascii2bin.cpp @@ -5,6 +5,8 @@ #include #include +#include +using namespace cgogn::numerics; int main(int argc, char **argv) { @@ -18,9 +20,9 @@ int main(int argc, char **argv) std::ofstream ofs(argv[2],std::ios::out|std::ofstream::binary); std::string str; - unsigned int nv; - unsigned int np; - unsigned int ne; + uint32 nv; + uint32 np; + uint32 ne; ifs >> str; @@ -34,9 +36,9 @@ int main(int argc, char **argv) ifs >> np; ifs >> ne; - unsigned int nv_be = cgogn::swap_endianness_native_big(nv); - unsigned int np_be = cgogn::swap_endianness_native_big(np); - unsigned int ne_be = cgogn::swap_endianness_native_big(ne); + uint32 nv_be = cgogn::swap_endianness_native_big(nv); + uint32 np_be = cgogn::swap_endianness_native_big(np); + uint32 ne_be = cgogn::swap_endianness_native_big(ne); ofs << "OFF BINARY"<< std::endl; @@ -46,13 +48,13 @@ int main(int argc, char **argv) float* vertices = new float[3*nv]; - for (unsigned int i=0; i> vertices[3*i] >> vertices[3*i+1] >> vertices[3*i+2]; } - unsigned int* ptr = reinterpret_cast(vertices); - for (unsigned int i=0; i<3*nv;++i) + uint32* ptr = reinterpret_cast(vertices); + for (uint32 i=0; i<3*nv;++i) { *ptr = cgogn::swap_endianness_native_big(*ptr); ptr++; @@ -63,24 +65,24 @@ int main(int argc, char **argv) delete[] vertices; - std::vector prim; + std::vector prim; prim.reserve(8*1024*1024); - for (unsigned int i=0; i> nb; prim.push_back(nb); - for (unsigned int j=0; j> ind; prim.push_back(ind); } } - ptr = reinterpret_cast(&(prim[0])); - for (unsigned int i=0; i(&(prim[0])); + for (uint32 i=0; i Date: Tue, 22 Mar 2016 11:56:09 +0100 Subject: [PATCH 379/402] small fix in vtk xml import. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/vtk_io.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cgogn/io/vtk_io.h b/cgogn/io/vtk_io.h index 47800c1f..32fef8da 100644 --- a/cgogn/io/vtk_io.h +++ b/cgogn/io/vtk_io.h @@ -335,7 +335,7 @@ protected : XMLElement* root_node = doc.RootElement(); cgogn_assert(root_node != nullptr); - const bool little_endian = (to_lower(std::string(root_node->Attribute("byte_order"))) == "littleendian"); + const bool little_endian = (!root_node->Attribute("byte_order")) ||(to_lower(std::string(root_node->Attribute("byte_order"))) == "littleendian"); std::string header_type("unsigned int"); if (root_node->Attribute("header_type")) @@ -383,7 +383,7 @@ protected : std::string data_name("cgogn_unnamed_vertex_data"); if (vertex_data->Attribute("Name")) data_name = to_lower(std::string(vertex_data->Attribute("Name"))); - const bool binary = (to_lower(std::string(vertex_data->Attribute("format", nullptr))) == "binary"); + const bool binary = vertex_data->Attribute("format", nullptr) && (to_lower(std::string(vertex_data->Attribute("format", nullptr))) == "binary"); unsigned int nb_comp = 1; vertex_data->QueryUnsignedAttribute("NumberOfComponents", &nb_comp); const std::string type = vtk_data_type_to_cgogn_name_of_type(std::string(vertex_data->Attribute("type", nullptr))); @@ -450,7 +450,7 @@ protected : for (XMLElement* cell_data : cell_nodes) { const std::string& data_name = to_lower(std::string(cell_data->Attribute("Name"))); - const bool binary = (to_lower(std::string(cell_data->Attribute("format", nullptr))) == "binary"); + const bool binary = cell_data->Attribute("format", nullptr) && (to_lower(std::string(cell_data->Attribute("format", nullptr))) == "binary"); unsigned int nb_comp = 1; cell_data->QueryUnsignedAttribute("NumberOfComponents", &nb_comp); std::string type = vtk_data_type_to_cgogn_name_of_type(std::string(cell_data->Attribute("type", nullptr))); From 5764f9e865a25b8ad8b471766713a8d3f15fc3a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 22 Mar 2016 12:20:42 +0100 Subject: [PATCH 380/402] removed useless assertion. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/mesh_generation/examples/map3_from_image.h | 1 - 1 file changed, 1 deletion(-) diff --git a/cgogn/io/mesh_generation/examples/map3_from_image.h b/cgogn/io/mesh_generation/examples/map3_from_image.h index 692d23c1..88abf32b 100644 --- a/cgogn/io/mesh_generation/examples/map3_from_image.h +++ b/cgogn/io/mesh_generation/examples/map3_from_image.h @@ -26,7 +26,6 @@ inline void create_map3_from_image(CMap3& map3, const std::string& i using Criteria = VolumeMeshFromImageCGALTraits::Criteria; using C3T3 = VolumeMeshFromImageCGALTraits::C3T3; - cgogn_assert(get_extension(image_path) == "inr"); Image inrimage; inrimage.read(image_path.c_str()); From 017d497d448cdb1d801efebd9b35593de9e0a3cc Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Tue, 22 Mar 2016 14:30:17 +0100 Subject: [PATCH 381/402] foreach_dart does not use masks --- cgogn/core/cmap/cmap2_builder.h | 11 +- cgogn/core/cmap/cmap3_builder.h | 10 +- cgogn/core/cmap/map_base.h | 151 ++++++++------------------- cgogn/core/examples/map/map.cpp | 2 +- cgogn/core/tests/cmap/cmap2_test.cpp | 4 +- cgogn/io/examples/cmap2_import.cpp | 5 +- 6 files changed, 59 insertions(+), 124 deletions(-) diff --git a/cgogn/core/cmap/cmap2_builder.h b/cgogn/core/cmap/cmap2_builder.h index 8ee807ca..cc27743a 100644 --- a/cgogn/core/cmap/cmap2_builder.h +++ b/cgogn/core/cmap/cmap2_builder.h @@ -195,12 +195,11 @@ class CMap2Builder_T inline void close_map() { std::vector* fix_point_darts = get_dart_buffers()->get_buffer(); - map_.foreach_dart_nomask( [&] (Dart d) - { - if (map_.phi2(d) == d) - fix_point_darts->push_back(d); - }); - + map_.foreach_dart([&] (Dart d) + { + if (map_.phi2(d) == d) + fix_point_darts->push_back(d); + }); for (Dart d : (*fix_point_darts)) { if (map_.phi2(d) == d) diff --git a/cgogn/core/cmap/cmap3_builder.h b/cgogn/core/cmap/cmap3_builder.h index 7ca06396..a5e800a4 100644 --- a/cgogn/core/cmap/cmap3_builder.h +++ b/cgogn/core/cmap/cmap3_builder.h @@ -195,11 +195,11 @@ class CMap3Builder_T { // Search the map for topological holes (fix points of phi3) std::vector* fix_point_darts = get_dart_buffers()->get_buffer(); - map_.foreach_dart_nomask( [&] (Dart d) - { - if (map_.phi3(d) == d) - fix_point_darts->push_back(d); - }); + map_.foreach_dart( [&] (Dart d) + { + if (map_.phi3(d) == d) + fix_point_darts->push_back(d); + }); for (Dart d : (*fix_point_darts)) { if (map_.phi3(d) == d) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 0b5216e7..e9856abc 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -48,8 +48,6 @@ enum TraversalStrategy FORCE_TOPO_CACHE }; -auto nomask = [] (Dart) { return true; }; - template class MapBase : public MapBaseData { @@ -340,7 +338,7 @@ class MapBase : public MapBaseData this->embeddings_[ORBIT] = ca; // initialize all darts indices to EMBNULL for this ORBIT - foreach_dart_nomask([ca] (Dart d) { (*ca)[d.index] = EMBNULL; }); + foreach_dart([ca] (Dart d) { (*ca)[d.index] = EMBNULL; }); // initialize the indices of the existing orbits foreach_cell_nomask([this] (Cell c) { this->new_orbit_embedding(c); }); @@ -410,38 +408,36 @@ class MapBase : public MapBaseData counter[i] = 0; // Check that the indexation of cells is correct - foreach_cell_until_nomask( - [&] (CellType c) + foreach_cell_until_nomask([&] (CellType c) + { + unsigned int idx = this->get_embedding(c); + // check used indices are valid + if (idx == EMBNULL) { - unsigned int idx = this->get_embedding(c); - // check used indices are valid - if (idx == EMBNULL) - { - result = false; - std::cerr << "EMBNULL found in orbit " << orbit_name(ORBIT) << std::endl; - return result; - } - // ensure that two cells do not share the same index - if (counter[idx] > 0) - { - result = false; - std::cerr << "Two cells with same index in orbit " << orbit_name(ORBIT) << std::endl; - return result; - } - counter[idx] = 1; - // check all darts of the cell use the same index (distinct to EMBNULL) - cmap->foreach_dart_of_orbit_until(c, [&] (Dart d) - { - if (this->get_embedding(CellType(d)) != idx) - result = false; - if (!result) - std::cerr << "Different indices in orbit " << orbit_name(ORBIT) << std::endl; - return result; - }); - + result = false; + std::cerr << "EMBNULL found in orbit " << orbit_name(ORBIT) << std::endl; + return result; + } + // ensure that two cells do not share the same index + if (counter[idx] > 0) + { + result = false; + std::cerr << "Two cells with same index in orbit " << orbit_name(ORBIT) << std::endl; return result; } - ); + counter[idx] = 1; + // check all darts of the cell use the same index (distinct to EMBNULL) + cmap->foreach_dart_of_orbit_until(c, [&] (Dart d) + { + if (this->get_embedding(CellType(d)) != idx) + result = false; + if (!result) + std::cerr << "Different indices in orbit " << orbit_name(ORBIT) << std::endl; + return result; + }); + + return result; + }); // check that all cells present in the attribute handler are used if (result) { @@ -513,9 +509,10 @@ class MapBase : public MapBaseData static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); cgogn_message_assert(is_topo_cache_enabled(), "Trying to update a disabled global topo cache"); - foreach_cell_nomask( - [this] (Cell c) { (*this->global_topo_cache_[ORBIT])[this->get_embedding(c)] = c.dart; } - ); + foreach_cell_nomask([this] (Cell c) + { + (*this->global_topo_cache_[ORBIT])[this->get_embedding(c)] = c.dart; + }); } template @@ -634,7 +631,7 @@ class MapBase : public MapBaseData /*! * \Brief Methods to iterate over darts with a MASK that filters the traversed darts. - * A MASK is a callable that determine if a dart should be traversed or skipped. + * A MASK is a callable that determines if a dart should be traversed or skipped. * It returns false when a dart should be skipped, true in other cases. */ template @@ -665,15 +662,14 @@ class MapBase : public MapBaseData } /*! - * \Brief Specialized methods for the nomask lambda to iterate over all darts. - * All darts are traversed without any MASK filtering. + * All darts are traversed without any filtering. */ - inline Dart begin(const decltype(nomask)&) const + inline Dart begin() const { return Dart(this->topology_.begin()); } - inline void next(Dart& d, const decltype(nomask)&) const + inline void next(Dart& d) const { this->topology_.next(d.index); } @@ -687,58 +683,18 @@ class MapBase : public MapBaseData */ template inline void foreach_dart(const FUNC& f) const - { - foreach_dart(f, [this] (Dart d) { return !this->is_boundary(d); }); - } - - template - inline void foreach_boundary_dart(const FUNC& f) const - { - foreach_dart(f, [this] (Dart d) { return this->is_boundary(d); }); - } - - template - inline void foreach_dart_nomask(const FUNC& f) const - { - foreach_dart(f, nomask); - } - - template - inline void foreach_dart(const FUNC& f, const MASK& mask) const { static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); - static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); - static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); - for (Dart it = begin(mask), last = end(); it.index < last.index; next(it, mask)) + for (Dart it = begin(), last = end(); it.index < last.index; next(it)) f(it); } template inline void parallel_foreach_dart(const FUNC& f) const - { - parallel_foreach_dart(f, [this] (Dart d) { return !this->is_boundary(d); }); - } - - template - inline void parallel_foreach_boundary_dart(const FUNC& f) const - { - parallel_foreach_dart(f, [this] (Dart d) { return this->is_boundary(d); }); - } - - template - inline void parallel_foreach_dart_nomask(const FUNC& f) const - { - parallel_foreach_dart(f, nomask); - } - - template - inline void parallel_foreach_dart(const FUNC& f, const MASK& mask) const { static_assert(check_func_ith_parameter_type(FUNC, 0, Dart), "Wrong function first parameter type"); static_assert(check_func_ith_parameter_type(FUNC, 1, unsigned int), "Wrong function second parameter type"); - static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); - static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); using Future = std::future::type>; using VecDarts = std::vector; @@ -755,7 +711,7 @@ class MapBase : public MapBaseData Buffers* dbuffs = cgogn::get_dart_buffers(); - Dart it = begin(mask); + Dart it = begin(); Dart last = end(); while (it.index < last.index) @@ -771,7 +727,7 @@ class MapBase : public MapBaseData for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it.index < last.index; ++k) { darts.push_back(it); - next(it, mask); + next(it); } futures[i].push_back(thread_pool->enqueue([&darts, &f] (unsigned int th_id) @@ -808,33 +764,14 @@ class MapBase : public MapBaseData * @tparam FUNC type of the callable * @param f a callable */ - template - inline void foreach_dart_until(const FUNC& f) const - { - foreach_dart_until(f, [this] (Dart d) { return !this->is_boundary(d); }); - } - - template - inline void foreach_boundary_dart_until(const FUNC& f) const - { - foreach_dart_until(f, [this] (Dart d) { return this->is_boundary(d); }); - } template - inline void foreach_dart_until_nomask(const FUNC& f) const - { - foreach_dart_until(f, nomask); - } - - template - inline void foreach_dart_until(const FUNC& f, const MASK& mask) const + inline void foreach_dart_until(const FUNC& f) const { static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); - static_assert(check_func_parameter_type(MASK, Dart), "Wrong mask parameter type"); - static_assert(check_func_return_type(MASK, bool), "Wrong mask return type"); - for (Dart it = begin(mask), last = end(); it.index < last.index; next(it, mask)) + for (Dart it = begin(), last = end(); it.index < last.index; next(it)) { if (!f(it)) break; @@ -864,7 +801,7 @@ class MapBase : public MapBaseData template inline void foreach_cell_nomask(const FUNC& f) const { - foreach_cell(f, nomask); + foreach_cell(f, [] (Dart) { return true; }); } template @@ -913,7 +850,7 @@ class MapBase : public MapBaseData template inline void parallel_foreach_cell_nomask(const FUNC& f) const { - parallel_foreach_cell(f, nomask); + parallel_foreach_cell(f, [] (Dart) { return true; }); } template @@ -968,7 +905,7 @@ class MapBase : public MapBaseData template inline void foreach_cell_until_nomask(const FUNC& f) const { - foreach_cell_until(f, nomask); + foreach_cell_until(f, [] (Dart) { return true; }); } template diff --git a/cgogn/core/examples/map/map.cpp b/cgogn/core/examples/map/map.cpp index f619b757..8490326e 100644 --- a/cgogn/core/examples/map/map.cpp +++ b/cgogn/core/examples/map/map.cpp @@ -95,7 +95,7 @@ int test1(MAP& map) dm.mark(d1); std::cout << "Darts :" << std::endl; - map.foreach_dart_nomask([] (Dart d) { std::cout << d << std::endl; }); + map.foreach_dart([] (Dart d) { std::cout << d << std::endl; }); std::cout << "End Darts" << std::endl; std::cout << "Vertices :" << std::endl; diff --git a/cgogn/core/tests/cmap/cmap2_test.cpp b/cgogn/core/tests/cmap/cmap2_test.cpp index c8fe298c..751b2c64 100644 --- a/cgogn/core/tests/cmap/cmap2_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_test.cpp @@ -133,12 +133,12 @@ class CMap2Test : public ::testing::Test } } // Close the map (remove remaining boundary) - cmap_.foreach_dart_nomask([&] (Dart d) + cmap_.foreach_dart([&] (Dart d) { if (cmap_.phi2(d) == d) mbuild.close_hole_topo(d); }); // Embed the map - cmap_.foreach_dart_nomask([&] (Dart d) + cmap_.foreach_dart([&] (Dart d) { mbuild.new_orbit_embedding(CDart(d)); }); diff --git a/cgogn/io/examples/cmap2_import.cpp b/cgogn/io/examples/cmap2_import.cpp index 3723dd9f..fa969374 100644 --- a/cgogn/io/examples/cmap2_import.cpp +++ b/cgogn/io/examples/cmap2_import.cpp @@ -43,14 +43,14 @@ int main(int argc, char** argv) cgogn::io::import_surface(map, surfaceMesh); unsigned int nb_darts = 0; - map.foreach_dart_nomask([&nb_darts] (cgogn::Dart) { nb_darts++; }); + map.foreach_dart([&nb_darts] (cgogn::Dart) { nb_darts++; }); std::cout << "nb darts -> " << nb_darts << std::endl; unsigned int nb_darts_2 = 0; std::vector nb_darts_per_thread(cgogn::NB_THREADS - 1); for (unsigned int& n : nb_darts_per_thread) n = 0; - map.parallel_foreach_dart_nomask([&nb_darts_per_thread] (cgogn::Dart, unsigned int thread_index) + map.parallel_foreach_dart([&nb_darts_per_thread] (cgogn::Dart, unsigned int thread_index) { nb_darts_per_thread[thread_index]++; }); @@ -58,7 +58,6 @@ int main(int argc, char** argv) nb_darts_2 += n; std::cout << "nb darts // -> " << nb_darts_2 << std::endl; - VertexAttributeHandler vertex_position = map.get_attribute("position"); VertexAttributeHandler vertex_normal = map.add_attribute("normal"); FaceAttributeHandler face_normal = map.add_attribute("normal"); From e1c529d2e539cec3ca7e1bd945d6d0182472c398 Mon Sep 17 00:00:00 2001 From: thery Date: Tue, 22 Mar 2016 15:20:52 +0100 Subject: [PATCH 382/402] windows compilation --- cgogn/core/cmap/cmap0.h | 1 + cgogn/core/cmap/cmap1.h | 4 +++- cgogn/core/cmap/cmap2.h | 4 ++-- cgogn/core/cmap/cmap3.h | 2 +- cgogn/core/cmap/map_base.h | 19 ++++++++++--------- cgogn/core/container/chunk_array.h | 5 ++--- cgogn/core/tests/utils/name_types_test.cpp | 9 +++++++++ cgogn/io/mesh_generation/tetgen_io.h | 2 +- cgogn/rendering/examples/drawing.cpp | 2 +- thirdparty/tetgen/CMakeLists.txt | 9 ++++++++- 10 files changed, 38 insertions(+), 19 deletions(-) diff --git a/cgogn/core/cmap/cmap0.h b/cgogn/core/cmap/cmap0.h index 7da1e744..3d54155d 100644 --- a/cgogn/core/cmap/cmap0.h +++ b/cgogn/core/cmap/cmap0.h @@ -46,6 +46,7 @@ class CMap0_T : public MapBase friend class cgogn::DartMarkerStore; using Vertex = Cell; + using Boundary = Vertex; // just for compilation template using ChunkArray = typename Inherit::template ChunkArray; diff --git a/cgogn/core/cmap/cmap1.h b/cgogn/core/cmap/cmap1.h index 4c179504..b6af82bd 100644 --- a/cgogn/core/cmap/cmap1.h +++ b/cgogn/core/cmap/cmap1.h @@ -48,6 +48,8 @@ class CMap1_T : public CMap0_T using Vertex = typename Inherit::Vertex; using Face = Cell; + using Boundary = Vertex; + template using ChunkArray = typename Inherit::template ChunkArray; template @@ -351,7 +353,7 @@ class CMap1_T : public CMap0_T public: - inline uint32 degree(Vertex v) const + inline uint32 degree(Vertex ) const { return 2; } diff --git a/cgogn/core/cmap/cmap2.h b/cgogn/core/cmap/cmap2.h index 1d8cc79d..4469f974 100644 --- a/cgogn/core/cmap/cmap2.h +++ b/cgogn/core/cmap/cmap2.h @@ -466,7 +466,7 @@ class CMap2_T : public CMap1_T return this->nb_darts_of_orbit(v); } - inline uint32 codegree(Edge e) const + inline uint32 codegree(Edge) const { return 2; } @@ -484,7 +484,7 @@ class CMap2_T : public CMap1_T return Inherit::codegree(f); } - inline uint32 degree(Face f) const + inline uint32 degree(Face) const { return 1; } diff --git a/cgogn/core/cmap/cmap3.h b/cgogn/core/cmap/cmap3.h index 7d360287..92e8e1d7 100644 --- a/cgogn/core/cmap/cmap3.h +++ b/cgogn/core/cmap/cmap3.h @@ -345,7 +345,7 @@ class CMap3_T : public CMap2_T return Inherit::degree(e); } - inline uint32 codegree(Edge e) const + inline uint32 codegree(Edge) const { return 2; } diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index db521a56..d8358723 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -48,7 +48,8 @@ enum TraversalStrategy FORCE_TOPO_CACHE }; -auto nomask = [] (Dart) { return true; }; +//auto nomask = [] (Dart) { return true; }; +#define MASK_NOMASK [] (Dart) { return true; } template class MapBase : public MapBaseData @@ -669,12 +670,12 @@ class MapBase : public MapBaseData * \Brief Specialized methods for the nomask lambda to iterate over all darts. * All darts are traversed without any MASK filtering. */ - inline Dart begin(const decltype(nomask)&) const + inline Dart begin() const { return Dart(this->topology_.begin()); } - inline void next(Dart& d, const decltype(nomask)&) const + inline void next(Dart& d) const { this->topology_.next(d.index); } @@ -701,7 +702,7 @@ class MapBase : public MapBaseData template inline void foreach_dart_nomask(const FUNC& f) const { - foreach_dart(f, nomask); + foreach_dart(f, MASK_NOMASK); } template @@ -730,7 +731,7 @@ class MapBase : public MapBaseData template inline void parallel_foreach_dart_nomask(const FUNC& f) const { - parallel_foreach_dart(f, nomask); + parallel_foreach_dart(f, MASK_NOMASK); } template @@ -824,7 +825,7 @@ class MapBase : public MapBaseData template inline void foreach_dart_until_nomask(const FUNC& f) const { - foreach_dart_until(f, nomask); + foreach_dart_until(f, MASK_NOMASK); } template @@ -865,7 +866,7 @@ class MapBase : public MapBaseData template inline void foreach_cell_nomask(const FUNC& f) const { - foreach_cell(f, nomask); + foreach_cell(f, MASK_NOMASK); } template @@ -914,7 +915,7 @@ class MapBase : public MapBaseData template inline void parallel_foreach_cell_nomask(const FUNC& f) const { - parallel_foreach_cell(f, nomask); + parallel_foreach_cell(f, MASK_NOMASK); } template @@ -969,7 +970,7 @@ class MapBase : public MapBaseData template inline void foreach_cell_until_nomask(const FUNC& f) const { - foreach_cell_until(f, nomask); + foreach_cell_until(f, MASK_NOMASK); } template diff --git a/cgogn/core/container/chunk_array.h b/cgogn/core/container/chunk_array.h index 4c23ce86..e4f3cc8d 100644 --- a/cgogn/core/container/chunk_array.h +++ b/cgogn/core/container/chunk_array.h @@ -693,9 +693,8 @@ class ChunkArray : public ChunkArrayGen for (uint32 * const ptr : table_data_) { //#pragma omp for -// for (int32 j = 0; j < int32(CHUNKSIZE/32); ++j) -// ptr[j] = 0u; - std::fill_n(ptr,CHUNKSIZE/32,0u); + for (int32 j = 0; j < int32(CHUNKSIZE/32); ++j) + ptr[j] = 0u; } } diff --git a/cgogn/core/tests/utils/name_types_test.cpp b/cgogn/core/tests/utils/name_types_test.cpp index 79900c8f..c03f9d56 100644 --- a/cgogn/core/tests/utils/name_types_test.cpp +++ b/cgogn/core/tests/utils/name_types_test.cpp @@ -51,8 +51,17 @@ TEST(NameTypesTest, NumTypes) EXPECT_EQ(cgogn::name_of_type(int32()), "int"); EXPECT_EQ(cgogn::name_of_type(uint32()), "unsigned int"); + +// TODO A TIRER AU CLAIR !! +#ifdef _MSC_VER + EXPECT_EQ(cgogn::name_of_type(int64()), "long long"); + EXPECT_EQ(cgogn::name_of_type(uint64()), "unsigned long long"); +#else EXPECT_EQ(cgogn::name_of_type(int64()), "long"); EXPECT_EQ(cgogn::name_of_type(uint64()), "unsigned long"); +#endif + + EXPECT_EQ(cgogn::name_of_type(llint()), "long long"); EXPECT_EQ(cgogn::name_of_type(ullint()), "unsigned long long"); diff --git a/cgogn/io/mesh_generation/tetgen_io.h b/cgogn/io/mesh_generation/tetgen_io.h index 2a59e879..a3abd272 100644 --- a/cgogn/io/mesh_generation/tetgen_io.h +++ b/cgogn/io/mesh_generation/tetgen_io.h @@ -375,7 +375,7 @@ std::unique_ptr export_tetgen(CMap2& map, const typename C //for each facet i = 0u; - map.template foreach_cell([&output,&i,&map](Face face) + map.foreach_cell([&output,&i,&map](Face face) { tetgenio::facet* f = &(output->facetlist[i]); tetgenio::init(f); diff --git a/cgogn/rendering/examples/drawing.cpp b/cgogn/rendering/examples/drawing.cpp index 5a093e23..a77d5178 100644 --- a/cgogn/rendering/examples/drawing.cpp +++ b/cgogn/rendering/examples/drawing.cpp @@ -157,7 +157,7 @@ void Drawing::init() } drawer2_->end(); - drawer2_->ball_size(0.03); + drawer2_->ball_size(0.03f); drawer2_->begin(GL_POINTS); drawer2_->color3f(1.0,1.0,1.0); for (float z=-1.0f; z < 1.0f; z+= 0.2f) diff --git a/thirdparty/tetgen/CMakeLists.txt b/thirdparty/tetgen/CMakeLists.txt index b8d7a952..ac23f548 100644 --- a/thirdparty/tetgen/CMakeLists.txt +++ b/thirdparty/tetgen/CMakeLists.txt @@ -2,12 +2,19 @@ set(CGOGN_THIRDPARTY_TETGEN_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE PATH # Set the minimum required version of cmake for a project. cmake_minimum_required(VERSION 3.0) +if(MSVC) + add_definitions("-D_CRT_SECURE_NO_WARNINGS /W0") + add_library(tet STATIC tetgen.h tetgen.cxx predicates.cxx) +else(MSVC) + add_library(tet SHARED tetgen.h tetgen.cxx predicates.cxx) +endif(MSVC) + # Add an executable to the project using the specified source files. # add_executable(tetgen tetgen.cxx predicates.cxx) #Add a library to the project using the specified source files. # In Linux/Unix, it will creates the libtet.a -add_library(tet SHARED tetgen.cxx predicates.cxx) + #Set properties on a target. #We use this here to set -DTETLIBRARY for when compiling the From d8e1664fdb3b0fdbcbd3e9a2211699b47d541a9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 22 Mar 2016 15:28:16 +0100 Subject: [PATCH 383/402] just check if the orbit is well embedded at the end of create_embedding() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/map_base.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 0b5216e7..a9885317 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -345,7 +345,7 @@ class MapBase : public MapBaseData // initialize the indices of the existing orbits foreach_cell_nomask([this] (Cell c) { this->new_orbit_embedding(c); }); - cgogn_assert(check_map_integrity()); + cgogn_assert(this->template is_well_embedded>()); } template From 9579ae07a36451569c40774947942670f5dbbcf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 22 Mar 2016 15:28:54 +0100 Subject: [PATCH 384/402] no more container browsers. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- .../core/container/chunk_array_container.cpp | 3 - cgogn/core/container/chunk_array_container.h | 157 +++--------------- cgogn/multiresolution/cph/ihcmap2.h | 37 +---- cgogn/multiresolution/cph/ihcmap3.h | 28 +--- 4 files changed, 25 insertions(+), 200 deletions(-) diff --git a/cgogn/core/container/chunk_array_container.cpp b/cgogn/core/container/chunk_array_container.cpp index d06b7afe..3310a543 100644 --- a/cgogn/core/container/chunk_array_container.cpp +++ b/cgogn/core/container/chunk_array_container.cpp @@ -29,9 +29,6 @@ namespace cgogn { -ContainerBrowser::~ContainerBrowser() -{} - template class CGOGN_CORE_API ChunkArrayContainer; template class CGOGN_CORE_API ChunkArrayContainer; diff --git a/cgogn/core/container/chunk_array_container.h b/cgogn/core/container/chunk_array_container.h index 3136d117..54e7d913 100644 --- a/cgogn/core/container/chunk_array_container.h +++ b/cgogn/core/container/chunk_array_container.h @@ -43,37 +43,6 @@ namespace cgogn { -class CGOGN_CORE_API ContainerBrowser -{ -public: - - virtual unsigned int begin() const = 0; - virtual unsigned int end() const = 0; - virtual void next(unsigned int &it) const = 0; - virtual void next_primitive(unsigned int &it, unsigned int primSz) const = 0; - virtual void enable() = 0; - virtual void disable() = 0; - virtual ~ContainerBrowser(); -}; - -template -class ContainerStandardBrowser : public ContainerBrowser -{ - const CONTAINER* cac_; - -public: - - ContainerStandardBrowser(const CONTAINER* cac) : cac_(cac) {} - virtual unsigned int begin() const { return cac_->real_begin(); } - virtual unsigned int end() const { return cac_->real_end(); } - virtual void next(unsigned int &it) const { cac_->real_next(it); } - virtual void next_primitive(unsigned int &it, unsigned int primSz) const { cac_->real_next_primitive(it,primSz); } - virtual void enable() {} - virtual void disable() {} - virtual ~ContainerStandardBrowser() {} -}; - - /** * @brief class that manage the storage of several ChunkArray * @tparam CHUNKSIZE chunk size for ChunkArray @@ -133,16 +102,6 @@ class ChunkArrayContainer */ unsigned int nb_max_lines_; - /** - * Browser that allow special traversals - */ - ContainerBrowser* current_browser_; - - /** - * Browser that allow special traversals - */ - ContainerStandardBrowser* std_browser_; - /** * @brief get array index from name * @warning do not store index (not stable) @@ -206,10 +165,7 @@ class ChunkArrayContainer ChunkArrayContainer(): nb_used_lines_(0u), nb_max_lines_(0u) - { - std_browser_ = new ContainerStandardBrowser(this); - current_browser_= std_browser_; - } + {} ChunkArrayContainer(Self const& ) = delete; ChunkArrayContainer(Self&& ) = delete; @@ -221,10 +177,6 @@ class ChunkArrayContainer */ ~ChunkArrayContainer() { - if (current_browser_ != std_browser_) - delete current_browser_; - delete std_browser_; - for (auto ptr : table_arrays_) delete ptr; @@ -419,65 +371,12 @@ class ChunkArrayContainer return refs_.capacity(); } - /** - * @brief set the current container browser - * @param browser, pointer to a heap-allocated ContainerBrowser - */ - inline void set_current_browser(ContainerBrowser* browser) - { - if (current_browser_ != std_browser_) - delete current_browser_; - current_browser_ = browser; - } - - inline void set_standard_browser() - { - if (current_browser_ != std_browser_) - delete current_browser_; - current_browser_ = std_browser_; - } /** - * @brief begin + * @brief begin of container * @return the index of the first used line of the container */ inline unsigned int begin() const - { - return current_browser_->begin(); - } - - /** - * @brief end - * @return the index after the last used line of the container - */ - inline unsigned int end() const - { - return current_browser_->end(); - } - - /** - * @brief next it <- next used index in the container - * @param it index to "increment" - */ - inline void next(unsigned int& it) const - { - current_browser_->next(it); - } - - /** - * @brief next primitive: it <- next primitive used index in the container (eq to PRIMSIZE next) - * @param it index to "increment" - */ - inline void next_primitive(unsigned int& it, unsigned int prim_size) const - { - current_browser_->next_primitive(it, prim_size); - } - - /** - * @brief begin of container without browser - * @return the real index of the first used line of the container - */ - inline unsigned int real_begin() const { unsigned int it = 0u; while ((it < nb_max_lines_) && (!used(it))) @@ -486,19 +385,19 @@ class ChunkArrayContainer } /** - * @brief end of container without browser - * @return the real index after the last used line of the container + * @brief end of container + * @return the index after the last used line of the container */ - inline unsigned int real_end() const + inline unsigned int end() const { return nb_max_lines_; } /** - * @brief next without browser + * @brief next * @param it */ - inline void real_next(unsigned int& it) const + inline void next(unsigned int& it) const { do { @@ -507,10 +406,10 @@ class ChunkArrayContainer } /** - * @brief next primitive without browser + * @brief next primitive * @param it */ - inline void real_next_primitive(unsigned int &it, unsigned int prim_size) const + inline void next_primitive(unsigned int &it, unsigned int prim_size) const { do { @@ -519,10 +418,10 @@ class ChunkArrayContainer } /** - * @brief reverse begin of container without browser - * @return the real index of the first used line of the container in reverse order + * @brief reverse begin of container + * @return the index of the first used line of the container in reverse order */ - unsigned int real_rbegin() const + inline unsigned int rbegin() const { unsigned int it = nb_max_lines_- 1u; while ((it != 0xffffffff) && (!used(it))) @@ -531,19 +430,19 @@ class ChunkArrayContainer } /** - * @brief reverse end of container without browser - * @return the real index before the last used line of the container in reverse order + * @brief reverse end of container + * @return the index before the last used line of the container in reverse order */ - unsigned int real_rend() const + unsigned int rend() const { - return 0xffffffff; // -1 + return 0xffffffff; } /** - * @brief reverse next without browser + * @brief reverse next * @param it */ - void real_rnext(unsigned int &it) const + void rnext(unsigned int &it) const { do { @@ -605,18 +504,6 @@ class ChunkArrayContainer holes_stack_.swap(container.holes_stack_); std::swap(nb_used_lines_, container.nb_used_lines_); std::swap(nb_max_lines_, container.nb_max_lines_); - - ContainerBrowser* browser = current_browser_; - - if (container.current_browser_ != container.std_browser_) - current_browser_ = container.current_browser_; - else - current_browser_ = std_browser_; - - if (browser != std_browser_) - container.current_browser_ = browser; - else - container.current_browser_ = container.std_browser_; } /** @@ -625,7 +512,7 @@ class ChunkArrayContainer */ float fragmentation() const { - return float(size()) / float(real_end()); + return float(size()) / float(end()); } /** @@ -636,9 +523,9 @@ class ChunkArrayContainer void compact(std::vector& map_old_new) { map_old_new.clear(); - map_old_new.resize(real_end(), 0xffffffff); + map_old_new.resize(end(), 0xffffffff); - unsigned int up = real_rbegin(); + unsigned int up = rbegin(); unsigned int down = 0u; while (down < up) @@ -650,7 +537,7 @@ class ChunkArrayContainer unsigned rdown = down + PRIMSIZE-1u - i; map_old_new[up] = rdown; copy_line(rdown, up); - real_rnext(up); + rnext(up); } down += PRIMSIZE; } diff --git a/cgogn/multiresolution/cph/ihcmap2.h b/cgogn/multiresolution/cph/ihcmap2.h index e9c7d000..9e8b692b 100644 --- a/cgogn/multiresolution/cph/ihcmap2.h +++ b/cgogn/multiresolution/cph/ihcmap2.h @@ -30,29 +30,6 @@ namespace cgogn { -template -class ContainerCPHBrowser : public ContainerBrowser -{ - const CONTAINER& cac_; - const MAP* map_; - -public: - ContainerCPHBrowser(const CONTAINER& cac, const MAP* map) : cac_(cac), map_(map) {} - virtual unsigned int begin() const { return cac_.real_begin(); } - virtual unsigned int end() const { return cac_.real_end(); } - virtual void next(unsigned int &it) const - { - cac_.real_next(it); - if(map_->get_dart_level(Dart(it)) > map_->get_current_level()) - it = cac_.real_end(); - } - virtual void next_primitive(unsigned int &it, unsigned int primSz) const { cac_.real_next_primitive(it,primSz); } - virtual void enable() {} - virtual void disable() {} - virtual ~ContainerCPHBrowser() {} - ContainerCPHBrowser& operator=(const ContainerCPHBrowser&) = delete; -}; - template class IHCMap2_T : public CMap2_T, public CPH2 { @@ -70,12 +47,6 @@ class IHCMap2_T : public CMap2_T, public CPH2 friend class DartMarker_T; friend class cgogn::DartMarkerStore; -// static const Orbit DART = Inherit_CMAP::DART; -// static const Orbit VERTEX = Inherit_CMAP::VERTEX; -// static const Orbit EDGE = Inherit_CMAP::EDGE; -// static const Orbit FACE = Inherit_CMAP::FACE; -// static const Orbit VOLUME = Inherit_CMAP::VOLUME; - using CDart = typename Inherit_CMAP::CDart; using Vertex = typename Inherit_CMAP::Vertex; using Edge = typename Inherit_CMAP::Edge; @@ -108,14 +79,10 @@ class IHCMap2_T : public CMap2_T, public CPH2 protected: - ContainerCPHBrowser, Self>* cph_browser; + inline void init() - { - cph_browser = new ContainerCPHBrowser, Self>( - this->topology_, this); - this->topology_.set_current_browser(cph_browser); - } + {} public: diff --git a/cgogn/multiresolution/cph/ihcmap3.h b/cgogn/multiresolution/cph/ihcmap3.h index 6c1c27c2..1d61fd52 100644 --- a/cgogn/multiresolution/cph/ihcmap3.h +++ b/cgogn/multiresolution/cph/ihcmap3.h @@ -79,37 +79,11 @@ class IHCMap3_T :public CMap3_T, public CPH3 ChunkArray* next_level_cell[NB_ORBITS]; - template - class ContainerCPHBrowser : public ContainerBrowser - { - const CONTAINER& cac_; - const MAP* map_; - - public: - ContainerCPHBrowser(const CONTAINER& cac, const MAP* map) : cac_(cac), map_(map) {} - virtual unsigned int begin() const { return cac_.real_begin(); } - virtual unsigned int end() const { return cac_.real_end(); } - virtual void next(unsigned int &it) const - { - cac_.real_next(it); - if(map_->get_dart_level(Dart(it)) > map_->get_current_level()) - it = cac_.real_end(); - } - virtual void next_primitive(unsigned int &it, unsigned int primSz) const { cac_.real_next_primitive(it,primSz); } - virtual void enable() {} - virtual void disable() {} - virtual ~ContainerCPHBrowser() {} - ContainerCPHBrowser& operator=(const ContainerCPHBrowser&) = delete; - }; protected: - ContainerCPHBrowser, Self>* cph_browser; inline void init() - { - cph_browser = new ContainerCPHBrowser, Self>(this->topology_, this); - this->topology_.set_current_browser(cph_browser); - } + {} public: IHCMap3_T() : Inherit_CMAP(), Inherit_CPH(this->topology_) From 8090633e480dbff7df05397e215f9142b3780c79 Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Tue, 22 Mar 2016 16:08:54 +0100 Subject: [PATCH 385/402] begin / next with mask ignore boundary darts (so do foreach_cell) --- cgogn/core/cmap/map_base.h | 91 +++-------------------- cgogn/core/tests/cmap/cmap2_test.cpp | 11 ++- cgogn/geometry/tests/algos/algos_test.cpp | 3 +- 3 files changed, 18 insertions(+), 87 deletions(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index e9856abc..216b121e 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -341,7 +341,7 @@ class MapBase : public MapBaseData foreach_dart([ca] (Dart d) { (*ca)[d.index] = EMBNULL; }); // initialize the indices of the existing orbits - foreach_cell_nomask([this] (Cell c) { this->new_orbit_embedding(c); }); + foreach_cell([this] (Cell c) { this->new_orbit_embedding(c); }); cgogn_assert(check_map_integrity()); } @@ -372,7 +372,7 @@ class MapBase : public MapBaseData AttributeHandler counter = add_attribute("__tmp_counter"); for (unsigned int& i : counter) i = 0; - foreach_cell_nomask([this, &counter] (Cell c) + foreach_cell([this, &counter] (Cell c) { if (counter[c] > 0) this->new_orbit_embedding(c); @@ -408,7 +408,7 @@ class MapBase : public MapBaseData counter[i] = 0; // Check that the indexation of cells is correct - foreach_cell_until_nomask([&] (CellType c) + foreach_cell_until([&] (CellType c) { unsigned int idx = this->get_embedding(c); // check used indices are valid @@ -509,7 +509,7 @@ class MapBase : public MapBaseData static_assert(ORBIT < NB_ORBITS, "Unknown orbit parameter"); cgogn_message_assert(is_topo_cache_enabled(), "Trying to update a disabled global topo cache"); - foreach_cell_nomask([this] (Cell c) + foreach_cell([this] (Cell c) { (*this->global_topo_cache_[ORBIT])[this->get_embedding(c)] = c.dart; }); @@ -568,28 +568,13 @@ class MapBase : public MapBaseData */ template unsigned int nb_cells() const - { - unsigned int result = 0; - foreach_cell([&result] (Cell) { ++result; }); - return result; - } - - unsigned int nb_boundary_cells() const - { - unsigned int result = 0; - foreach_boundary_cell([&result] (typename ConcreteMap::Boundary) { ++result; }); - return result; - } - - template - unsigned int nb_cells_nomask() const { if (this->template is_embedded()) return this->attributes_[ORBIT].size(); else { unsigned int result = 0; - foreach_cell_nomask([&result] (Cell) { ++result; }); + foreach_cell([&result] (Cell) { ++result; }); return result; } } @@ -640,7 +625,7 @@ class MapBase : public MapBaseData Dart d = Dart(this->topology_.begin()); Dart end = Dart(this->topology_.end()); - while (d != end && !mask(d)) + while (d != end && (is_boundary(d) || !mask(d))) this->topology_.next(d.index); return d; @@ -653,7 +638,7 @@ class MapBase : public MapBaseData do { this->topology_.next(d.index); - } while (d != end && !mask(d)); + } while (d != end && (is_boundary(d) || !mask(d))); } inline Dart end() const @@ -661,19 +646,6 @@ class MapBase : public MapBaseData return Dart(this->topology_.end()); } - /*! - * All darts are traversed without any filtering. - */ - inline Dart begin() const - { - return Dart(this->topology_.begin()); - } - - inline void next(Dart& d) const - { - this->topology_.next(d.index); - } - public: /** @@ -686,7 +658,7 @@ class MapBase : public MapBaseData { static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); - for (Dart it = begin(), last = end(); it.index < last.index; next(it)) + for (Dart it = Dart(this->topology_.begin()), last = Dart(this->topology_.end()); it.index < last.index; this->topology_.next(it.index)) f(it); } @@ -711,8 +683,8 @@ class MapBase : public MapBaseData Buffers* dbuffs = cgogn::get_dart_buffers(); - Dart it = begin(); - Dart last = end(); + Dart it = Dart(this->topology_.begin()); + Dart last = Dart(this->topology_.end()); while (it.index < last.index) { @@ -727,7 +699,7 @@ class MapBase : public MapBaseData for (unsigned k = 0u; k < PARALLEL_BUFFER_SIZE && it.index < last.index; ++k) { darts.push_back(it); - next(it); + this->topology_.next(it.index); } futures[i].push_back(thread_pool->enqueue([&darts, &f] (unsigned int th_id) @@ -771,7 +743,7 @@ class MapBase : public MapBaseData static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); - for (Dart it = begin(), last = end(); it.index < last.index; next(it)) + for (Dart it = Dart(this->topology_.begin()), last = Dart(this->topology_.end()); it.index < last.index; this->topology_.next(it.index)) { if (!f(it)) break; @@ -785,21 +757,6 @@ class MapBase : public MapBaseData */ template inline void foreach_cell(const FUNC& f) const - { - foreach_cell(f, [this] (Dart d) { return !this->is_boundary(d); }); - } - - template - inline void foreach_boundary_cell(const FUNC& f) const - { - using CellType = typename function_traits::template arg<0>::type; - static_assert(std::is_same::value, "Bad boundary orbit"); - - foreach_cell(f, [this] (Dart d) { return this->is_boundary(d); }); - } - - template - inline void foreach_cell_nomask(const FUNC& f) const { foreach_cell(f, [] (Dart) { return true; }); } @@ -837,18 +794,6 @@ class MapBase : public MapBaseData template inline void parallel_foreach_cell(const FUNC& f) const - { - parallel_foreach_cell(f, [this] (Dart d) { return !this->is_boundary(d); }); - } - - template - inline void parallel_foreach_boundary_cell(const FUNC& f) const - { - parallel_foreach_cell(f, [this] (Dart d) { return this->is_boundary(d); }); - } - - template - inline void parallel_foreach_cell_nomask(const FUNC& f) const { parallel_foreach_cell(f, [] (Dart) { return true; }); } @@ -892,18 +837,6 @@ class MapBase : public MapBaseData */ template inline void foreach_cell_until(const FUNC& f) const - { - foreach_cell_until(f, [this] (Dart d) { return !this->is_boundary(d); }); - } - - template - inline void foreach_boundary_cell_until(const FUNC& f) const - { - foreach_cell_until(f, [this] (Dart d) { return this->is_boundary(d); }); - } - - template - inline void foreach_cell_until_nomask(const FUNC& f) const { foreach_cell_until(f, [] (Dart) { return true; }); } diff --git a/cgogn/core/tests/cmap/cmap2_test.cpp b/cgogn/core/tests/cmap/cmap2_test.cpp index 751b2c64..c238cdf8 100644 --- a/cgogn/core/tests/cmap/cmap2_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_test.cpp @@ -142,19 +142,19 @@ class CMap2Test : public ::testing::Test { mbuild.new_orbit_embedding(CDart(d)); }); - cmap_.foreach_cell_nomask([&] (Vertex v) + cmap_.foreach_cell([&] (Vertex v) { mbuild.new_orbit_embedding(v); }); - cmap_.foreach_cell_nomask([&] (Edge e) + cmap_.foreach_cell([&] (Edge e) { mbuild.new_orbit_embedding(e); }); - cmap_.foreach_cell_nomask([&] (Face f) + cmap_.foreach_cell([&] (Face f) { mbuild.new_orbit_embedding(f); }); - cmap_.foreach_cell_nomask([&] (Volume w) + cmap_.foreach_cell([&] (Volume w) { mbuild.new_orbit_embedding(w); }); @@ -183,8 +183,7 @@ TEST_F(CMap2Test, add_face) EXPECT_EQ(cmap_.nb_cells(), count_vertices); EXPECT_EQ(cmap_.nb_cells(), count_vertices); EXPECT_EQ(cmap_.nb_cells(), NB_MAX); - EXPECT_EQ(cmap_.nb_cells_nomask(), 2 * NB_MAX); - EXPECT_EQ(cmap_.nb_boundary_cells(), NB_MAX); +// EXPECT_EQ(cmap_.nb_boundary_cells(), NB_MAX); EXPECT_EQ(cmap_.nb_cells(), NB_MAX); EXPECT_TRUE(cmap_.check_map_integrity()); } diff --git a/cgogn/geometry/tests/algos/algos_test.cpp b/cgogn/geometry/tests/algos/algos_test.cpp index 5d4f893c..f446d851 100644 --- a/cgogn/geometry/tests/algos/algos_test.cpp +++ b/cgogn/geometry/tests/algos/algos_test.cpp @@ -177,7 +177,6 @@ TYPED_TEST(Algos_TEST, EarTriangulation) cgogn::geometry::apply_ear_triangulation(this->map2_, f, vertex_position); EXPECT_TRUE(this->map2_.template nb_cells() == 3); - EXPECT_TRUE(this->map2_.template nb_cells_nomask() == 4); - EXPECT_TRUE(this->map2_.nb_boundary_cells() == 1); +// EXPECT_TRUE(this->map2_.nb_boundary_cells() == 1); EXPECT_TRUE(this->map2_.template nb_cells() == 7); } From 3bc338e6645c965cc8f999da622aa9034d826e7a Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Tue, 22 Mar 2016 16:17:51 +0100 Subject: [PATCH 386/402] minor simplifications --- cgogn/core/cmap/map_base.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 216b121e..8bef4da6 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -658,7 +658,7 @@ class MapBase : public MapBaseData { static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); - for (Dart it = Dart(this->topology_.begin()), last = Dart(this->topology_.end()); it.index < last.index; this->topology_.next(it.index)) + for (Dart it = Dart(this->topology_.begin()), last = Dart(this->topology_.end()); it != last; this->topology_.next(it.index)) f(it); } @@ -686,7 +686,7 @@ class MapBase : public MapBaseData Dart it = Dart(this->topology_.begin()); Dart last = Dart(this->topology_.end()); - while (it.index < last.index) + while (it != last) { for (unsigned int i = 0u; i < 2u; ++i) { @@ -743,7 +743,7 @@ class MapBase : public MapBaseData static_assert(check_func_parameter_type(FUNC, Dart), "Wrong function parameter type"); static_assert(check_func_return_type(FUNC, bool), "Wrong function return type"); - for (Dart it = Dart(this->topology_.begin()), last = Dart(this->topology_.end()); it.index < last.index; this->topology_.next(it.index)) + for (Dart it = Dart(this->topology_.begin()), last = Dart(this->topology_.end()); it != last; this->topology_.next(it.index)) { if (!f(it)) break; From fac8adce4d1b4ed6e23a9873ff457494200fcfb9 Mon Sep 17 00:00:00 2001 From: thery Date: Tue, 22 Mar 2016 16:48:38 +0100 Subject: [PATCH 387/402] fix long long pb on windows --- cgogn/core/tests/utils/name_types_test.cpp | 12 +++--------- cgogn/core/utils/name_types.h | 4 ++-- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/cgogn/core/tests/utils/name_types_test.cpp b/cgogn/core/tests/utils/name_types_test.cpp index c03f9d56..d2c5d0d7 100644 --- a/cgogn/core/tests/utils/name_types_test.cpp +++ b/cgogn/core/tests/utils/name_types_test.cpp @@ -25,6 +25,7 @@ #include #include + using namespace cgogn::numerics; TEST(NameTypesTest, NumTypes) @@ -52,18 +53,11 @@ TEST(NameTypesTest, NumTypes) EXPECT_EQ(cgogn::name_of_type(uint32()), "unsigned int"); -// TODO A TIRER AU CLAIR !! -#ifdef _MSC_VER - EXPECT_EQ(cgogn::name_of_type(int64()), "long long"); - EXPECT_EQ(cgogn::name_of_type(uint64()), "unsigned long long"); -#else EXPECT_EQ(cgogn::name_of_type(int64()), "long"); EXPECT_EQ(cgogn::name_of_type(uint64()), "unsigned long"); -#endif - - EXPECT_EQ(cgogn::name_of_type(llint()), "long long"); - EXPECT_EQ(cgogn::name_of_type(ullint()), "unsigned long long"); + EXPECT_EQ(cgogn::name_of_type(llint()), "long"); + EXPECT_EQ(cgogn::name_of_type(ullint()), "unsigned long"); EXPECT_EQ(cgogn::name_of_type(float()), "float"); EXPECT_EQ(cgogn::name_of_type(double()), "double"); diff --git a/cgogn/core/utils/name_types.h b/cgogn/core/utils/name_types.h index 37e6f7d8..96887896 100644 --- a/cgogn/core/utils/name_types.h +++ b/cgogn/core/utils/name_types.h @@ -137,9 +137,9 @@ inline auto name_of_type_impl(const T&)->typename std::enable_if::value) - return "long long"; + return "long"; if (std::is_same::value) - return "unsigned long long"; + return "unsigned long"; // removing all "class " and "struct" from type_name { From d284939ecccd4b2d0828bae7d748d2eccc6fa66c Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Tue, 22 Mar 2016 16:51:48 +0100 Subject: [PATCH 388/402] update some comments --- cgogn/core/cmap/map_base.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 8bef4da6..ae5d2a66 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -618,6 +618,7 @@ class MapBase : public MapBaseData * \Brief Methods to iterate over darts with a MASK that filters the traversed darts. * A MASK is a callable that determines if a dart should be traversed or skipped. * It returns false when a dart should be skipped, true in other cases. + * These functions also skip boundary darts. */ template inline Dart begin(const MASK& mask) const @@ -649,7 +650,7 @@ class MapBase : public MapBaseData public: /** - * \brief apply a function on each dart of the map + * \brief apply a function on each dart of the map (including boundary darts) * @tparam FUNC type of the callable * @param f a callable */ @@ -732,11 +733,10 @@ class MapBase : public MapBaseData } /** - * \brief apply a function on each dart of the map and stops when the function returns false + * \brief apply a function on each dart of the map (including boundary darts) and stops when the function returns false * @tparam FUNC type of the callable * @param f a callable */ - template inline void foreach_dart_until(const FUNC& f) const { @@ -751,7 +751,8 @@ class MapBase : public MapBaseData } /** - * \brief apply a function on each orbit of the map + * \brief apply a function on each cell of the map (boundary cells excluded) + * (the dimension of the traversed cells is determined based on the parameter of the given callable) * @tparam FUNC type of the callable * @param f a callable */ @@ -831,7 +832,8 @@ class MapBase : public MapBaseData } /** - * \brief apply a function on each orbit of the map and stops when the function returns false + * \brief apply a function on each cell of the map (boundary cells excluded) and stops when the function returns false + * (the dimension of the traversed cells is determined based on the parameter of the given callable) * @tparam FUNC type of the callable * @param f a callable */ From fe8f08c1f72b07fab37382f643404114ce878461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Tue, 22 Mar 2016 17:01:11 +0100 Subject: [PATCH 389/402] is_well_embedded more expressive. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/map_base.h | 49 ++++++++++++++--------------------- cgogn/geometry/CMakeLists.txt | 5 ++-- 2 files changed, 23 insertions(+), 31 deletions(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index a9885317..c4fba473 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -400,17 +400,13 @@ class MapBase : public MapBaseData cgogn_message_assert(this->template is_embedded(), "Invalid parameter: orbit not embedded"); const ConcreteMap* cmap = to_concrete(); - AttributeHandler counter = add_attribute("__tmp_marker"); + AttributeHandler, ORBIT> counter = add_attribute, ORBIT>("__tmp_dart_per_emb"); bool result = true; const typename Inherit::template ChunkArrayContainer& container = this->attributes_[ORBIT]; - // a marker is initialized to false for each "used" index of the container - for (unsigned int i = container.begin(), end = container.end(); i != end; container.next(i)) - counter[i] = 0; - // Check that the indexation of cells is correct - foreach_cell_until_nomask( + foreach_cell( [&] (CellType c) { unsigned int idx = this->get_embedding(c); @@ -418,40 +414,35 @@ class MapBase : public MapBaseData if (idx == EMBNULL) { result = false; - std::cerr << "EMBNULL found in orbit " << orbit_name(ORBIT) << std::endl; - return result; + std::cerr << "EMBNULL found for dart "<< c << " in orbit " << orbit_name(ORBIT) << std::endl; + return; } - // ensure that two cells do not share the same index - if (counter[idx] > 0) - { - result = false; - std::cerr << "Two cells with same index in orbit " << orbit_name(ORBIT) << std::endl; - return result; - } - counter[idx] = 1; + counter[idx].push_back(c); // check all darts of the cell use the same index (distinct to EMBNULL) - cmap->foreach_dart_of_orbit_until(c, [&] (Dart d) + cmap->foreach_dart_of_orbit(c, [&] (Dart d) { - if (this->get_embedding(CellType(d)) != idx) - result = false; - if (!result) - std::cerr << "Different indices in orbit " << orbit_name(ORBIT) << std::endl; - return result; + const unsigned int emb_d = this->get_embedding(CellType(d)); + if (emb_d != idx) + std::cerr << "Different indices (" << idx << " and " << emb_d << ") in orbit " << orbit_name(ORBIT) << std::endl; }); - - return result; } ); // check that all cells present in the attribute handler are used - if (result) { for (unsigned int i = container.begin(), end = container.end(); i != end; container.next(i)) { - if (counter[i] == 0) + if (counter[i].empty()) { - result = false; - std::cerr << "Some cells are not used in orbit " << orbit_name(ORBIT) << std::endl; - break; + result =false; + std::cerr << "Cell #" << i << " is not used in orbit " << orbit_name(ORBIT) << std::endl; + } else + { + const std::size_t size = counter[i].size(); + if (size >= 2ul) + { + result =false; + std::cerr << size << " cells with same index \"" << i << "\" in orbit " << orbit_name(ORBIT) << std::endl; + } } } } diff --git a/cgogn/geometry/CMakeLists.txt b/cgogn/geometry/CMakeLists.txt index d03fb8a9..cb881079 100644 --- a/cgogn/geometry/CMakeLists.txt +++ b/cgogn/geometry/CMakeLists.txt @@ -33,9 +33,10 @@ add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "_d") - target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC - $ +target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC + $ ) + target_include_directories(${PROJECT_NAME} PUBLIC $ $ From 3aee739d191f3551811331e64c186fbc451a669a Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Wed, 23 Mar 2016 10:07:42 +0100 Subject: [PATCH 390/402] CMap2Test : do not index Dart orbits for boundary Darts --- cgogn/core/tests/cmap/cmap2_test.cpp | 8 ++++---- cgogn/core/tests/cmap/cmap2_topo_test.cpp | 16 +++++++--------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/cgogn/core/tests/cmap/cmap2_test.cpp b/cgogn/core/tests/cmap/cmap2_test.cpp index 5602f059..d3144a2e 100644 --- a/cgogn/core/tests/cmap/cmap2_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_test.cpp @@ -104,12 +104,11 @@ class CMap2Test : public ::testing::Test { darts_.clear(); MapBuilder mbuild(cmap_); - uint32 n; // Generate NB_MAX random 1-faces (without boundary) for (uint32 i = 0u; i < NB_MAX; ++i) { - n = 1u + std::rand() % 10u; + uint32 n = 1u + std::rand() % 10u; Dart d = mbuild.add_face_topo_parent(n); darts_.push_back(d); } @@ -117,7 +116,7 @@ class CMap2Test : public ::testing::Test for (uint32 i = 0u; i < 3u * NB_MAX; ++i) { Dart e1 = darts_[std::rand() % NB_MAX]; - n = std::rand() % 10u; + uint32 n = std::rand() % 10u; while (n-- > 0u) e1 = cmap_.phi1(e1); Dart e2 = darts_[std::rand() % NB_MAX]; @@ -140,7 +139,8 @@ class CMap2Test : public ::testing::Test // Embed the map cmap_.foreach_dart([&] (Dart d) { - mbuild.new_orbit_embedding(CDart(d)); + if (!cmap_.is_boundary(d)) + mbuild.new_orbit_embedding(CDart(d)); }); cmap_.foreach_cell([&] (Vertex v) { diff --git a/cgogn/core/tests/cmap/cmap2_topo_test.cpp b/cgogn/core/tests/cmap/cmap2_topo_test.cpp index 006c7214..1820299a 100644 --- a/cgogn/core/tests/cmap/cmap2_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_topo_test.cpp @@ -35,13 +35,12 @@ namespace cgogn * \brief The CMap2TopoTest class implements topological tests on CMap2 * It derives from CMap2 to allow the test of protected methods * - * Note that these tests, check that the topological operators perform as wanted - * but do neither tests the containers (refs_, used_, etc.) or the iterators. + * Note that these tests check that the topological operators perform as wanted + * but do neither test the containers (refs_, used_, etc.) nor the iterators. * These last tests are implemented in another test suite. */ class CMap2TopoTest : public CMap2, public ::testing::Test { - public: using Inherit = CMap2; @@ -96,7 +95,7 @@ class CMap2TopoTest : public CMap2, public ::testing::Test { bool result = false; - foreach_dart_of_orbit_until(Volume(d), [&](Dart vit) + foreach_dart_of_orbit_until(Volume(d), [&] (Dart vit) { if (vit == e) result = true; return !result; @@ -157,20 +156,19 @@ class CMap2TopoTest : public CMap2, public ::testing::Test void add_closed_surfaces() { darts_.clear(); - uint32 n; // Generate NB_MAX random 1-faces (without boundary) for (uint32 i = 0u; i < NB_MAX; ++i) { - n = 1u + std::rand() % 10; + uint32 n = 1u + std::rand() % 10u; Dart d = Inherit::Inherit::add_face_topo(n); darts_.push_back(d); } - // Sew some pairs off 1-edges + // Sew some pairs of 1-edges for (uint32 i = 0u; i < 3u * NB_MAX; ++i) { Dart e1 = darts_[std::rand() % NB_MAX]; - n = std::rand() % 10u; + uint32 n = std::rand() % 10u; while (n-- > 0u) e1 = phi1(e1); Dart e2 = darts_[std::rand() % NB_MAX]; @@ -185,7 +183,7 @@ class CMap2TopoTest : public CMap2, public ::testing::Test e2 = phi_1(e2); } } - // Close de map + // Close the map MapBuilder mbuild(*this); mbuild.close_map(); } From 127a447abe9e0652f79a5e5035e4964fad080417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 23 Mar 2016 11:19:08 +0100 Subject: [PATCH 391/402] added name_of_type_impl overrides. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/tests/utils/name_types_test.cpp | 26 ++++++-------- cgogn/core/utils/definitions.h | 13 ++----- cgogn/core/utils/name_types.cpp | 40 ++++++++++++++++++++++ cgogn/core/utils/name_types.h | 27 +++++++++++---- 4 files changed, 72 insertions(+), 34 deletions(-) diff --git a/cgogn/core/tests/utils/name_types_test.cpp b/cgogn/core/tests/utils/name_types_test.cpp index d2c5d0d7..21391be1 100644 --- a/cgogn/core/tests/utils/name_types_test.cpp +++ b/cgogn/core/tests/utils/name_types_test.cpp @@ -30,34 +30,28 @@ using namespace cgogn::numerics; TEST(NameTypesTest, NumTypes) { - using llint = long long; - using ullint = unsigned long long; - EXPECT_EQ(cgogn::name_of_type(bool()), "bool"); EXPECT_EQ(cgogn::name_of_type(char()), "char"); - EXPECT_EQ(cgogn::name_of_type(int8()), "signed char"); - EXPECT_EQ(cgogn::name_of_type(uint8()), "unsigned char"); + EXPECT_EQ(cgogn::name_of_type(int8()), "int8"); + EXPECT_EQ(cgogn::name_of_type(uint8()), "uint8"); EXPECT_EQ(cgogn::name_of_type(wchar_t()), "wchar_t"); #if _MSC_VER == 1800 // VS2013 - EXPECT_EQ(cgogn::name_of_type(char16_t()), "unsigned short"); - EXPECT_EQ(cgogn::name_of_type(char32_t()), "unsigned int"); + EXPECT_EQ(cgogn::name_of_type(char16_t()), "uint16"); + EXPECT_EQ(cgogn::name_of_type(char32_t()), "uint32"); #else EXPECT_EQ(cgogn::name_of_type(char16_t()), "char16_t"); EXPECT_EQ(cgogn::name_of_type(char32_t()), "char32_t"); #endif // VS2013 - EXPECT_EQ(cgogn::name_of_type(int16()), "short"); - EXPECT_EQ(cgogn::name_of_type(uint16()), "unsigned short"); - EXPECT_EQ(cgogn::name_of_type(int32()), "int"); - - EXPECT_EQ(cgogn::name_of_type(uint32()), "unsigned int"); + EXPECT_EQ(cgogn::name_of_type(int16()), "int16"); + EXPECT_EQ(cgogn::name_of_type(uint16()), "uint16"); - EXPECT_EQ(cgogn::name_of_type(int64()), "long"); - EXPECT_EQ(cgogn::name_of_type(uint64()), "unsigned long"); + EXPECT_EQ(cgogn::name_of_type(int32()), "int32"); + EXPECT_EQ(cgogn::name_of_type(uint32()), "uint32"); - EXPECT_EQ(cgogn::name_of_type(llint()), "long"); - EXPECT_EQ(cgogn::name_of_type(ullint()), "unsigned long"); + EXPECT_EQ(cgogn::name_of_type(int64()), "int64"); + EXPECT_EQ(cgogn::name_of_type(uint64()), "uint64"); EXPECT_EQ(cgogn::name_of_type(float()), "float"); EXPECT_EQ(cgogn::name_of_type(double()), "double"); diff --git a/cgogn/core/utils/definitions.h b/cgogn/core/utils/definitions.h index a84fa13a..146d9347 100644 --- a/cgogn/core/utils/definitions.h +++ b/cgogn/core/utils/definitions.h @@ -29,6 +29,7 @@ namespace cgogn { + namespace numerics { @@ -42,21 +43,11 @@ using uint16 = std::uint16_t; using uint32 = std::uint32_t; using uint64 = std::uint64_t; -using float32 = float; -using float64 = double; - } + using namespace numerics; } - -//#define USING_CGOGN_NUMERICS using cgogn::int8; using cgogn::uint8; \ -// using cgogn::int16; using cgogn::uint16;\ -// using cgogn::int32; using cgogn::uint32;\ -// using cgogn::int64; using cgogn::uint64;\ -// using cgogn::float32; using cgogn::float64; - - /** * \brief No execpt declaration for CGOGN symbols. * For a given type T, std::vector will only use move constructor of T if it's marked noexcept. Same for std::swap. diff --git a/cgogn/core/utils/name_types.cpp b/cgogn/core/utils/name_types.cpp index c2e6b8ce..8890fe1b 100644 --- a/cgogn/core/utils/name_types.cpp +++ b/cgogn/core/utils/name_types.cpp @@ -57,5 +57,45 @@ CGOGN_CORE_API std::string demangle(const std::string& str) #endif // __GNUG__ } +CGOGN_CORE_API std::string name_of_type_impl(const int8&) +{ + return "int8"; +} + +CGOGN_CORE_API std::string name_of_type_impl(const uint8&) +{ + return "uint8"; +} + +CGOGN_CORE_API std::string name_of_type_impl(const int16&) +{ + return "int16"; +} + +CGOGN_CORE_API std::string name_of_type_impl(const uint16&) +{ + return "uint16"; +} + +CGOGN_CORE_API std::string name_of_type_impl(const int32&) +{ + return "int32"; +} + +CGOGN_CORE_API std::string name_of_type_impl(const uint32&) +{ + return "uint32"; +} + +CGOGN_CORE_API std::string name_of_type_impl(const int64&) +{ + return "int64"; +} + +CGOGN_CORE_API std::string name_of_type_impl(const uint64&) +{ + return "uint64"; +} + } // namespace internal } // namespace cgogn diff --git a/cgogn/core/utils/name_types.h b/cgogn/core/utils/name_types.h index 96887896..46fe967c 100644 --- a/cgogn/core/utils/name_types.h +++ b/cgogn/core/utils/name_types.h @@ -59,6 +59,8 @@ inline std::string name_of_type(const T& t); namespace internal { +CGOGN_CORE_API std::string demangle(const std::string& str); + template struct sfinae_true : std::true_type{}; @@ -93,7 +95,22 @@ inline std::string name_of_type_impl(const std::basic_string&); template inline std::string name_of_type_impl(const std::array&); -CGOGN_CORE_API std::string demangle(const std::string& str); +CGOGN_CORE_API std::string name_of_type_impl(const int8&); + +CGOGN_CORE_API std::string name_of_type_impl(const uint8&); + +CGOGN_CORE_API std::string name_of_type_impl(const int16&); + +CGOGN_CORE_API std::string name_of_type_impl(const uint16&); + +CGOGN_CORE_API std::string name_of_type_impl(const int32&); + +CGOGN_CORE_API std::string name_of_type_impl(const uint32&); + +CGOGN_CORE_API std::string name_of_type_impl(const int64&); + +CGOGN_CORE_API std::string name_of_type_impl(const uint64&); + // definitions @@ -135,12 +152,6 @@ inline auto name_of_type_impl(const T&)->typename std::enable_if::value) - return "long"; - if (std::is_same::value) - return "unsigned long"; - // removing all "class " and "struct" from type_name { std::regex regex_class("class ", std::regex_constants::ECMAScript); @@ -187,6 +198,8 @@ inline std::string name_of_type(const T& t) return internal::name_of_type_impl(t); } + + } // namespace cgogn #endif // CORE_UTILS_NAME_TYPES_H_ From 2a8ad33b963f5e9a3d5ab8f188a5ba1a343b059f Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Wed, 23 Mar 2016 15:21:25 +0100 Subject: [PATCH 392/402] fix cmap2 close_map test --- cgogn/core/tests/cmap/cmap2_topo_test.cpp | 28 +++++++++++++---------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/cgogn/core/tests/cmap/cmap2_topo_test.cpp b/cgogn/core/tests/cmap/cmap2_topo_test.cpp index 1820299a..cce914d4 100644 --- a/cgogn/core/tests/cmap/cmap2_topo_test.cpp +++ b/cgogn/core/tests/cmap/cmap2_topo_test.cpp @@ -354,6 +354,7 @@ TEST_F(CMap2TopoTest, close_map) add_attribute("edges"); add_attribute("faces"); add_attribute("volumes"); + EXPECT_TRUE(check_map_integrity()); // create some random holes (full removal or partial unsewing of faces) @@ -367,18 +368,21 @@ TEST_F(CMap2TopoTest, close_map) foreach_dart_of_orbit_until(Face(d), [&] (Dart e) { Dart e2 = phi2(e); - phi2_unsew(e); - // correct indexation of vertices - if (!same_open_vertex(e2, phi1(e))) new_open_vertex_embedding(e2); - if (!same_open_vertex(e, phi1(e2))) new_open_vertex_embedding(e); - // correct indexation of edges - new_orbit_embedding(Edge(e2)); - // correct indexation of volumes - if (!same_volume(e2, e)) new_orbit_embedding(Volume(e)); - // interrupt the face unsewing after n steps - if (n-- <= 0) return false; - // control if a partial or full face unsewing has been done - --k; + if (!this->is_boundary(e) && !this->is_boundary(e2)) + { + phi2_unsew(e); + // correct indexation of vertices + if (!same_open_vertex(e2, phi1(e))) new_open_vertex_embedding(e2); + if (!same_open_vertex(e, phi1(e2))) new_open_vertex_embedding(e); + // correct indexation of edges + new_orbit_embedding(Edge(e2)); + // correct indexation of volumes + if (!same_volume(e2, e)) new_orbit_embedding(Volume(e)); + // interrupt the face unsewing after n steps + if (n-- <= 0) return false; + // control if a partial or full face unsewing has been done + --k; + } return true; }); // if the face is completely unsewn randomly removes it From 92cf8d32853ec08a489682f5152f4f07c6229a20 Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Wed, 23 Mar 2016 16:30:14 +0100 Subject: [PATCH 393/402] do not index boundary volume cells in CMap3Builder::close_map --- cgogn/core/cmap/cmap3_builder.h | 77 +++++++++++++++++---------------- 1 file changed, 39 insertions(+), 38 deletions(-) diff --git a/cgogn/core/cmap/cmap3_builder.h b/cgogn/core/cmap/cmap3_builder.h index 5750dce6..5354cb99 100644 --- a/cgogn/core/cmap/cmap3_builder.h +++ b/cgogn/core/cmap/cmap3_builder.h @@ -195,7 +195,7 @@ class CMap3Builder_T { // Search the map for topological holes (fix points of phi3) std::vector* fix_point_darts = get_dart_buffers()->get_buffer(); - map_.foreach_dart( [&] (Dart d) + map_.foreach_dart([&] (Dart d) { if (map_.phi3(d) == d) fix_point_darts->push_back(d); @@ -209,45 +209,46 @@ class CMap3Builder_T { map_.set_boundary(db,true); }); - const Volume new_volume(map_.phi3(d)); - - if (map_.template is_embedded()) - { - map_.foreach_dart_of_orbit(new_volume, [this] (Dart d) - { - map_.new_orbit_embedding(CDart(d)); - }); - } - if (map_.template is_embedded()) - { - map_.CMap3::Inherit::foreach_incident_vertex(new_volume, [this] (Vertex2 v) - { - map_.new_orbit_embedding(v); - }); - } - - if (map_.template is_embedded()) - { - map_.CMap3::Inherit::foreach_incident_edge(new_volume, [this] (Edge2 e) - { - map_.new_orbit_embedding(e); - }); - } + const Volume new_volume(map_.phi3(d)); - if (map_.template is_embedded()) - { - map_.CMap3::Inherit::foreach_incident_face(new_volume, [this] (Face2 f) - { - map_.new_orbit_embedding(f); - }); - } +// if (map_.template is_embedded()) +// { +// map_.foreach_dart_of_orbit(new_volume, [this] (Dart d) +// { +// map_.new_orbit_embedding(CDart(d)); +// }); +// } + +// if (map_.template is_embedded()) +// { +// map_.CMap3::Inherit::foreach_incident_vertex(new_volume, [this] (Vertex2 v) +// { +// map_.new_orbit_embedding(v); +// }); +// } + +// if (map_.template is_embedded()) +// { +// map_.CMap3::Inherit::foreach_incident_edge(new_volume, [this] (Edge2 e) +// { +// map_.new_orbit_embedding(e); +// }); +// } + +// if (map_.template is_embedded()) +// { +// map_.CMap3::Inherit::foreach_incident_face(new_volume, [this] (Face2 f) +// { +// map_.new_orbit_embedding(f); +// }); +// } if (map_.template is_embedded()) { - map_.foreach_dart_of_orbit(new_volume, [this] (Dart wd) + map_.foreach_dart_of_orbit(new_volume, [this] (Dart it) { - map_.template copy_embedding(wd, map_.phi1(map_.phi3(wd))); + map_.template copy_embedding(it, map_.phi1(map_.phi3(it))); }); } @@ -267,10 +268,10 @@ class CMap3Builder_T }); } - if (map_.template is_embedded()) - { - map_.new_orbit_embedding(new_volume); - } +// if (map_.template is_embedded()) +// { +// map_.new_orbit_embedding(new_volume); +// } } } get_dart_buffers()->release_buffer(fix_point_darts); From 2632629f98c7a102f7789527534c07f0fb719966 Mon Sep 17 00:00:00 2001 From: Pierre Kraemer Date: Wed, 23 Mar 2016 16:37:00 +0100 Subject: [PATCH 394/402] Dart output stream operator no more prints "-1" for nil Darts --- cgogn/core/basic/dart.h | 29 +++++++++++------------ cgogn/core/tests/basic/dart_test.cpp | 4 ++-- cgogn/rendering/examples/viewer_topo3.cpp | 2 ++ 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/cgogn/core/basic/dart.h b/cgogn/core/basic/dart.h index 225b2559..e94d2195 100644 --- a/cgogn/core/basic/dart.h +++ b/cgogn/core/basic/dart.h @@ -110,20 +110,17 @@ struct Dart inline bool operator!=(Dart rhs) const { return index != rhs.index; } // To remove - // operator < is needed if we want to use std::set +// operator < is needed if we want to use std::set // inline bool operator<(Dart rhs) const { return index < rhs.index; } -// /** -// * \brief Prints a dart to a stream. -// * \param[out] out the stream to print on -// * \param[in] rhs the dart to print -// */ - - // -1 should be less system dependent - inline friend std::ostream& operator<<(std::ostream &out, const Dart& rhs) { - if (rhs.is_nil()) - return out << -1; - else - return out << rhs.index; + + /** + * \brief Prints a dart to a stream. + * \param[out] out the stream to print on + * \param[in] rhs the dart to print + */ + inline friend std::ostream& operator<<(std::ostream &out, const Dart& rhs) + { + return out << rhs.index; } /** @@ -131,8 +128,10 @@ struct Dart * \param[in] in the stream to read from * \param[out] rhs the dart read */ - inline friend std::istream& operator>>(std::istream &in, Dart& rhs) { - in >> rhs.index; return in; + inline friend std::istream& operator>>(std::istream &in, Dart& rhs) + { + in >> rhs.index; + return in; } }; diff --git a/cgogn/core/tests/basic/dart_test.cpp b/cgogn/core/tests/basic/dart_test.cpp index 3d1f0315..1d64697f 100644 --- a/cgogn/core/tests/basic/dart_test.cpp +++ b/cgogn/core/tests/basic/dart_test.cpp @@ -103,7 +103,7 @@ TEST_F(DartTest, PrintingOut) EXPECT_STREQ(s.str().c_str(), "10"); std::ostringstream t; t << dNil_; - EXPECT_STREQ(t.str().c_str(), "-1"); + EXPECT_STREQ(t.str().c_str(), "4294967295"); } TEST_F(DartTest, ReadingIn) @@ -113,7 +113,7 @@ TEST_F(DartTest, ReadingIn) s >> d; EXPECT_TRUE(d == d10a_); Dart e; - std::istringstream t("-1"); + std::istringstream t("4294967295"); t >> e; EXPECT_TRUE(e == dNil_); } diff --git a/cgogn/rendering/examples/viewer_topo3.cpp b/cgogn/rendering/examples/viewer_topo3.cpp index 0cf6de90..ccf0935a 100644 --- a/cgogn/rendering/examples/viewer_topo3.cpp +++ b/cgogn/rendering/examples/viewer_topo3.cpp @@ -112,6 +112,8 @@ void Viewer::import(const std::string& volumeMesh) Vec3 center = bb_.center(); setSceneCenter(qoglviewer::Vec(center[0], center[1], center[2])); showEntireScene(); + + map_.check_map_integrity(); } Viewer::~Viewer() From 582a4052f56b25041a10dc1ff737f2a60ea4c59f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 23 Mar 2016 17:38:19 +0100 Subject: [PATCH 395/402] using PUBLIC target_compile_definitions to avoid missing definition bug. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/CMakeLists.txt | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/cgogn/io/CMakeLists.txt b/cgogn/io/CMakeLists.txt index 6cd3d67c..dbadb246 100644 --- a/cgogn/io/CMakeLists.txt +++ b/cgogn/io/CMakeLists.txt @@ -3,12 +3,6 @@ project(cgogn_io ) find_package(ZLIB) -if (ZLIB_FOUND) - add_definitions("-DZLIB_CONST") - add_definitions("-DCGOGN_WITH_ZLIB") -endif() - - set(HEADER_FILES surface_import.h @@ -49,6 +43,11 @@ target_include_directories(${PROJECT_NAME} PUBLIC $ ) +if (${ZLIB_FOUND}) + target_compile_definitions(${PROJECT_NAME} PUBLIC -DZLIB_CONST) + target_compile_definitions(${PROJECT_NAME} PUBLIC -DCGOGN_WITH_ZLIB) +endif() + target_link_libraries(${PROJECT_NAME} tinyxml2 cgogn_core cgogn_geometry ply lm6 ${ZLIB_LIBRARIES}) install(DIRECTORY . From c88c9f60040c72bbac97e55f1690a389bf423de9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 23 Mar 2016 18:28:05 +0100 Subject: [PATCH 396/402] Chunk array container : added two booleans parameters : copy_marker and copy_refs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/container/chunk_array_container.h | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/cgogn/core/container/chunk_array_container.h b/cgogn/core/container/chunk_array_container.h index 32724bbe..646e175d 100644 --- a/cgogn/core/container/chunk_array_container.h +++ b/cgogn/core/container/chunk_array_container.h @@ -537,7 +537,7 @@ class ChunkArrayContainer { unsigned rdown = down + PRIMSIZE-1u - i; map_old_new[up] = rdown; - copy_line(rdown, up); + copy_line(rdown, up,true,true); rnext(up); } down += PRIMSIZE; @@ -676,16 +676,21 @@ class ChunkArrayContainer * @brief copy the content of line src in line dst (with refs & markers) * @param dstIndex destination * @param srcIndex source + * @param copy_markers, to specify if the marker should be copied. + * @param copy_refs, to specify if the refs should be copied. */ - void copy_line(uint32 dst, uint32 src) + void copy_line(uint32 dst, uint32 src, bool copy_markers, bool copy_refs) { for (auto ptr : table_arrays_) ptr->copy_element(dst, src); - for (auto ptr : table_marker_arrays_) - ptr->copy_element(dst, src); - - refs_[dst] = refs_[src]; + if (copy_markers) + { + for (auto ptr : table_marker_arrays_) + ptr->copy_element(dst, src); + } + if (copy_refs) + refs_[dst] = refs_[src]; } /** From c2d31bdea8dfd01eaff62b26c362ee4b7d04cca8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 23 Mar 2016 18:28:35 +0100 Subject: [PATCH 397/402] enforce_unique_orbit_embedding : copy the attributes of the duplicated vertex. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/map_base.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 665cb693..294aad25 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -376,7 +376,12 @@ class MapBase : public MapBaseData foreach_cell([this, &counter] (Cell c) { if (counter[c] > 0) - this->new_orbit_embedding(c); + { + const uint32 old_emb = this->get_embedding(c); + const uint32 new_emb = this->new_orbit_embedding(c); + this->template get_attribute_container().copy_line(new_emb, old_emb,false,false); + } + counter[c]++; }); From 239f8e4e8df04455139562119a3fad9743eca5a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 23 Mar 2016 18:29:08 +0100 Subject: [PATCH 398/402] calling enforce_unique_orbit_embedding when importing a volume mesh. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/volume_import.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cgogn/io/volume_import.h b/cgogn/io/volume_import.h index 57886426..303b8116 100644 --- a/cgogn/io/volume_import.h +++ b/cgogn/io/volume_import.h @@ -466,6 +466,9 @@ class VolumeImport : public MeshImportGen std::cout << CGOGN_FUNC << ": Map closed with " << nbBoundaryFaces << " boundary face(s)." << std::endl; } + if (this->nb_vertices_ != map.template nb_cells()) + map.template enforce_unique_orbit_embedding(); + if (this->volume_attributes_.get_nb_attributes() > 0) { mbuild.template create_embedding(); From 9c40e069fd010b1a775c1581830f0e9107c96f80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 23 Mar 2016 18:35:09 +0100 Subject: [PATCH 399/402] added a warning message. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/map_base.h | 1 + 1 file changed, 1 insertion(+) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 294aad25..19e2cdc9 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -379,6 +379,7 @@ class MapBase : public MapBaseData { const uint32 old_emb = this->get_embedding(c); const uint32 new_emb = this->new_orbit_embedding(c); + std::cerr << "Warning : " << CGOGN_FUNC << ": duplicating orbit #" << old_emb << " in orbit " << orbit_name(ORBIT) << std::endl; this->template get_attribute_container().copy_line(new_emb, old_emb,false,false); } From 55eca074d2d8d8d64972f66afba26e4e9054520e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 23 Mar 2016 18:56:21 +0100 Subject: [PATCH 400/402] fixed CGOGN_FUNC displaying "operator ()" because called inside a lambda. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/core/cmap/map_base.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cgogn/core/cmap/map_base.h b/cgogn/core/cmap/map_base.h index 19e2cdc9..12b45358 100644 --- a/cgogn/core/cmap/map_base.h +++ b/cgogn/core/cmap/map_base.h @@ -379,7 +379,7 @@ class MapBase : public MapBaseData { const uint32 old_emb = this->get_embedding(c); const uint32 new_emb = this->new_orbit_embedding(c); - std::cerr << "Warning : " << CGOGN_FUNC << ": duplicating orbit #" << old_emb << " in orbit " << orbit_name(ORBIT) << std::endl; + std::cerr << "Warning: enforce_unique_orbit_embedding: duplicating orbit #" << old_emb << " in orbit " << orbit_name(ORBIT) << std::endl; this->template get_attribute_container().copy_line(new_emb, old_emb,false,false); } From a286121071092a3231e687a7a15213897f16f042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Schmitt?= Date: Wed, 23 Mar 2016 18:57:02 +0100 Subject: [PATCH 401/402] enforce_unique_embedding called if nb of vertices with dart marking is != from the nb of vertices in the mesh. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Étienne Schmitt --- cgogn/io/volume_import.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cgogn/io/volume_import.h b/cgogn/io/volume_import.h index 303b8116..450c962d 100644 --- a/cgogn/io/volume_import.h +++ b/cgogn/io/volume_import.h @@ -466,7 +466,10 @@ class VolumeImport : public MeshImportGen std::cout << CGOGN_FUNC << ": Map closed with " << nbBoundaryFaces << " boundary face(s)." << std::endl; } - if (this->nb_vertices_ != map.template nb_cells()) + unsigned int nb_vert_dart_marking = 0u; + map.template foreach_cell([&nb_vert_dart_marking](Vertex v){++nb_vert_dart_marking;}); + + if (this->nb_vertices_ != nb_vert_dart_marking) map.template enforce_unique_orbit_embedding(); if (this->volume_attributes_.get_nb_attributes() > 0) From aa5016a2acef2888501dca584beef67bb1860071 Mon Sep 17 00:00:00 2001 From: Lionel Untereiner Date: Wed, 23 Mar 2016 22:43:27 +0100 Subject: [PATCH 402/402] float/double to float32/float64 to be more consistant --- .../multithreading/bench_multithreading.cpp | 2 +- cgogn/core/container/chunk_array.cpp | 4 +- cgogn/core/container/chunk_array.h | 4 +- cgogn/core/container/chunk_array_container.h | 4 +- cgogn/core/container/chunk_array_factory.h | 8 +-- .../chunk_array/bench_chunk_array.cpp | 16 ++--- .../core/examples/chunk_array/chunk_array.cpp | 18 ++--- .../examples/chunk_array/chunk_array2.cpp | 10 +-- cgogn/core/examples/map/map.cpp | 26 +++---- cgogn/core/utils/definitions.h | 3 + cgogn/core/utils/endian.h | 12 ++-- cgogn/geometry/types/bounding_box.cpp | 4 +- cgogn/geometry/types/bounding_box.h | 4 +- cgogn/geometry/types/geometry_traits.h | 8 +-- cgogn/geometry/types/plane_3d.cpp | 4 +- cgogn/geometry/types/plane_3d.h | 4 +- cgogn/geometry/types/vec.cpp | 4 +- cgogn/geometry/types/vec.h | 4 +- cgogn/io/data_io.h | 16 ++--- cgogn/io/examples/cmap2_import.cpp | 4 +- cgogn/io/examples/cmap3_import.cpp | 4 +- cgogn/io/import_ply_data.h | 6 +- cgogn/io/io_utils.cpp | 4 +- cgogn/io/lm6_io.h | 2 +- cgogn/io/map_export.h | 24 +++---- .../examples/map3_from_surface.cpp | 2 +- cgogn/io/mesh_generation/tetgen_io.h | 4 +- cgogn/io/obj_io.h | 2 +- cgogn/io/off_io.h | 14 ++-- cgogn/io/vtk_io.h | 4 +- cgogn/rendering/drawer.cpp | 6 +- cgogn/rendering/drawer.h | 34 ++++----- cgogn/rendering/examples/picking_viewer.cpp | 2 +- cgogn/rendering/examples/viewer_per_face.cpp | 14 ++-- cgogn/rendering/examples/viewer_topo.cpp | 2 +- cgogn/rendering/examples/viewer_topo3.cpp | 4 +- cgogn/rendering/shaders/shader_bold_line.cpp | 4 +- cgogn/rendering/shaders/shader_bold_line.h | 2 +- .../shaders/shader_explode_volumes.cpp | 2 +- .../shaders/shader_explode_volumes.h | 2 +- .../shaders/shader_explode_volumes_line.cpp | 2 +- .../shaders/shader_explode_volumes_line.h | 2 +- cgogn/rendering/shaders/shader_phong.cpp | 2 +- cgogn/rendering/shaders/shader_phong.h | 2 +- .../rendering/shaders/shader_point_sprite.cpp | 2 +- cgogn/rendering/shaders/shader_point_sprite.h | 2 +- .../rendering/shaders/shader_round_point.cpp | 4 +- cgogn/rendering/shaders/shader_round_point.h | 2 +- .../shaders/shader_vector_per_vertex.cpp | 2 +- .../shaders/shader_vector_per_vertex.h | 2 +- cgogn/rendering/shaders/vbo.h | 52 +++++++------- cgogn/rendering/topo_render.h | 44 ++++++------ cgogn/rendering/volume_render.h | 72 +++++++++---------- 53 files changed, 245 insertions(+), 242 deletions(-) diff --git a/benchmarks/multithreading/bench_multithreading.cpp b/benchmarks/multithreading/bench_multithreading.cpp index 515788f1..b7ece59b 100644 --- a/benchmarks/multithreading/bench_multithreading.cpp +++ b/benchmarks/multithreading/bench_multithreading.cpp @@ -47,7 +47,7 @@ const cgogn::Orbit FACE = Face::ORBIT; const uint32 ITERATIONS = 1u; //using Vec3 = Eigen::Vector3d; -using Vec3 = cgogn::geometry::Vec_T>; +using Vec3 = cgogn::geometry::Vec_T>; template using VertexAttributeHandler = Map2::VertexAttributeHandler; diff --git a/cgogn/core/container/chunk_array.cpp b/cgogn/core/container/chunk_array.cpp index 68b5a5db..13926ef2 100644 --- a/cgogn/core/container/chunk_array.cpp +++ b/cgogn/core/container/chunk_array.cpp @@ -33,7 +33,7 @@ namespace cgogn template class CGOGN_CORE_API ChunkArray; template class CGOGN_CORE_API ChunkArray; template class CGOGN_CORE_API ChunkArray; -template class CGOGN_CORE_API ChunkArray>; -template class CGOGN_CORE_API ChunkArray>; +template class CGOGN_CORE_API ChunkArray>; +template class CGOGN_CORE_API ChunkArray>; } // namespace cgogn diff --git a/cgogn/core/container/chunk_array.h b/cgogn/core/container/chunk_array.h index e4f3cc8d..98229109 100644 --- a/cgogn/core/container/chunk_array.h +++ b/cgogn/core/container/chunk_array.h @@ -712,8 +712,8 @@ class ChunkArray : public ChunkArrayGen extern template class CGOGN_CORE_API ChunkArray; extern template class CGOGN_CORE_API ChunkArray; extern template class CGOGN_CORE_API ChunkArray; -extern template class CGOGN_CORE_API ChunkArray>; -extern template class CGOGN_CORE_API ChunkArray>; +extern template class CGOGN_CORE_API ChunkArray>; +extern template class CGOGN_CORE_API ChunkArray>; #endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(CORE_CONTAINER_CHUNK_ARRAY_CPP_)) } // namespace cgogn diff --git a/cgogn/core/container/chunk_array_container.h b/cgogn/core/container/chunk_array_container.h index 32724bbe..608dd308 100644 --- a/cgogn/core/container/chunk_array_container.h +++ b/cgogn/core/container/chunk_array_container.h @@ -511,9 +511,9 @@ class ChunkArrayContainer * @brief fragmentation of container (size/index of last lines): 100% = no holes * @return 1 is full filled - 0 is lots of holes */ - float fragmentation() const + float32 fragmentation() const { - return float(size()) / float(end()); + return float32(size()) / float32(end()); } /** diff --git a/cgogn/core/container/chunk_array_factory.h b/cgogn/core/container/chunk_array_factory.h index 2022dc14..0fd9baa4 100644 --- a/cgogn/core/container/chunk_array_factory.h +++ b/cgogn/core/container/chunk_array_factory.h @@ -92,11 +92,11 @@ class ChunkArrayFactory // register_CA(); // register_CA(); // register_CA(); - register_CA(); - register_CA(); + register_CA(); + register_CA(); register_CA(); - register_CA>(); - register_CA>(); + register_CA>(); + register_CA>(); // NOT TODO : add Eigen. known_types_initialized_ = true; diff --git a/cgogn/core/examples/chunk_array/bench_chunk_array.cpp b/cgogn/core/examples/chunk_array/bench_chunk_array.cpp index 2d89b213..23730719 100644 --- a/cgogn/core/examples/chunk_array/bench_chunk_array.cpp +++ b/cgogn/core/examples/chunk_array/bench_chunk_array.cpp @@ -16,14 +16,14 @@ int test5(); */ class Vec3f { - float data_[3]; + float32 data_[3]; public: Vec3f() {} - Vec3f(float x,float y, float z) + Vec3f(float32 x,float32 y, float32 z) { data_[0] = x; data_[1] = y; @@ -44,7 +44,7 @@ int test1() ChunkArrayContainer container; ChunkArray* att1 = container.add_attribute("entier"); - ChunkArray* att2 = container.add_attribute("reel"); + ChunkArray* att2 = container.add_attribute("reel"); ChunkArray* att3 = container.add_attribute("Vec3f"); for (uint32 i = 0; i < NB_LINES; ++i) @@ -53,8 +53,8 @@ int test1() for(uint32 i = container.begin(); i != container.end(); container.next(i)) { (*att1)[i] = 1+int32(i); - (*att2)[i] = 3.0f + 0.1f*float(i); - (*att3)[i] = Vec3f(float(i), float(i), float(i)); + (*att2)[i] = 3.0f + 0.1f*float32(i); + (*att3)[i] = Vec3f(float32(i), float32(i), float32(i)); } for (uint32 j = 0; j < 100; ++j) @@ -80,7 +80,7 @@ int test2() ChunkArrayContainer container; ChunkArray* att1 = container.add_attribute("entier"); - ChunkArray* att2 = container.add_attribute("reel"); + ChunkArray* att2 = container.add_attribute("reel"); ChunkArray* att3 = container.add_attribute("Vec3f"); for (uint32 i = 0; i < NB_LINES; ++i) @@ -89,8 +89,8 @@ int test2() for(uint32 i = container.begin(); i != container.end(); container.next(i)) { (*att1)[i] = 1+int32(i); - (*att2)[i] = 3.0f + 0.1f*float(i); - (*att3)[i] = Vec3f(float(i), float(i), float(i)); + (*att2)[i] = 3.0f + 0.1f*float32(i); + (*att3)[i] = Vec3f(float32(i), float32(i), float32(i)); } for (uint32 j = 0; j < 100; ++j) diff --git a/cgogn/core/examples/chunk_array/chunk_array.cpp b/cgogn/core/examples/chunk_array/chunk_array.cpp index 8ae8dac3..258852e9 100644 --- a/cgogn/core/examples/chunk_array/chunk_array.cpp +++ b/cgogn/core/examples/chunk_array/chunk_array.cpp @@ -23,7 +23,7 @@ int test1() ChunkArrayContainer container; ChunkArray* att1 = container.add_attribute("entier"); - ChunkArray* att2 = container.add_attribute("reel"); + ChunkArray* att2 = container.add_attribute("reel"); for (uint32 i = 0; i < 41; ++i) container.insert_lines<1>(); @@ -31,7 +31,7 @@ int test1() for(uint32 i = container.begin(); i != container.end(); container.next(i)) { (*att1)[i] = 1+int32(i); - (*att2)[i] = 3.0f + 0.1f*float(i); + (*att2)[i] = 3.0f + 0.1f*float32(i); } container.remove_lines<1>(3); @@ -212,11 +212,11 @@ int test3() int test4() { std::cout << "############### TEST 4 ###############" << std::endl; - using vecvecdouble = std::vector< std::vector< double > >; - using veclistdouble = std::vector< std::list< double > >; + using vecvecdouble = std::vector< std::vector< float64 > >; + using veclistdouble = std::vector< std::list< float64 > >; ChunkArrayContainer container; ChunkArray* att1 = container.add_attribute("entier"); - ChunkArray* att2 = container.add_attribute("reel"); + ChunkArray* att2 = container.add_attribute("reel"); ChunkArray* att3 = container.add_attribute("bools"); ChunkArray* att4 = container.add_attribute("vecvecdouble"); ChunkArray* att5 = container.add_attribute("veclistdouble"); @@ -227,10 +227,10 @@ int test4() for(uint32 i = container.begin(); i != container.end(); container.next(i)) { (*att1)[i] = 1+int32(i); - (*att2)[i] = 3.0f + 0.1f*float(i); + (*att2)[i] = 3.0f + 0.1f*float32(i); (*att3).set_value(i, static_cast(i%2 != 0)); - (*att4)[i] = {{3.0 + 0.1*double(i),15.0 + 0.1*double(i)}, {103.0 + 0.1*double(i), 203.0 + 0.1*double(i), 303.0 + 0.1*double(i)}}; - (*att5)[i] = {{3.0 + 0.1*double(i),15.0 + 0.1*double(i)}, {103.0 + 0.1*double(i), 203.0 + 0.1*double(i), 303.0 + 0.1*double(i)}}; + (*att4)[i] = {{3.0 + 0.1*float64(i),15.0 + 0.1*float64(i)}, {103.0 + 0.1*float64(i), 203.0 + 0.1*float64(i), 303.0 + 0.1*float64(i)}}; + (*att5)[i] = {{3.0 + 0.1*float64(i),15.0 + 0.1*float64(i)}, {103.0 + 0.1*float64(i), 203.0 + 0.1*float64(i), 303.0 + 0.1*float64(i)}}; } container.remove_lines<3>(3); @@ -246,7 +246,7 @@ int test4() ifi.close(); ChunkArray* load_att1 = cont2.get_attribute("entier"); - ChunkArray* load_att2 = cont2.get_attribute("reel"); + ChunkArray* load_att2 = cont2.get_attribute("reel"); ChunkArray* load_att3 = cont2.get_attribute("bools"); ChunkArray* load_att4 = cont2.get_attribute("vecvecdouble"); ChunkArray* load_att5 = cont2.get_attribute("veclistdouble"); diff --git a/cgogn/core/examples/chunk_array/chunk_array2.cpp b/cgogn/core/examples/chunk_array/chunk_array2.cpp index cfc2646e..d8ace780 100644 --- a/cgogn/core/examples/chunk_array/chunk_array2.cpp +++ b/cgogn/core/examples/chunk_array/chunk_array2.cpp @@ -13,7 +13,7 @@ using ChunkArray = cgogn::ChunkArray; using ChunkArrayContainer = cgogn::ChunkArrayContainer; using ChunkArrayFactory = cgogn::ChunkArrayFactory; -using DoubleVecList = std::list< std::vector< double > >; +using DoubleVecList = std::list< std::vector< float64 > >; using StringListVec = std::vector< std::list < std::string > >; using StringArray = std::array< std::string, 2>; @@ -27,7 +27,7 @@ int test_save() ChunkArrayContainer container; - ChunkArray* att1 = container.add_attribute("float"); + ChunkArray* att1 = container.add_attribute("float32"); ChunkArray* att4 = container.add_attribute("std::string"); ChunkArray* att2 = container.add_attribute("ListVecDouble"); ChunkArray* att3 = container.add_attribute("VecListString"); @@ -38,10 +38,10 @@ int test_save() for(uint32 i = container.begin(); i != container.end(); container.next(i)) { - (*att1)[i] = 0.1f*float(i); + (*att1)[i] = 0.1f*float32(i); (*att4)[i] = std::string(3,char('Z'-i)); - (*att2)[i] = {{3.0 + 0.1*double(i),15.0 + 0.1*double(i)}, {103.0 + 0.1*double(i), 203.0 + 0.1*double(i), 303.0 + 0.1*double(i)}}; + (*att2)[i] = {{3.0 + 0.1*float64(i),15.0 + 0.1*float64(i)}, {103.0 + 0.1*float64(i), 203.0 + 0.1*float64(i), 303.0 + 0.1*float64(i)}}; (*att3)[i] = {{"riri","riri"},{"fifi","fifi"},{"loulou","loulou"}}; @@ -127,7 +127,7 @@ int test_load(bool with_register) cont2.load(ifi); ifi.close(); - ChunkArray* att1 = cont2.get_attribute("float"); + ChunkArray* att1 = cont2.get_attribute("float32"); ChunkArray* att4 = cont2.get_attribute("std::string"); ChunkArray* att2 = cont2.get_attribute("ListVecDouble"); ChunkArray* att3 = cont2.get_attribute("VecListString"); diff --git a/cgogn/core/examples/map/map.cpp b/cgogn/core/examples/map/map.cpp index 05035398..98828350 100644 --- a/cgogn/core/examples/map/map.cpp +++ b/cgogn/core/examples/map/map.cpp @@ -15,39 +15,39 @@ using Map3 = CMap3; template -void fonc_const(const typename MAP::template VertexAttributeHandler& ah); +void fonc_const(const typename MAP::template VertexAttributeHandler& ah); template -void fonc_non_const(typename MAP::template VertexAttributeHandler& ah); +void fonc_non_const(typename MAP::template VertexAttributeHandler& ah); template int test1(MAP& map); template -void fonc_const(const typename MAP::template VertexAttributeHandler& ah) +void fonc_const(const typename MAP::template VertexAttributeHandler& ah) { - for (const float& f : ah) + for (const float32& f : ah) { std::cout << f << std::endl; } // equivalent to - for (typename MAP::template VertexAttributeHandler::const_iterator it = ah.begin(); it != ah.end(); ++it) + for (typename MAP::template VertexAttributeHandler::const_iterator it = ah.begin(); it != ah.end(); ++it) std::cout << *it << std::endl; } template -void fonc_non_const(typename MAP::template VertexAttributeHandler& ah) +void fonc_non_const(typename MAP::template VertexAttributeHandler& ah) { - for (float& f : ah) + for (float32& f : ah) { f *= 2.0f; std::cout << f << std::endl; } // equivalent to - for (typename MAP::template VertexAttributeHandler::iterator it = ah.begin(); it != ah.end(); ++it) + for (typename MAP::template VertexAttributeHandler::iterator it = ah.begin(); it != ah.end(); ++it) { *it /= 2.0f; } @@ -60,12 +60,12 @@ int test1(MAP& map) using Face = typename MAP::Face; // add an attribute on vertex of map with - typename MAP::template VertexAttributeHandler ah = map.template add_attribute("floats"); + typename MAP::template VertexAttributeHandler ah = map.template add_attribute("floats"); - typename MAP::template FaceAttributeHandler ahf = map.template add_attribute("floats"); + typename MAP::template FaceAttributeHandler ahf = map.template add_attribute("floats"); // get attribute and change type (dangerous!) - typename MAP::template VertexAttributeHandler ahf2 = map.template get_attribute_force_type("floats"); + typename MAP::template VertexAttributeHandler ahf2 = map.template get_attribute_force_type("floats"); map.remove_attribute(ahf); std::cout << "ahf valid : " << std::boolalpha << ahf.is_valid() << std::endl; @@ -114,7 +114,7 @@ int test1(MAP& map) // get ChunkArrayContainer -> get ChunkArray -> fill // typename MAP::template ChunkArrayContainer& container = map.get_attribute_container(MAP::Vertex); -// typename MAP::template ChunkArray* att = container.template get_attribute("floats"); +// typename MAP::template ChunkArray* att = container.template get_attribute("floats"); // for (uint32 i = 0; i < 10; ++i) // container.template insert_lines<1>(); for (auto& v : ah) @@ -127,7 +127,7 @@ int test1(MAP& map) fonc_const(ah); // // traverse container with for range - // for (float f:ah) + // for (float32 f:ah) // std::cout << f << std::endl; return 0; diff --git a/cgogn/core/utils/definitions.h b/cgogn/core/utils/definitions.h index 146d9347..32648bc8 100644 --- a/cgogn/core/utils/definitions.h +++ b/cgogn/core/utils/definitions.h @@ -43,6 +43,9 @@ using uint16 = std::uint16_t; using uint32 = std::uint32_t; using uint64 = std::uint64_t; +using float32 = float; +using float64 = double; + } using namespace numerics; diff --git a/cgogn/core/utils/endian.h b/cgogn/core/utils/endian.h index 7ab308ee..2b4c4a81 100644 --- a/cgogn/core/utils/endian.h +++ b/cgogn/core/utils/endian.h @@ -93,24 +93,24 @@ inline std::int64_t swap_endianness64(std::int64_t x) (step16 & 0xFF00FF00FF00FF00ULL) >> 8); } -inline float swap_endianness_float(float x) +inline float32 swap_endianness_float(float32 x) { union U32F32 { std::uint32_t as_u32; - float as_f32; + float32 as_f32; } u; u.as_f32 = x; u.as_u32 = swap_endianness32u(u.as_u32); return u.as_f32; } -inline double swap_endianness_double(double x) +inline float64 swap_endianness_double(float64 x) { union U64F64 { std::uint64_t as_u64; - double as_f64; + float64 as_f64; } u; u.as_f64 = x; u.as_u64 = swap_endianness64u(u.as_u64); @@ -185,7 +185,7 @@ inline std::int64_t swap_endianness_if(std::int64_t x) } template< bool COND> -inline float swap_endianness_if(float x) +inline float32 swap_endianness_if(float32 x) { if (COND) return swap_endianness_float(x); @@ -193,7 +193,7 @@ inline float swap_endianness_if(float x) } template< bool COND> -inline double swap_endianness_if(double x) +inline float64 swap_endianness_if(float64 x) { if (COND) return swap_endianness_double(x); diff --git a/cgogn/geometry/types/bounding_box.cpp b/cgogn/geometry/types/bounding_box.cpp index e7392540..c7e19fb5 100644 --- a/cgogn/geometry/types/bounding_box.cpp +++ b/cgogn/geometry/types/bounding_box.cpp @@ -34,8 +34,8 @@ namespace geometry template class CGOGN_GEOMETRY_API BoundingBox; template class CGOGN_GEOMETRY_API BoundingBox; -template class CGOGN_GEOMETRY_API BoundingBox>>; -template class CGOGN_GEOMETRY_API BoundingBox>>; +template class CGOGN_GEOMETRY_API BoundingBox>>; +template class CGOGN_GEOMETRY_API BoundingBox>>; } // namespace geometry diff --git a/cgogn/geometry/types/bounding_box.h b/cgogn/geometry/types/bounding_box.h index 3acd0d2e..a5805214 100644 --- a/cgogn/geometry/types/bounding_box.h +++ b/cgogn/geometry/types/bounding_box.h @@ -313,8 +313,8 @@ std::istream& operator>>(std::istream& in, BoundingBox& bb) #if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(GEOMETRY_BOUNDING_BOX_CPP_)) //extern template class CGOGN_GEOMETRY_API BoundingBox; //extern template class CGOGN_GEOMETRY_API BoundingBox; -extern template class CGOGN_GEOMETRY_API BoundingBox>>; -extern template class CGOGN_GEOMETRY_API BoundingBox>>; +extern template class CGOGN_GEOMETRY_API BoundingBox>>; +extern template class CGOGN_GEOMETRY_API BoundingBox>>; #endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(GEOMETRY_BOUNDING_BOX_CPP_)) } // namespace geometry diff --git a/cgogn/geometry/types/geometry_traits.h b/cgogn/geometry/types/geometry_traits.h index fd4dee3f..0e3762f5 100644 --- a/cgogn/geometry/types/geometry_traits.h +++ b/cgogn/geometry/types/geometry_traits.h @@ -59,18 +59,18 @@ struct vector_traits> // specialization 3 & 4: is for uniform manip of vec & scalar (vbo) // specialization 3 : float template<> -struct vector_traits +struct vector_traits { static const std::size_t SIZE = 1; - using Scalar = float; + using Scalar = float32; }; // specialization 4 : double template<> -struct vector_traits +struct vector_traits { static const std::size_t SIZE = 1; - using Scalar = double; + using Scalar = float64; }; template diff --git a/cgogn/geometry/types/plane_3d.cpp b/cgogn/geometry/types/plane_3d.cpp index 173fb062..b7aecd53 100644 --- a/cgogn/geometry/types/plane_3d.cpp +++ b/cgogn/geometry/types/plane_3d.cpp @@ -34,8 +34,8 @@ namespace geometry template class CGOGN_GEOMETRY_API Plane3D; template class CGOGN_GEOMETRY_API Plane3D; -template class CGOGN_GEOMETRY_API Plane3D>>; -template class CGOGN_GEOMETRY_API Plane3D>>; +template class CGOGN_GEOMETRY_API Plane3D>>; +template class CGOGN_GEOMETRY_API Plane3D>>; } // namespace geometry diff --git a/cgogn/geometry/types/plane_3d.h b/cgogn/geometry/types/plane_3d.h index 10e7c873..1682b184 100644 --- a/cgogn/geometry/types/plane_3d.h +++ b/cgogn/geometry/types/plane_3d.h @@ -141,8 +141,8 @@ class Plane3D #if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(GEOMETRY_TYPES_PLANE_3D_CPP_)) extern template class CGOGN_GEOMETRY_API Plane3D; extern template class CGOGN_GEOMETRY_API Plane3D; -extern template class CGOGN_GEOMETRY_API Plane3D>>; -extern template class CGOGN_GEOMETRY_API Plane3D>>; +extern template class CGOGN_GEOMETRY_API Plane3D>>; +extern template class CGOGN_GEOMETRY_API Plane3D>>; #endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(GEOMETRY_TYPES_PLANE_3D_CPP_)) } // namespace geometry diff --git a/cgogn/geometry/types/vec.cpp b/cgogn/geometry/types/vec.cpp index feabe26d..b0c36a13 100644 --- a/cgogn/geometry/types/vec.cpp +++ b/cgogn/geometry/types/vec.cpp @@ -32,8 +32,8 @@ namespace cgogn namespace geometry { -template class CGOGN_GEOMETRY_API Vec_T>; -template class CGOGN_GEOMETRY_API Vec_T>; +template class CGOGN_GEOMETRY_API Vec_T>; +template class CGOGN_GEOMETRY_API Vec_T>; } // namespace geometry diff --git a/cgogn/geometry/types/vec.h b/cgogn/geometry/types/vec.h index 1e474a32..1dee8481 100644 --- a/cgogn/geometry/types/vec.h +++ b/cgogn/geometry/types/vec.h @@ -266,8 +266,8 @@ class Vec_T }; #if defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(GEOMETRY_TYPES_VEC_CPP_)) -extern template class CGOGN_GEOMETRY_API Vec_T>; -extern template class CGOGN_GEOMETRY_API Vec_T>; +extern template class CGOGN_GEOMETRY_API Vec_T>; +extern template class CGOGN_GEOMETRY_API Vec_T>; #endif // defined(CGOGN_USE_EXTERNAL_TEMPLATES) && (!defined(GEOMETRY_TYPES_VEC_CPP_)) } // namespace geometry diff --git a/cgogn/io/data_io.h b/cgogn/io/data_io.h index d5c45687..7971df67 100644 --- a/cgogn/io/data_io.h +++ b/cgogn/io/data_io.h @@ -273,8 +273,8 @@ std::unique_ptr> DataInputGen::newDataIO(co { const DataType type = get_data_type(type_name); switch (type) { - case DataType::FLOAT: return make_unique>(); - case DataType::DOUBLE: return make_unique>(); + case DataType::FLOAT: return make_unique>(); + case DataType::DOUBLE: return make_unique>(); case DataType::CHAR: return make_unique>(); case DataType::INT8: return make_unique>(); case DataType::UINT8: return make_unique>(); @@ -296,8 +296,8 @@ std::unique_ptr> DataInputGen::newDataIO(co { const DataType type = get_data_type(type_name); switch (type) { - case DataType::FLOAT: return make_unique>(); - case DataType::DOUBLE: return make_unique>(); + case DataType::FLOAT: return make_unique>(); + case DataType::DOUBLE: return make_unique>(); case DataType::CHAR: return make_unique>(); case DataType::INT8: return make_unique>(); case DataType::UINT8: return make_unique>(); @@ -331,7 +331,7 @@ std::unique_ptr> DataInputGen::newDataIO(co default:break; } } else { - if (type_name == name_of_type(float())) + if (type_name == name_of_type(float32())) { switch (nb_components) { @@ -341,7 +341,7 @@ std::unique_ptr> DataInputGen::newDataIO(co default:break; } } else { - if (type_name == name_of_type(double())) + if (type_name == name_of_type(float64())) { switch (nb_components) { @@ -376,7 +376,7 @@ std::unique_ptr> DataInputGen::newDataIO(co default:break; } } else { - if (type_name == name_of_type(float())) + if (type_name == name_of_type(float32())) { switch (nb_components) { @@ -386,7 +386,7 @@ std::unique_ptr> DataInputGen::newDataIO(co default:break; } } else { - if (type_name == name_of_type(double())) + if (type_name == name_of_type(float64())) { switch (nb_components) { diff --git a/cgogn/io/examples/cmap2_import.cpp b/cgogn/io/examples/cmap2_import.cpp index dcc3e817..af6e22ca 100644 --- a/cgogn/io/examples/cmap2_import.cpp +++ b/cgogn/io/examples/cmap2_import.cpp @@ -19,7 +19,7 @@ struct MyMapTraits : public cgogn::DefaultMapTraits using Map2 = cgogn::CMap2; using Vec3 = Eigen::Vector3d; -//using Vec3 = cgogn::geometry::Vec_T>; +//using Vec3 = cgogn::geometry::Vec_T>; template using VertexAttributeHandler = Map2::VertexAttributeHandler; @@ -133,7 +133,7 @@ int main(int argc, char** argv) } end = std::chrono::system_clock::now(); - std::chrono::duration elapsed_seconds = end - start; + std::chrono::duration elapsed_seconds = end - start; std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n"; } diff --git a/cgogn/io/examples/cmap3_import.cpp b/cgogn/io/examples/cmap3_import.cpp index 4661f1a8..52da6758 100644 --- a/cgogn/io/examples/cmap3_import.cpp +++ b/cgogn/io/examples/cmap3_import.cpp @@ -13,7 +13,7 @@ using namespace cgogn::numerics; using Map3 = cgogn::CMap3; using Vec3 = Eigen::Vector3d; -//using Vec3 = cgogn::geometry::Vec_T>; +//using Vec3 = cgogn::geometry::Vec_T>; template using VertexAttributeHandler = Map3::VertexAttributeHandler; @@ -86,7 +86,7 @@ int main(int argc, char** argv) std::cout << "nb volumes -> " << nbw << std::endl; end = std::chrono::system_clock::now(); - std::chrono::duration elapsed_seconds = end - start; + std::chrono::duration elapsed_seconds = end - start; std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n"; } diff --git a/cgogn/io/import_ply_data.h b/cgogn/io/import_ply_data.h index 3defe9bc..4454e73c 100644 --- a/cgogn/io/import_ply_data.h +++ b/cgogn/io/import_ply_data.h @@ -94,10 +94,10 @@ class CGOGN_IO_API PlyImportData /* vertex and face definitions for a polygonal object */ typedef struct VertexPly { - float x,y,z; - float r,g,b; + float32 x,y,z; + float32 r,g,b; unsigned char red,green,blue; - float nx,ny,nz; + float32 nx,ny,nz; void *other_props; /* other properties */ } VertexPly; diff --git a/cgogn/io/io_utils.cpp b/cgogn/io/io_utils.cpp index 6632d359..4775cff0 100644 --- a/cgogn/io/io_utils.cpp +++ b/cgogn/io/io_utils.cpp @@ -227,9 +227,9 @@ CGOGN_IO_API FileType get_file_type(const std::string& filename) CGOGN_IO_API DataType get_data_type(const std::string& type_name) { - if (type_name == name_of_type(float())) + if (type_name == name_of_type(float32())) return DataType::FLOAT; - else if (type_name == name_of_type(double())) + else if (type_name == name_of_type(float64())) return DataType::DOUBLE; else if (type_name == name_of_type(char())) return DataType::CHAR; diff --git a/cgogn/io/lm6_io.h b/cgogn/io/lm6_io.h index 464bf8ee..87830a70 100644 --- a/cgogn/io/lm6_io.h +++ b/cgogn/io/lm6_io.h @@ -86,7 +86,7 @@ class LM6VolumeImport : public VolumeImport for (int i = 0 ; i < number_of_vertices; ++i) { uint32 idx = this->vertex_attributes_.template insert_lines<1>(); - std::array v; + std::array v; (void) GmfGetLin(mesh_index, GmfVertices, &v[0],&v[1], &v[2], &ref); position->operator [](idx)[0] = v[0]; position->operator [](idx)[1] = v[1]; diff --git a/cgogn/io/map_export.h b/cgogn/io/map_export.h index 7eb2f2e0..38d3de1a 100644 --- a/cgogn/io/map_export.h +++ b/cgogn/io/map_export.h @@ -154,7 +154,7 @@ bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandle static const uint32 BUFFER_SZ = 1024*1024; - std::vector buffer_pos; + std::vector buffer_pos; buffer_pos.reserve(BUFFER_SZ+3); map.template foreach_cell([&] (Face f) @@ -166,7 +166,7 @@ bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandle ids[v] = count++; VEC3 P = position[v]; // VEC3 can be double ! - float Pf[3]={float(P[0]),float(P[1]),float(P[2])}; + float32 Pf[3]={float32(P[0]),float32(P[1]),float32(P[2])}; uint32* ui_vec = reinterpret_cast(Pf); ui_vec[0] = swap_endianness_native_big(ui_vec[0]); ui_vec[1] = swap_endianness_native_big(ui_vec[1]); @@ -178,7 +178,7 @@ bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandle if (buffer_pos.size() >= BUFFER_SZ) { - fp.write(reinterpret_cast(&(buffer_pos[0])),buffer_pos.size()*sizeof(float)); + fp.write(reinterpret_cast(&(buffer_pos[0])),buffer_pos.size()*sizeof(float32)); buffer_pos.clear(); } } @@ -186,7 +186,7 @@ bool export_off_bin(MAP& map, const typename MAP::template VertexAttributeHandle }); if (!buffer_pos.empty()) { - fp.write(reinterpret_cast(&(buffer_pos[0])),buffer_pos.size()*sizeof(float)); + fp.write(reinterpret_cast(&(buffer_pos[0])),buffer_pos.size()*sizeof(float32)); buffer_pos.clear(); buffer_pos.shrink_to_fit(); } @@ -465,7 +465,7 @@ bool export_stl_bin(MAP& map, const typename MAP::template VertexAttributeHandle fp.write(reinterpret_cast(header),21*sizeof(uint32)); // buffer - std::array buffer_floats; // +1 for #@! ushort at end of each triangle + std::array buffer_floats; // +1 for #@! ushort at end of each triangle buffer_floats[12] = 0.0f; // local function for writing a triangle @@ -474,14 +474,14 @@ bool export_stl_bin(MAP& map, const typename MAP::template VertexAttributeHandle VEC3 N = geometry::triangle_normal(A,B,C); uint32 i=0; for (uint32 j=0; j<3; ++j) - buffer_floats[i++]= float(N[j]); + buffer_floats[i++]= float32(N[j]); for (uint32 j=0; j<3; ++j) - buffer_floats[i++]= float(A[j]); + buffer_floats[i++]= float32(A[j]); for (uint32 j=0; j<3; ++j) - buffer_floats[i++]= float(B[j]); + buffer_floats[i++]= float32(B[j]); for (uint32 j=0; j<3; ++j) - buffer_floats[i++]= float(C[j]); - fp.write(reinterpret_cast(buffer_floats.data()),12*sizeof(float)+2); // +2 for #@! ushort at end of each triangle + buffer_floats[i++]= float32(C[j]); + fp.write(reinterpret_cast(buffer_floats.data()),12*sizeof(float32)+2); // +2 for #@! ushort at end of each triangle }; // indices for ear triangulation @@ -543,8 +543,8 @@ template <> inline std::string nameOfTypePly(const int&) { return "int"; } template <> inline std::string nameOfTypePly(const uint32&) { return "uint"; } template <> inline std::string nameOfTypePly(const unsigned char&) { return "uint8"; } template <> inline std::string nameOfTypePly(const unsigned short int&) { return "uint16"; } -template <> inline std::string nameOfTypePly(const float&) { return "float"; } -template <> inline std::string nameOfTypePly(const double&) { return "float64"; } +template <> inline std::string nameOfTypePly(const float32&) { return "float32"; } +template <> inline std::string nameOfTypePly(const float64&) { return "float64"; } template bool export_ply(MAP& map, const typename MAP::template VertexAttributeHandler& position, const std::string& filename) diff --git a/cgogn/io/mesh_generation/examples/map3_from_surface.cpp b/cgogn/io/mesh_generation/examples/map3_from_surface.cpp index ffb0fd35..9e6d9779 100644 --- a/cgogn/io/mesh_generation/examples/map3_from_surface.cpp +++ b/cgogn/io/mesh_generation/examples/map3_from_surface.cpp @@ -117,7 +117,7 @@ int main(int argc, char** argv) std::cout << "nb volumes -> " << nbw << std::endl; end = std::chrono::system_clock::now(); - std::chrono::duration elapsed_seconds = end - start; + std::chrono::duration elapsed_seconds = end - start; std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n"; diff --git a/cgogn/io/mesh_generation/tetgen_io.h b/cgogn/io/mesh_generation/tetgen_io.h index a3abd272..e70c4627 100644 --- a/cgogn/io/mesh_generation/tetgen_io.h +++ b/cgogn/io/mesh_generation/tetgen_io.h @@ -152,7 +152,7 @@ // // // //create vertices -// double* p = volume_->pointlist ; +// float64* p = volume_->pointlist ; // std::vector verticesID; // verticesID.reserve(volume_->numberofpoints); // AttributeContainer& container = map3.template getAttributeContainer() ; @@ -315,7 +315,7 @@ class TetgenVolumeImport : public VolumeImport //create vertices std::vector vertices_indices; - double* p = volume_->pointlist ; + float64* p = volume_->pointlist ; vertices_indices.reserve(this->nb_vertices_); for(uint32 i = 0u; i < this->nb_vertices_; ++i) diff --git a/cgogn/io/obj_io.h b/cgogn/io/obj_io.h index 973c3fc8..dd87ac4d 100644 --- a/cgogn/io/obj_io.h +++ b/cgogn/io/obj_io.h @@ -68,7 +68,7 @@ class ObjSurfaceImport : public SurfaceImport { { std::stringstream oss(line); - double x, y, z; + float64 x, y, z; oss >> x; oss >> y; oss >> z; diff --git a/cgogn/io/off_io.h b/cgogn/io/off_io.h index 25771319..2f251ab9 100644 --- a/cgogn/io/off_io.h +++ b/cgogn/io/off_io.h @@ -80,9 +80,9 @@ class OffSurfaceImport : public SurfaceImport { for (uint32 i = 0; i < this->nb_vertices_; ++i) { - double x = this->read_double(fp,line); - double y = this->read_double(fp,line); - double z = this->read_double(fp,line); + float64 x = this->read_double(fp,line); + float64 y = this->read_double(fp,line); + float64 z = this->read_double(fp,line); VEC3 pos{Scalar(x), Scalar(y), Scalar(z)}; @@ -124,7 +124,7 @@ class OffSurfaceImport : public SurfaceImport { static const uint32 BUFFER_SZ = 1024*1024; - float* buff_pos = new float[3*BUFFER_SZ]; + float32* buff_pos = new float32[3*BUFFER_SZ]; std::vector vertices_id; vertices_id.reserve(this->nb_vertices_); @@ -137,9 +137,9 @@ class OffSurfaceImport : public SurfaceImport { j = 0; // read from file into buffer if (i + BUFFER_SZ < this->nb_vertices_) - fp.read(reinterpret_cast(buff_pos), 3 * sizeof(float)*BUFFER_SZ); + fp.read(reinterpret_cast(buff_pos), 3 * sizeof(float32)*BUFFER_SZ); else - fp.read(reinterpret_cast(buff_pos), 3 * sizeof(float)*(this->nb_vertices_ - i)); + fp.read(reinterpret_cast(buff_pos), 3 * sizeof(float32)*(this->nb_vertices_ - i)); //endian uint32* ptr = reinterpret_cast(buff_pos); @@ -213,7 +213,7 @@ class OffSurfaceImport : public SurfaceImport { return true; } private: - static inline double read_double(std::istream& fp, std::string& line) + static inline float64 read_double(std::istream& fp, std::string& line) { fp >> line; while (line[0]=='#') diff --git a/cgogn/io/vtk_io.h b/cgogn/io/vtk_io.h index c26862e3..81d668ce 100644 --- a/cgogn/io/vtk_io.h +++ b/cgogn/io/vtk_io.h @@ -588,9 +588,9 @@ protected : if (data_type == "unsigned_long" || data_type == "uint64") return name_of_type(std::uint64_t()); if (data_type == "float" || data_type == "float32") - return name_of_type(float()); + return name_of_type(float32()); if (data_type == "double" || data_type == "float64") - return name_of_type(double()); + return name_of_type(float64()); std::cerr << "vtk_data_type_to_cgogn_name_of_type : unknown vtk type : " << vtk_type_str << std::endl; return std::string(); diff --git a/cgogn/rendering/drawer.cpp b/cgogn/rendering/drawer.cpp index 5ce0d2bd..8c0ce27c 100644 --- a/cgogn/rendering/drawer.cpp +++ b/cgogn/rendering/drawer.cpp @@ -160,7 +160,7 @@ void Drawer::end() } -void Drawer::vertex3f(float x, float y, float z) +void Drawer::vertex3f(float32 x, float32 y, float32 z) { if (data_pos_.size() == data_col_.size()) { @@ -173,7 +173,7 @@ void Drawer::vertex3f(float x, float y, float z) } -void Drawer::color3f(float r, float g, float b) +void Drawer::color3f(float32 r, float32 g, float32 b) { if (data_pos_.size() == data_col_.size()) data_col_.push_back(Vec3f{r,g,b}); @@ -190,7 +190,7 @@ void Drawer::end_list() return; vbo_pos_->allocate(nb_elts,3); - float* ptr = vbo_pos_->lock_pointer(); + float32* ptr = vbo_pos_->lock_pointer(); std::memcpy(ptr,data_pos_[0].data(),nb_elts*12); vbo_pos_->release_pointer(); diff --git a/cgogn/rendering/drawer.h b/cgogn/rendering/drawer.h index 50ddf2f3..99b57363 100644 --- a/cgogn/rendering/drawer.h +++ b/cgogn/rendering/drawer.h @@ -47,13 +47,13 @@ class CGOGN_RENDERING_API Drawer { uint32 begin; GLenum mode; - float width; + float32 width; uint32 nb; bool aa; - PrimParam(std::size_t b, GLenum m, float w, bool a) : begin(uint32(b)), mode(m), width(w), nb(0), aa(a){} + PrimParam(std::size_t b, GLenum m, float32 w, bool a) : begin(uint32(b)), mode(m), width(w), nb(0), aa(a){} }; - using Vec3f = std::array; + using Vec3f = std::array; protected: @@ -83,7 +83,7 @@ class CGOGN_RENDERING_API Drawer uint32 vao_rp_; uint32 vao_ps_; - float current_size_; + float32 current_size_; bool current_aa_; bool current_ball_; @@ -128,20 +128,20 @@ class CGOGN_RENDERING_API Drawer /** * use as glVertex3f */ - void vertex3f(float x, float y, float z); + void vertex3f(float32 x, float32 y, float32 z); /** * use as glColor3f */ - void color3f(float r, float g, float b); + void color3f(float32 r, float32 g, float32 b); - inline void vertex3fv(const std::array& xyz) + inline void vertex3fv(const std::array& xyz) { vertex3f(xyz[0],xyz[1],xyz[2]); } - inline void color3fv(const std::array& rgb) + inline void color3fv(const std::array& rgb) { color3f(rgb[0],rgb[1],rgb[2]); } @@ -149,25 +149,25 @@ class CGOGN_RENDERING_API Drawer template inline void vertex3fv(SCAL* xyz) { - vertex3f(float(xyz[0]),float(xyz[1]),float(xyz[2])); + vertex3f(float32(xyz[0]),float32(xyz[1]),float32(xyz[2])); } template inline void color3fv(SCAL* rgb) { - color3f(float(rgb[0]),float(rgb[1]),float(rgb[2])); + color3f(float32(rgb[0]),float32(rgb[1]),float32(rgb[2])); } template inline void vertex3fv(const VEC3& xyz) { - vertex3f(float(xyz[0]),float(xyz[1]),float(xyz[2])); + vertex3f(float32(xyz[0]),float32(xyz[1]),float32(xyz[2])); } template inline void color3fv(const VEC3& rgb) { - color3f(float(rgb[0]),float(rgb[1]),float(rgb[2])); + color3f(float32(rgb[0]),float32(rgb[1]),float32(rgb[2])); } @@ -181,21 +181,21 @@ class CGOGN_RENDERING_API Drawer /** * usr as glPointSize */ - inline void point_size(float ps) + inline void point_size(float32 ps) { current_aa_ = false; current_size_ = ps; current_ball_ = false; } - inline void point_size_aa(float ps) + inline void point_size_aa(float32 ps) { current_aa_ = true; current_size_ = ps; current_ball_ = false; } - inline void ball_size(float ps) + inline void ball_size(float32 ps) { current_ball_ = true; current_aa_ = false; @@ -206,13 +206,13 @@ class CGOGN_RENDERING_API Drawer /** * usr as glLineWidth */ - inline void line_width(float lw) + inline void line_width(float32 lw) { current_aa_ = false; current_size_ = lw; } - inline void line_width_aa(float lw) + inline void line_width_aa(float32 lw) { current_aa_ = true; current_size_ = 2.0*lw; diff --git a/cgogn/rendering/examples/picking_viewer.cpp b/cgogn/rendering/examples/picking_viewer.cpp index d6690ba2..f7e94b72 100644 --- a/cgogn/rendering/examples/picking_viewer.cpp +++ b/cgogn/rendering/examples/picking_viewer.cpp @@ -48,7 +48,7 @@ using namespace cgogn::numerics; using Map2 = cgogn::CMap2; //using Vec3 = Eigen::Vector3d; -using Vec3 = cgogn::geometry::Vec_T>; +using Vec3 = cgogn::geometry::Vec_T>; template using VertexAttributeHandler = Map2::VertexAttributeHandler; diff --git a/cgogn/rendering/examples/viewer_per_face.cpp b/cgogn/rendering/examples/viewer_per_face.cpp index 2702eda7..88579dd5 100644 --- a/cgogn/rendering/examples/viewer_per_face.cpp +++ b/cgogn/rendering/examples/viewer_per_face.cpp @@ -48,7 +48,7 @@ using namespace cgogn::numerics; using Map2 = cgogn::CMap2; using Vec3 = Eigen::Vector3d; -//using Vec3 = cgogn::geometry::Vec_T>; +//using Vec3 = cgogn::geometry::Vec_T>; template using VertexAttributeHandler = Map2::VertexAttributeHandler; @@ -205,21 +205,21 @@ void Viewer::init() cgogn::rendering::create_indices_vertices_faces(map_,vertex_position_,ind_v,ind_f); // generate VBO: positions - cgogn::rendering::generate_vbo(vertex_position_, ind_v, *vbo_pos_, [] (const Vec3& v) -> std::array + cgogn::rendering::generate_vbo(vertex_position_, ind_v, *vbo_pos_, [] (const Vec3& v) -> std::array { - return {float(v[0]), float(v[1]), float(v[2])}; + return {float32(v[0]), float32(v[1]), float32(v[2])}; }); // generate VBO: normals - cgogn::rendering::generate_vbo(face_normal_, ind_f, *vbo_norm_, [] (const Vec3& n) -> std::array + cgogn::rendering::generate_vbo(face_normal_, ind_f, *vbo_norm_, [] (const Vec3& n) -> std::array { - return {float(n[0]), float(n[1]), float(n[2])}; + return {float32(n[0]), float32(n[1]), float32(n[2])}; }); // generate VBO: colors (here abs of normals) - cgogn::rendering::generate_vbo(face_normal_, ind_f, *vbo_color_, [] (const Vec3& n) -> std::array + cgogn::rendering::generate_vbo(face_normal_, ind_f, *vbo_color_, [] (const Vec3& n) -> std::array { - return {float(std::abs(n[0])), float(std::abs(n[1])), float(std::abs(n[2]))}; + return {float32(std::abs(n[0])), float32(std::abs(n[1])), float32(std::abs(n[2]))}; }); diff --git a/cgogn/rendering/examples/viewer_topo.cpp b/cgogn/rendering/examples/viewer_topo.cpp index ab9078e0..219c63d8 100644 --- a/cgogn/rendering/examples/viewer_topo.cpp +++ b/cgogn/rendering/examples/viewer_topo.cpp @@ -45,7 +45,7 @@ using Map2 = cgogn::CMap2; using Vec3 = Eigen::Vector3d; -//using Vec3 = cgogn::geometry::Vec_T>; +//using Vec3 = cgogn::geometry::Vec_T>; template using VertexAttributeHandler = Map2::VertexAttributeHandler; diff --git a/cgogn/rendering/examples/viewer_topo3.cpp b/cgogn/rendering/examples/viewer_topo3.cpp index ccf0935a..eac8a960 100644 --- a/cgogn/rendering/examples/viewer_topo3.cpp +++ b/cgogn/rendering/examples/viewer_topo3.cpp @@ -44,7 +44,7 @@ using namespace cgogn::numerics; using Map3 = cgogn::CMap3; using Vec3 = Eigen::Vector3d; -//using Vec3 = cgogn::geometry::Vec_T>; +//using Vec3 = cgogn::geometry::Vec_T>; template using VertexAttributeHandler = Map3::VertexAttributeHandler; @@ -85,7 +85,7 @@ class Viewer : public QOGLViewer bool edge_rendering_; bool topo_rendering_; - float expl_; + float32 expl_; }; diff --git a/cgogn/rendering/shaders/shader_bold_line.cpp b/cgogn/rendering/shaders/shader_bold_line.cpp index a96f2d90..9cc9881b 100644 --- a/cgogn/rendering/shaders/shader_bold_line.cpp +++ b/cgogn/rendering/shaders/shader_bold_line.cpp @@ -215,12 +215,12 @@ void ShaderBoldLine::set_color(const QColor& rgb) prg_.setUniformValue(unif_color_, rgb); } -void ShaderBoldLine::set_width(float wpix) +void ShaderBoldLine::set_width(float32 wpix) { QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); GLint viewport[4]; ogl->glGetIntegerv(GL_VIEWPORT, viewport); - QSizeF wd(wpix / float(viewport[2]), wpix / float(viewport[3])); + QSizeF wd(wpix / float32(viewport[2]), wpix / float32(viewport[3])); prg_.setUniformValue(unif_width_, wd); } diff --git a/cgogn/rendering/shaders/shader_bold_line.h b/cgogn/rendering/shaders/shader_bold_line.h index 72272756..6fc369b8 100644 --- a/cgogn/rendering/shaders/shader_bold_line.h +++ b/cgogn/rendering/shaders/shader_bold_line.h @@ -68,7 +68,7 @@ class CGOGN_RENDERING_API ShaderBoldLine : public ShaderProgram * @brief set the width of lines (call before each draw) * @param w width in pixel */ - void set_width(float w); + void set_width(float32 w); /** * @brief set a vao configuration diff --git a/cgogn/rendering/shaders/shader_explode_volumes.cpp b/cgogn/rendering/shaders/shader_explode_volumes.cpp index 9f5fe628..1abd49ed 100644 --- a/cgogn/rendering/shaders/shader_explode_volumes.cpp +++ b/cgogn/rendering/shaders/shader_explode_volumes.cpp @@ -183,7 +183,7 @@ void ShaderExplodeVolumes::set_light_position(const QVector3D& l) } -void ShaderExplodeVolumes::set_explode_volume(float x) +void ShaderExplodeVolumes::set_explode_volume(float32 x) { prg_.setUniformValue(unif_expl_v_, x); } diff --git a/cgogn/rendering/shaders/shader_explode_volumes.h b/cgogn/rendering/shaders/shader_explode_volumes.h index ccc42d49..cbb096cc 100644 --- a/cgogn/rendering/shaders/shader_explode_volumes.h +++ b/cgogn/rendering/shaders/shader_explode_volumes.h @@ -63,7 +63,7 @@ class CGOGN_RENDERING_API ShaderExplodeVolumes : public ShaderProgram ShaderExplodeVolumes(bool color_per_vertex = false); - void set_explode_volume(float x); + void set_explode_volume(float32 x); void set_light_position(const QVector3D& l); diff --git a/cgogn/rendering/shaders/shader_explode_volumes_line.cpp b/cgogn/rendering/shaders/shader_explode_volumes_line.cpp index d483ae09..460af741 100644 --- a/cgogn/rendering/shaders/shader_explode_volumes_line.cpp +++ b/cgogn/rendering/shaders/shader_explode_volumes_line.cpp @@ -101,7 +101,7 @@ void ShaderExplodeVolumesLine::set_color(const QColor& rgb) } -void ShaderExplodeVolumesLine::set_explode_volume(float x) +void ShaderExplodeVolumesLine::set_explode_volume(float32 x) { prg_.setUniformValue(unif_expl_v_, x); } diff --git a/cgogn/rendering/shaders/shader_explode_volumes_line.h b/cgogn/rendering/shaders/shader_explode_volumes_line.h index 3144c647..bc31708c 100644 --- a/cgogn/rendering/shaders/shader_explode_volumes_line.h +++ b/cgogn/rendering/shaders/shader_explode_volumes_line.h @@ -57,7 +57,7 @@ class CGOGN_RENDERING_API ShaderExplodeVolumesLine : public ShaderProgram ShaderExplodeVolumesLine(); - void set_explode_volume(float x); + void set_explode_volume(float32 x); void set_plane_clip(const QVector4D& plane); diff --git a/cgogn/rendering/shaders/shader_phong.cpp b/cgogn/rendering/shaders/shader_phong.cpp index 2e8e463d..5394d857 100644 --- a/cgogn/rendering/shaders/shader_phong.cpp +++ b/cgogn/rendering/shaders/shader_phong.cpp @@ -221,7 +221,7 @@ void ShaderPhong::set_specular_color(const QColor& rgb) prg_.setUniformValue(unif_spec_color_,rgb); } -void ShaderPhong::set_specular_coef(float coef) +void ShaderPhong::set_specular_coef(float32 coef) { prg_.setUniformValue(unif_spec_coef_,coef); } diff --git a/cgogn/rendering/shaders/shader_phong.h b/cgogn/rendering/shaders/shader_phong.h index bd934e48..363526ca 100644 --- a/cgogn/rendering/shaders/shader_phong.h +++ b/cgogn/rendering/shaders/shader_phong.h @@ -93,7 +93,7 @@ class CGOGN_RENDERING_API ShaderPhong : public ShaderProgram * @brief set current specular coefficient * @param rgb */ - void set_specular_coef(float coef); + void set_specular_coef(float32 coef); /** * @brief set double side option diff --git a/cgogn/rendering/shaders/shader_point_sprite.cpp b/cgogn/rendering/shaders/shader_point_sprite.cpp index 3d07f2dc..b6428d0a 100644 --- a/cgogn/rendering/shaders/shader_point_sprite.cpp +++ b/cgogn/rendering/shaders/shader_point_sprite.cpp @@ -335,7 +335,7 @@ void ShaderPointSprite::set_ambiant(const QColor& rgb) prg_.setUniformValue(unif_ambiant_, rgb); } -void ShaderPointSprite::set_size(float w) +void ShaderPointSprite::set_size(float32 w) { // if (unif_size_>=0) prg_.setUniformValue(unif_size_, w); diff --git a/cgogn/rendering/shaders/shader_point_sprite.h b/cgogn/rendering/shaders/shader_point_sprite.h index 560e53dc..84892539 100644 --- a/cgogn/rendering/shaders/shader_point_sprite.h +++ b/cgogn/rendering/shaders/shader_point_sprite.h @@ -92,7 +92,7 @@ class CGOGN_RENDERING_API ShaderPointSprite : public ShaderProgram * @brief set the size of sphere (call before each draw) * @param w size ofs phere */ - void set_size(float w); + void set_size(float32 w); /** * @brief set a vao configuration diff --git a/cgogn/rendering/shaders/shader_round_point.cpp b/cgogn/rendering/shaders/shader_round_point.cpp index 4140c110..4477f991 100644 --- a/cgogn/rendering/shaders/shader_round_point.cpp +++ b/cgogn/rendering/shaders/shader_round_point.cpp @@ -175,12 +175,12 @@ void ShaderRoundPoint::set_color(const QColor& rgb) prg_.setUniformValue(unif_color_, rgb); } -void ShaderRoundPoint::set_width(float wpix) +void ShaderRoundPoint::set_width(float32 wpix) { QOpenGLFunctions *ogl = QOpenGLContext::currentContext()->functions(); int viewport[4]; ogl->glGetIntegerv(GL_VIEWPORT, viewport); - QSizeF wd(wpix / float(viewport[2]), wpix / float(viewport[3])); + QSizeF wd(wpix / float32(viewport[2]), wpix / float32(viewport[3])); prg_.setUniformValue(unif_width_, wd); } diff --git a/cgogn/rendering/shaders/shader_round_point.h b/cgogn/rendering/shaders/shader_round_point.h index 2db4b0b3..73ed5f46 100644 --- a/cgogn/rendering/shaders/shader_round_point.h +++ b/cgogn/rendering/shaders/shader_round_point.h @@ -68,7 +68,7 @@ class CGOGN_RENDERING_API ShaderRoundPoint : public ShaderProgram * @brief set the width of lines (call before each draw) * @param w width in pixel */ - void set_width(float w); + void set_width(float32 w); /** * @brief set a vao configuration diff --git a/cgogn/rendering/shaders/shader_vector_per_vertex.cpp b/cgogn/rendering/shaders/shader_vector_per_vertex.cpp index eb190d5d..eaea209d 100644 --- a/cgogn/rendering/shaders/shader_vector_per_vertex.cpp +++ b/cgogn/rendering/shaders/shader_vector_per_vertex.cpp @@ -94,7 +94,7 @@ void ShaderVectorPerVertex::set_color(const QColor& rgb) prg_.setUniformValue(unif_color_, rgb); } -void ShaderVectorPerVertex::set_length(float l) +void ShaderVectorPerVertex::set_length(float32 l) { prg_.setUniformValue(unif_length_, l); } diff --git a/cgogn/rendering/shaders/shader_vector_per_vertex.h b/cgogn/rendering/shaders/shader_vector_per_vertex.h index 82dfd8c4..13dc0fdf 100644 --- a/cgogn/rendering/shaders/shader_vector_per_vertex.h +++ b/cgogn/rendering/shaders/shader_vector_per_vertex.h @@ -64,7 +64,7 @@ class CGOGN_RENDERING_API ShaderVectorPerVertex : public ShaderProgram * @brief set length of normal * @param l length */ - void set_length(float l); + void set_length(float32 l); /** * @brief set a vao configuration diff --git a/cgogn/rendering/shaders/vbo.h b/cgogn/rendering/shaders/vbo.h index c88bbdda..c63d343e 100644 --- a/cgogn/rendering/shaders/vbo.h +++ b/cgogn/rendering/shaders/vbo.h @@ -80,7 +80,7 @@ class VBO buffer_.bind(); uint32 total = nb_vectors * vector_dimension; if (total != nb_vectors_ * vector_dimension_) // only allocate when > ? - buffer_.allocate(total * sizeof(float)); + buffer_.allocate(total * sizeof(float32)); nb_vectors_ = nb_vectors; if (vector_dimension != vector_dimension_) { @@ -94,10 +94,10 @@ class VBO * @brief get and lock pointer on buffer memory * @return the pointer */ - inline float* lock_pointer() + inline float32* lock_pointer() { buffer_.bind(); - return reinterpret_cast(buffer_.map(QOpenGLBuffer::ReadWrite)); + return reinterpret_cast(buffer_.map(QOpenGLBuffer::ReadWrite)); } /** @@ -142,7 +142,7 @@ class VBO template void update_vbo(const ATTR& attr, VBO& vbo) { - static_assert(std::is_same::Scalar, float>::value || std::is_same::Scalar, double>::value, "only float or double allowed for vbo"); + static_assert(std::is_same::Scalar, float32>::value || std::is_same::Scalar, double>::value, "only float or double allowed for vbo"); const typename ATTR::TChunkArray* ca = attr.get_data(); @@ -153,9 +153,9 @@ void update_vbo(const ATTR& attr, VBO& vbo) vbo.allocate(nb_chunks * ATTR::CHUNKSIZE, vec_dim); - const uint32 vbo_blk_bytes = ATTR::CHUNKSIZE * vec_dim * sizeof(float); + const uint32 vbo_blk_bytes = ATTR::CHUNKSIZE * vec_dim * sizeof(float32); - if (std::is_same::Scalar, float>::value) + if (std::is_same::Scalar, float32>::value) { // copy vbo.bind(); @@ -163,19 +163,19 @@ void update_vbo(const ATTR& attr, VBO& vbo) vbo.copy_data(i* vbo_blk_bytes, vbo_blk_bytes, chunk_addr[i]); vbo.release(); } - else if (std::is_same::Scalar, double>::value) + else if (std::is_same::Scalar, float64>::value) { // copy (after conversion to float) - float* float_buffer = new float[ATTR::CHUNKSIZE * vec_dim]; + float32* float_buffer = new float32[ATTR::CHUNKSIZE * vec_dim]; for (uint32 i = 0; i < nb_chunks; ++i) { // transform double into float - float* fit = float_buffer; - double* src = reinterpret_cast(chunk_addr[i]); + float32* fit = float_buffer; + float64* src = reinterpret_cast(chunk_addr[i]); for (uint32 j = 0; j < ATTR::CHUNKSIZE * vec_dim; ++j) *fit++ = *src++; vbo.bind(); - vbo.copy_data(i* ATTR::CHUNKSIZE * vec_dim * sizeof(float), ATTR::CHUNKSIZE * vec_dim * sizeof(float),float_buffer); + vbo.copy_data(i* ATTR::CHUNKSIZE * vec_dim * sizeof(float32), ATTR::CHUNKSIZE * vec_dim * sizeof(float32),float_buffer); vbo.release(); } delete[] float_buffer; @@ -206,14 +206,14 @@ void update_vbo(const ATTR& attr, VBO& vbo, const FUNC& convert) uint32 nb_chunks = ca->get_chunks_pointers(chunk_addr, byte_chunk_size); // check that out of convert is float or std::array - using Vec2f = std::array; - using Vec3f = std::array; - using Vec4f = std::array; - static_assert(check_func_return_type(FUNC,float) || check_func_return_type(FUNC,Vec2f) || check_func_return_type(FUNC,Vec3f) ||check_func_return_type(FUNC,Vec4f), "convert output must be float or std::array" ); + using Vec2f = std::array; + using Vec3f = std::array; + using Vec4f = std::array; + static_assert(check_func_return_type(FUNC,float32) || check_func_return_type(FUNC,Vec2f) || check_func_return_type(FUNC,Vec3f) ||check_func_return_type(FUNC,Vec4f), "convert output must be float or std::array" ); // set vec dimension uint32 vec_dim = 0; - if (check_func_return_type(FUNC,float) ) + if (check_func_return_type(FUNC,float32) ) vec_dim = 1; else if (check_func_return_type(FUNC,Vec2f) ) vec_dim = 2; @@ -272,14 +272,14 @@ void update_vbo(const ATTR& attr, const ATTR2& attr2, VBO& vbo, const FUNC& conv ca2->get_chunks_pointers(chunk_addr2, byte_chunk_size); // check that out of convert is float or std::array - using Vec2f = std::array; - using Vec3f = std::array; - using Vec4f = std::array; - static_assert(check_func_return_type(FUNC,float) || check_func_return_type(FUNC,Vec2f) || check_func_return_type(FUNC,Vec3f) ||check_func_return_type(FUNC,Vec4f), "convert output must be float or std::array" ); + using Vec2f = std::array; + using Vec3f = std::array; + using Vec4f = std::array; + static_assert(check_func_return_type(FUNC,float32) || check_func_return_type(FUNC,Vec2f) || check_func_return_type(FUNC,Vec3f) ||check_func_return_type(FUNC,Vec4f), "convert output must be float or std::array" ); // set vec dimension uint32 vec_dim = 0; - if (check_func_return_type(FUNC,float) ) + if (check_func_return_type(FUNC,float32) ) vec_dim = 1; else if (check_func_return_type(FUNC,Vec2f) ) vec_dim = 2; @@ -325,14 +325,14 @@ void generate_vbo(const ATTR& attr, const std::vector& indices, VBO& vbo static_assert(std::is_same::value, "wrong parameter 1"); // check that out of convert is float or std::array - using Vec2f = std::array; - using Vec3f = std::array; - using Vec4f = std::array; - static_assert(check_func_return_type(FUNC,float) || check_func_return_type(FUNC,Vec2f) || check_func_return_type(FUNC,Vec3f) ||check_func_return_type(FUNC,Vec4f), "convert output must be float or std::array" ); + using Vec2f = std::array; + using Vec3f = std::array; + using Vec4f = std::array; + static_assert(check_func_return_type(FUNC,float32) || check_func_return_type(FUNC,Vec2f) || check_func_return_type(FUNC,Vec3f) ||check_func_return_type(FUNC,Vec4f), "convert output must be float or std::array" ); // set vec dimension uint32 vec_dim = 0; - if (check_func_return_type(FUNC,float) ) + if (check_func_return_type(FUNC,float32) ) vec_dim = 1; else if (check_func_return_type(FUNC,Vec2f) ) vec_dim = 2; diff --git a/cgogn/rendering/topo_render.h b/cgogn/rendering/topo_render.h index 6dd2be73..2c99ee18 100644 --- a/cgogn/rendering/topo_render.h +++ b/cgogn/rendering/topo_render.h @@ -43,7 +43,7 @@ namespace rendering class CGOGN_RENDERING_API TopoRender { - using Vec3f = std::array; + using Vec3f = std::array; protected: @@ -66,9 +66,9 @@ class CGOGN_RENDERING_API TopoRender QColor phi2_color_; QColor phi3_color_; - float shrink_v_; - float shrink_f_; - float shrink_e_; + float32 shrink_v_; + float32 shrink_f_; + float32 shrink_e_; public: @@ -83,9 +83,9 @@ class CGOGN_RENDERING_API TopoRender */ ~TopoRender(); - inline void set_explode_volume(float x) { shrink_v_ = x; } - inline void set_explode_face(float x) { shrink_f_ = x; } - inline void set_explode_edge(float x) { shrink_e_ = x; } + inline void set_explode_volume(float32 x) { shrink_v_ = x; } + inline void set_explode_face(float32 x) { shrink_f_ = x; } + inline void set_explode_edge(float32 x) { shrink_e_ = x; } template void update_map2(MAP& m, const typename MAP::template VertexAttributeHandler& position); @@ -107,10 +107,10 @@ void TopoRender::update_map2(MAP& m, const typename MAP::template VertexAttribut Scalar opp_shrink_e = 1.0 -shrink_e_; Scalar opp_shrink_f = 1.0 - shrink_f_; - std::vector> out_pos; + std::vector> out_pos; out_pos.reserve(1024*1024); - std::vector> out_pos2; + std::vector> out_pos2; out_pos2.reserve(1024*1024); @@ -150,13 +150,13 @@ void TopoRender::update_map2(MAP& m, const typename MAP::template VertexAttribut for (uint32 i=0; i> out_pos; + std::vector> out_pos; out_pos.reserve(1024*1024); - std::vector> out_pos2; + std::vector> out_pos2; out_pos2.reserve(1024*1024); - std::vector> out_pos3; + std::vector> out_pos3; out_pos3.reserve(1024*1024); @@ -241,17 +241,17 @@ void TopoRender::update_map3(MAP& m, const typename MAP::template VertexAttribut for (uint32 i=0; i; + using Vec3f = std::array; protected: @@ -64,8 +64,8 @@ class CGOGN_RENDERING_API VolumeRender QOpenGLFunctions_3_3_Core* ogl33_; - float shrink_v_; - float shrink_f_; + float32 shrink_v_; + float32 shrink_f_; void init_with_color(); @@ -86,9 +86,9 @@ class CGOGN_RENDERING_API VolumeRender */ ~VolumeRender(); - inline void set_explode_face(float x) { shrink_f_ = x; } + inline void set_explode_face(float32 x) { shrink_f_ = x; } - inline void set_explode_volume(float x) { shrink_v_ = x; } + inline void set_explode_volume(float32 x) { shrink_v_ = x; } inline void set_face_color(const QColor& rgb) { face_color_= rgb; } @@ -120,7 +120,7 @@ void VolumeRender::update_face(MAP& m, const typename MAP::template VertexAttrib using Volume = typename MAP::Volume; using Scalar = typename VEC3::Scalar; - std::vector> out_pos; + std::vector> out_pos; out_pos.reserve(1024*1024); std::vector ear_indices; @@ -136,10 +136,10 @@ void VolumeRender::update_face(MAP& m, const typename MAP::template VertexAttrib const VEC3& P1 = position[Vertex(f.dart)]; const VEC3& P2 = position[Vertex(m.phi1(f.dart))]; const VEC3& P3 = position[Vertex(m.phi1(m.phi1(f.dart)))]; - out_pos.push_back({float(CV[0]),float(CV[1]),float(CV[2])}); - out_pos.push_back({float(P1[0]),float(P1[1]),float(P1[2])}); - out_pos.push_back({float(P2[0]),float(P2[1]),float(P2[2])}); - out_pos.push_back({float(P3[0]),float(P3[1]),float(P3[2])}); + out_pos.push_back({float32(CV[0]),float32(CV[1]),float32(CV[2])}); + out_pos.push_back({float32(P1[0]),float32(P1[1]),float32(P1[2])}); + out_pos.push_back({float32(P2[0]),float32(P2[1]),float32(P2[2])}); + out_pos.push_back({float32(P3[0]),float32(P3[1]),float32(P3[2])}); } else { @@ -150,10 +150,10 @@ void VolumeRender::update_face(MAP& m, const typename MAP::template VertexAttrib const VEC3& P1 = position[ear_indices[i]]; const VEC3& P2 = position[ear_indices[i+1]]; const VEC3& P3 = position[ear_indices[i+2]]; - out_pos.push_back({float(CV[0]),float(CV[1]),float(CV[2])}); - out_pos.push_back({float(P1[0]),float(P1[1]),float(P1[2])}); - out_pos.push_back({float(P2[0]),float(P2[1]),float(P2[2])}); - out_pos.push_back({float(P3[0]),float(P3[1]),float(P3[2])}); + out_pos.push_back({float32(CV[0]),float32(CV[1]),float32(CV[2])}); + out_pos.push_back({float32(P1[0]),float32(P1[1]),float32(P1[2])}); + out_pos.push_back({float32(P2[0]),float32(P2[1]),float32(P2[2])}); + out_pos.push_back({float32(P3[0]),float32(P3[1]),float32(P3[2])}); } } }); @@ -178,10 +178,10 @@ void VolumeRender::update_face(MAP& m, const typename MAP::template VertexAttrib using Volume = typename MAP::Volume; using Scalar = typename VEC3::Scalar; - std::vector> out_pos; + std::vector> out_pos; out_pos.reserve(1024*1024); - std::vector> out_color; + std::vector> out_color; out_color.reserve(1024*1024); std::vector ear_indices; @@ -203,14 +203,14 @@ void VolumeRender::update_face(MAP& m, const typename MAP::template VertexAttrib d = m.phi1(d); const VEC3& P3 = position[Vertex(d)]; const VEC3& C3 = color[Vertex(d)]; - out_pos.push_back({float(CV[0]),float(CV[1]),float(CV[2])}); - out_pos.push_back({float(P1[0]),float(P1[1]),float(P1[2])}); - out_pos.push_back({float(P2[0]),float(P2[1]),float(P2[2])}); - out_pos.push_back({float(P3[0]),float(P3[1]),float(P3[2])}); - out_color.push_back({float(CV[0]),float(CV[1]),float(CV[2])}); - out_color.push_back({float(C1[0]),float(C1[1]),float(C1[2])}); - out_color.push_back({float(C2[0]),float(C2[1]),float(C2[2])}); - out_color.push_back({float(C3[0]),float(C3[1]),float(C3[2])}); + out_pos.push_back({float32(CV[0]),float32(CV[1]),float32(CV[2])}); + out_pos.push_back({float32(P1[0]),float32(P1[1]),float32(P1[2])}); + out_pos.push_back({float32(P2[0]),float32(P2[1]),float32(P2[2])}); + out_pos.push_back({float32(P3[0]),float32(P3[1]),float32(P3[2])}); + out_color.push_back({float32(CV[0]),float32(CV[1]),float32(CV[2])}); + out_color.push_back({float32(C1[0]),float32(C1[1]),float32(C1[2])}); + out_color.push_back({float32(C2[0]),float32(C2[1]),float32(C2[2])}); + out_color.push_back({float32(C3[0]),float32(C3[1]),float32(C3[2])}); } else { @@ -225,14 +225,14 @@ void VolumeRender::update_face(MAP& m, const typename MAP::template VertexAttrib const VEC3& C2 = color[ear_indices[i+1]]; const VEC3& P3 = position[ear_indices[i+2]]; const VEC3& C3 = color[ear_indices[i+2]]; - out_pos.push_back({float(CV[0]),float(CV[1]),float(CV[2])}); - out_pos.push_back({float(P1[0]),float(P1[1]),float(P1[2])}); - out_pos.push_back({float(P2[0]),float(P2[1]),float(P2[2])}); - out_pos.push_back({float(P3[0]),float(P3[1]),float(P3[2])}); - out_color.push_back({float(CV[0]),float(CV[1]),float(CV[2])}); - out_color.push_back({float(C1[0]),float(C1[1]),float(C1[2])}); - out_color.push_back({float(C2[0]),float(C2[1]),float(C2[2])}); - out_color.push_back({float(C3[0]),float(C3[1]),float(C3[2])}); + out_pos.push_back({float32(CV[0]),float32(CV[1]),float32(CV[2])}); + out_pos.push_back({float32(P1[0]),float32(P1[1]),float32(P1[2])}); + out_pos.push_back({float32(P2[0]),float32(P2[1]),float32(P2[2])}); + out_pos.push_back({float32(P3[0]),float32(P3[1]),float32(P3[2])}); + out_color.push_back({float32(CV[0]),float32(CV[1]),float32(CV[2])}); + out_color.push_back({float32(C1[0]),float32(C1[1]),float32(C1[2])}); + out_color.push_back({float32(C2[0]),float32(C2[1]),float32(C2[2])}); + out_color.push_back({float32(C3[0]),float32(C3[1]),float32(C3[2])}); } } }); @@ -263,7 +263,7 @@ void VolumeRender::update_edge(MAP& m, const typename MAP::template VertexAttrib using Volume = typename MAP::Volume; using Scalar = typename VEC3::Scalar; - std::vector> out_pos; + std::vector> out_pos; out_pos.reserve(1024*1024); std::vector ear_indices; @@ -276,9 +276,9 @@ void VolumeRender::update_edge(MAP& m, const typename MAP::template VertexAttrib { const VEC3& P1 = position[Vertex(e.dart)]; const VEC3& P2 = position[Vertex(m.phi1(e.dart))]; - out_pos.push_back({float(CV[0]),float(CV[1]),float(CV[2])}); - out_pos.push_back({float(P1[0]),float(P1[1]),float(P1[2])}); - out_pos.push_back({float(P2[0]),float(P2[1]),float(P2[2])}); + out_pos.push_back({float32(CV[0]),float32(CV[1]),float32(CV[2])}); + out_pos.push_back({float32(P1[0]),float32(P1[1]),float32(P1[2])}); + out_pos.push_back({float32(P2[0]),float32(P2[1]),float32(P2[2])}); }); });