diff options
Diffstat (limited to 'extern/draco/dracoenc/src/draco/mesh/corner_table_iterators.h')
-rw-r--r-- | extern/draco/dracoenc/src/draco/mesh/corner_table_iterators.h | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/extern/draco/dracoenc/src/draco/mesh/corner_table_iterators.h b/extern/draco/dracoenc/src/draco/mesh/corner_table_iterators.h new file mode 100644 index 00000000000..65869dbe109 --- /dev/null +++ b/extern/draco/dracoenc/src/draco/mesh/corner_table_iterators.h @@ -0,0 +1,281 @@ +// Copyright 2016 The Draco Authors. +// +// 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 DRACO_MESH_CORNER_TABLE_ITERATORS_H_ +#define DRACO_MESH_CORNER_TABLE_ITERATORS_H_ + +#include "draco/mesh/corner_table.h" + +namespace draco { + +// Class for iterating over vertices in a 1-ring around the specified vertex. +template <class CornerTableT> +class VertexRingIterator + : public std::iterator<std::forward_iterator_tag, VertexIndex> { + public: + // std::iterator interface requires a default constructor. + VertexRingIterator() + : corner_table_(nullptr), + start_corner_(kInvalidCornerIndex), + corner_(start_corner_), + left_traversal_(true) {} + + // Create the iterator from the provided corner table and the central vertex. + VertexRingIterator(const CornerTableT *table, VertexIndex vert_id) + : corner_table_(table), + start_corner_(table->LeftMostCorner(vert_id)), + corner_(start_corner_), + left_traversal_(true) {} + + // Gets the last visited ring vertex. + VertexIndex Vertex() const { + CornerIndex ring_corner = left_traversal_ ? corner_table_->Previous(corner_) + : corner_table_->Next(corner_); + return corner_table_->Vertex(ring_corner); + } + + // Returns true when all ring vertices have been visited. + bool End() const { return corner_ == kInvalidCornerIndex; } + + // Proceeds to the next ring vertex if possible. + void Next() { + if (left_traversal_) { + corner_ = corner_table_->SwingLeft(corner_); + if (corner_ == kInvalidCornerIndex) { + // Open boundary reached. + corner_ = start_corner_; + left_traversal_ = false; + } else if (corner_ == start_corner_) { + // End reached. + corner_ = kInvalidCornerIndex; + } + } else { + // Go to the right until we reach a boundary there (no explicit check + // is needed in this case). + corner_ = corner_table_->SwingRight(corner_); + } + } + + // std::iterator interface. + value_type operator*() const { return Vertex(); } + VertexRingIterator &operator++() { + Next(); + return *this; + } + VertexRingIterator operator++(int) { + const VertexRingIterator result = *this; + ++(*this); + return result; + } + bool operator!=(const VertexRingIterator &other) const { + return corner_ != other.corner_ || start_corner_ != other.start_corner_; + } + bool operator==(const VertexRingIterator &other) const { + return !this->operator!=(other); + } + + // Helper function for getting a valid end iterator. + static VertexRingIterator EndIterator(VertexRingIterator other) { + VertexRingIterator ret = other; + ret.corner_ = kInvalidCornerIndex; + return ret; + } + + private: + const CornerTableT *corner_table_; + // The first processed corner. + CornerIndex start_corner_; + // The last processed corner. + CornerIndex corner_; + // Traversal direction. + bool left_traversal_; +}; + +// Class for iterating over faces adjacent to the specified input face. +template <class CornerTableT> +class FaceAdjacencyIterator + : public std::iterator<std::forward_iterator_tag, FaceIndex> { + public: + // std::iterator interface requires a default constructor. + FaceAdjacencyIterator() + : corner_table_(nullptr), + start_corner_(kInvalidCornerIndex), + corner_(start_corner_) {} + + // Create the iterator from the provided corner table and the central vertex. + FaceAdjacencyIterator(const CornerTableT *table, FaceIndex face_id) + : corner_table_(table), + start_corner_(table->FirstCorner(face_id)), + corner_(start_corner_) { + // We need to start with a corner that has a valid opposite face (if + // there is any such corner). + if (corner_table_->Opposite(corner_) == kInvalidCornerIndex) + FindNextFaceNeighbor(); + } + + // Gets the last visited adjacent face. + FaceIndex Face() const { + return corner_table_->Face(corner_table_->Opposite(corner_)); + } + + // Returns true when all adjacent faces have been visited. + bool End() const { return corner_ == kInvalidCornerIndex; } + + // Proceeds to the next adjacent face if possible. + void Next() { FindNextFaceNeighbor(); } + + // std::iterator interface. + value_type operator*() const { return Face(); } + FaceAdjacencyIterator &operator++() { + Next(); + return *this; + } + FaceAdjacencyIterator operator++(int) { + const FaceAdjacencyIterator result = *this; + ++(*this); + return result; + } + bool operator!=(const FaceAdjacencyIterator &other) const { + return corner_ != other.corner_ || start_corner_ != other.start_corner_; + } + bool operator==(const FaceAdjacencyIterator &other) const { + return !this->operator!=(other); + } + + // Helper function for getting a valid end iterator. + static FaceAdjacencyIterator EndIterator(FaceAdjacencyIterator other) { + FaceAdjacencyIterator ret = other; + ret.corner_ = kInvalidCornerIndex; + return ret; + } + + private: + // Finds the next corner with a valid opposite face. + void FindNextFaceNeighbor() { + while (corner_ != kInvalidCornerIndex) { + corner_ = corner_table_->Next(corner_); + if (corner_ == start_corner_) { + corner_ = kInvalidCornerIndex; + return; + } + if (corner_table_->Opposite(corner_) != kInvalidCornerIndex) { + // Valid opposite face. + return; + } + } + } + + const CornerTableT *corner_table_; + // The first processed corner. + CornerIndex start_corner_; + // The last processed corner. + CornerIndex corner_; +}; + +// Class for iterating over corners attached to a specified vertex. +template <class CornerTableT = CornerTable> +class VertexCornersIterator + : public std::iterator<std::forward_iterator_tag, CornerIndex> { + public: + // std::iterator interface requires a default constructor. + VertexCornersIterator() + : corner_table_(nullptr), + start_corner_(-1), + corner_(start_corner_), + left_traversal_(true) {} + + // Create the iterator from the provided corner table and the central vertex. + VertexCornersIterator(const CornerTableT *table, VertexIndex vert_id) + : corner_table_(table), + start_corner_(table->LeftMostCorner(vert_id)), + corner_(start_corner_), + left_traversal_(true) {} + + // Create the iterator from the provided corner table and the first corner. + VertexCornersIterator(const CornerTableT *table, CornerIndex corner_id) + : corner_table_(table), + start_corner_(corner_id), + corner_(start_corner_), + left_traversal_(true) {} + + // Gets the last visited corner. + CornerIndex Corner() const { return corner_; } + + // Returns true when all ring vertices have been visited. + bool End() const { return corner_ == kInvalidCornerIndex; } + + // Proceeds to the next corner if possible. + void Next() { + if (left_traversal_) { + corner_ = corner_table_->SwingLeft(corner_); + if (corner_ == kInvalidCornerIndex) { + // Open boundary reached. + corner_ = corner_table_->SwingRight(start_corner_); + left_traversal_ = false; + } else if (corner_ == start_corner_) { + // End reached. + corner_ = kInvalidCornerIndex; + } + } else { + // Go to the right until we reach a boundary there (no explicit check + // is needed in this case). + corner_ = corner_table_->SwingRight(corner_); + } + } + + // std::iterator interface. + CornerIndex operator*() const { return Corner(); } + VertexCornersIterator &operator++() { + Next(); + return *this; + } + VertexCornersIterator operator++(int) { + const VertexCornersIterator result = *this; + ++(*this); + return result; + } + bool operator!=(const VertexCornersIterator &other) const { + return corner_ != other.corner_ || start_corner_ != other.start_corner_; + } + bool operator==(const VertexCornersIterator &other) const { + return !this->operator!=(other); + } + + // Helper function for getting a valid end iterator. + static VertexCornersIterator EndIterator(VertexCornersIterator other) { + VertexCornersIterator ret = other; + ret.corner_ = kInvalidCornerIndex; + return ret; + } + + protected: + const CornerTableT *corner_table() const { return corner_table_; } + CornerIndex start_corner() const { return start_corner_; } + CornerIndex &corner() { return corner_; } + bool is_left_traversal() const { return left_traversal_; } + void swap_traversal() { left_traversal_ = !left_traversal_; } + + private: + const CornerTableT *corner_table_; + // The first processed corner. + CornerIndex start_corner_; + // The last processed corner. + CornerIndex corner_; + // Traversal direction. + bool left_traversal_; +}; + +} // namespace draco + +#endif // DRACO_MESH_CORNER_TABLE_ITERATORS_H_ |