// Copyright 2019 Blender Foundation. All rights reserved. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software Foundation, // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // Author: Sergey Sharybin #ifndef OPENSUBDIV_EDGE_MAP_H_ #define OPENSUBDIV_EDGE_MAP_H_ #include "internal/opensubdiv_util.h" namespace blender { namespace opensubdiv { // Helper class to ease dealing with edge indexing. // Simply takes care of ensuring order of vertices is strictly defined. class EdgeKey { public: inline EdgeKey(); inline EdgeKey(int v1, int v2); inline size_t hash() const; inline bool operator==(const EdgeKey &other) const; // These indices are guaranteed to be so v1 < v2. int v1; int v2; }; // Map from an edge defined by its vertices index to a custom tag value. template class EdgeTagMap { public: typedef EdgeKey key_type; typedef T value_type; inline EdgeTagMap(); // Modifiers. inline void clear(); inline void insert(const key_type &key, const value_type &value); inline void insert(int v1, int v2, const value_type &value); // Lookup. value_type &at(const key_type &key); value_type &at(key_type &&key); value_type &at(int v1, int v2); value_type &operator[](const key_type &key); value_type &operator[](key_type &&key); protected: unordered_map edge_tags_; }; //////////////////////////////////////////////////////////////////////////////// // Implementation. // EdgeKey. EdgeKey::EdgeKey() : v1(-1), v2(-1) { } EdgeKey::EdgeKey(int v1, int v2) { assert(v1 >= 0); assert(v2 >= 0); assert(v1 != v2); if (v1 < v2) { this->v1 = v1; this->v2 = v2; } else { this->v1 = v2; this->v2 = v1; } } size_t EdgeKey::hash() const { return (static_cast(v1) << 32) | v2; } bool EdgeKey::operator==(const EdgeKey &other) const { return v1 == other.v1 && v2 == other.v2; } // EdgeTagMap. template EdgeTagMap::EdgeTagMap() { } template void EdgeTagMap::clear() { edge_tags_.clear(); } template void EdgeTagMap::insert(const key_type &key, const value_type &value) { edge_tags_.insert(make_pair(key, value)); } template void EdgeTagMap::insert(int v1, int v2, const value_type &value) { insert(EdgeKey(v1, v2), value); } template typename EdgeTagMap::value_type &EdgeTagMap::at(const key_type &key) { return edge_tags_.at[key]; } template typename EdgeTagMap::value_type &EdgeTagMap::at(key_type &&key) { return edge_tags_.at[key]; } template typename EdgeTagMap::value_type &EdgeTagMap::at(int v1, int v2) { return edge_tags_.at(EdgeKey(v1, v2)); } template typename EdgeTagMap::value_type &EdgeTagMap::operator[](const key_type &key) { return edge_tags_[key]; } template typename EdgeTagMap::value_type &EdgeTagMap::operator[](key_type &&key) { return edge_tags_[key]; } } // namespace opensubdiv } // namespace blender namespace std { template<> struct hash { std::size_t operator()(const blender::opensubdiv::EdgeKey &key) const { return key.hash(); } }; } // namespace std #endif // OPENSUBDIV_EDGE_MAP_H_