/* * 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. */ #pragma once /** \file * \ingroup freestyle * \brief Chaining iterators */ #include #include "Predicates1D.h" #include "../system/Iterator.h" #include "../view_map/ViewMap.h" #include "../view_map/ViewMapAdvancedIterators.h" #include "../view_map/ViewMapIterators.h" // using namespace ViewEdgeInternal; namespace Freestyle { // // Adjacency iterator used in the chaining process // /////////////////////////////////////////////////////////// class AdjacencyIterator : public Iterator { protected: ViewVertexInternal::orientedViewEdgeIterator _internalIterator; bool _restrictToSelection; bool _restrictToUnvisited; public: AdjacencyIterator() { _restrictToSelection = true; _restrictToUnvisited = true; } AdjacencyIterator(ViewVertex *iVertex, bool iRestrictToSelection = true, bool iRestrictToUnvisited = true) { _restrictToSelection = iRestrictToSelection; _restrictToUnvisited = iRestrictToUnvisited; _internalIterator = iVertex->edgesBegin(); while ((!_internalIterator.isEnd()) && (!isValid((*_internalIterator).first))) { ++_internalIterator; } } AdjacencyIterator(const AdjacencyIterator &iBrother) { _internalIterator = iBrother._internalIterator; _restrictToSelection = iBrother._restrictToSelection; _restrictToUnvisited = iBrother._restrictToUnvisited; } AdjacencyIterator &operator=(const AdjacencyIterator &iBrother) { _internalIterator = iBrother._internalIterator; _restrictToSelection = iBrother._restrictToSelection; _restrictToUnvisited = iBrother._restrictToUnvisited; return *this; } virtual ~AdjacencyIterator() { } virtual string getExactTypeName() const { return "AdjacencyIterator"; } virtual inline bool isEnd() const { return _internalIterator.isEnd(); } virtual inline bool isBegin() const { return _internalIterator.isBegin(); } /*! Returns true if the current ViewEdge is coming towards the iteration vertex. * False otherwise. */ bool isIncoming() const; /*! Returns a *pointer* to the pointed ViewEdge. */ virtual ViewEdge *operator*(); virtual ViewEdge *operator->() { return operator*(); } virtual AdjacencyIterator &operator++() { increment(); return *this; } virtual AdjacencyIterator operator++(int) { AdjacencyIterator tmp(*this); increment(); return tmp; } virtual int increment(); virtual int decrement() { cerr << "Warning: method decrement() not implemented" << endl; return 0; } protected: bool isValid(ViewEdge *edge); }; // // Base class for Chaining Iterators // /////////////////////////////////////////////////////////// /*! Base class for chaining iterators. * This class is designed to be overloaded in order to describe chaining rules. * It makes the works of chaining rules description easier. * The two main methods that need to overloaded are traverse() and init(). * traverse() tells which ViewEdge to follow, among the adjacent ones. * If you specify restriction rules (such as "Chain only ViewEdges of the selection"), * they will be included in the adjacency iterator. * (i.e, the adjacent iterator will only stop on "valid" edges). */ class ChainingIterator : public ViewEdgeInternal::ViewEdgeIterator { protected: bool _restrictToSelection; bool _restrictToUnvisited; bool _increment; // true if we're currently incrementing, false when decrementing public: ViewEdge *result; void *py_c_it; /*! Builds a Chaining Iterator from the first ViewEdge used for iteration and its orientation. * \param iRestrictToSelection: * Indicates whether to force the chaining to stay within * the set of selected ViewEdges or not. * \param iRestrictToUnvisited: * Indicates whether a ViewEdge that has already been chained must be ignored ot not. * \param begin: * The ViewEdge from which to start the chain. * \param orientation: * The direction to follow to explore the graph. If true, * the direction indicated by the first ViewEdge is used. */ ChainingIterator(bool iRestrictToSelection = true, bool iRestrictToUnvisited = true, ViewEdge *begin = NULL, bool orientation = true) : ViewEdgeIterator(begin, orientation) { _restrictToSelection = iRestrictToSelection; _restrictToUnvisited = iRestrictToUnvisited; _increment = true; py_c_it = NULL; } /*! Copy constructor */ ChainingIterator(const ChainingIterator &brother) : ViewEdgeIterator(brother) { _restrictToSelection = brother._restrictToSelection; _restrictToUnvisited = brother._restrictToUnvisited; _increment = brother._increment; py_c_it = brother.py_c_it; } /*! Returns the string "ChainingIterator" */ virtual string getExactTypeName() const { return "ChainingIterator"; } /*! Inits the iterator context. * This method is called each time a new chain is started. * It can be used to reset some history information that you might want to keep. */ virtual int init(); /*! This method iterates over the potential next ViewEdges and returns the one that will be * followed next. returns the next ViewEdge to follow or 0 when the end of the chain is reached. * \param it: * The iterator over the ViewEdges adjacent to the end vertex of the current ViewEdge. * The Adjacency iterator reflects the restriction rules by only iterating over the valid * ViewEdges. */ virtual int traverse(const AdjacencyIterator &it); /* accessors */ /*! Returns true if the orientation of the current ViewEdge corresponds to its natural * orientation */ // inline bool getOrientation() const {} /*! Returns the vertex which is the next crossing */ inline ViewVertex *getVertex() { if (_increment) { if (_orientation) { return _edge->B(); } else { return _edge->A(); } } else { if (_orientation) { return _edge->A(); } else { return _edge->B(); } } } /*! Returns true if the current iteration is an incrementation */ inline bool isIncrementing() const { return _increment; } /* increments.*/ virtual int increment(); virtual int decrement(); }; // // Chaining iterators definitions // /////////////////////////////////////////////////////////// /*! A ViewEdge Iterator used to follow ViewEdges the most naturally. * For example, it will follow visible ViewEdges of same nature. * As soon, as the nature or the visibility changes, the iteration stops (by setting the pointed * ViewEdge to 0). In the case of an iteration over a set of ViewEdge that are both Silhouette * and Crease, there will be a precedence of the silhouette over the crease criterion. */ class ChainSilhouetteIterator : public ChainingIterator { public: /*! Builds a ChainSilhouetteIterator from the first ViewEdge used for iteration and its * orientation. * \param iRestrictToSelection: * Indicates whether to force the chaining to stay within the set of selected ViewEdges or * not. * \param begin: * The ViewEdge from where to start the iteration. * \param orientation: * If true, we'll look for the next ViewEdge among the ViewEdges that surround the ending * ViewVertex of begin. If false, we'll search over the ViewEdges surrounding the ending * ViewVertex of begin. */ ChainSilhouetteIterator(bool iRestrictToSelection = true, ViewEdge *begin = NULL, bool orientation = true) : ChainingIterator(iRestrictToSelection, true, begin, orientation) { } /*! Copy constructor */ ChainSilhouetteIterator(const ChainSilhouetteIterator &brother) : ChainingIterator(brother) { } /*! Returns the string "ChainSilhouetteIterator" */ virtual string getExactTypeName() const { return "ChainSilhouetteIterator"; } /*! This method iterates over the potential next ViewEdges and returns the one that will be * followed next. * When reaching the end of a chain, 0 is returned. */ virtual int traverse(const AdjacencyIterator &it); /*! Inits the iterator context */ virtual int init() { return 0; } }; // // ChainPredicateIterator // /////////////////////////////////////////////////////////// /*! A "generic" user-controlled ViewEdge iterator. This iterator is in particular built from a * unary predicate and a binary predicate. * First, the unary predicate is evaluated for all potential next ViewEdges in order to only * keep the ones respecting a certain constraint. * Then, the binary predicate is evaluated on the current ViewEdge together with each ViewEdge * of the previous selection. The first ViewEdge respecting both the unary predicate and the * binary predicate is kept as the next one. If none of the potential next ViewEdge respects * these 2 predicates, 0 is returned. */ class ChainPredicateIterator : public ChainingIterator { protected: BinaryPredicate1D *_binary_predicate; // the caller is responsible for the deletion of this object UnaryPredicate1D *_unary_predicate; // the caller is responsible for the deletion of this object public: /*! Builds a ChainPredicateIterator from a starting ViewEdge and its orientation. * \param iRestrictToSelection: * Indicates whether to force the chaining to stay * within the set of selected ViewEdges or not. * \param iRestrictToUnvisited: * Indicates whether a ViewEdge that has already been chained must be ignored ot not. * \param begin: * The ViewEdge from where to start the iteration. * \param orientation: * If true, we'll look for the next ViewEdge among the ViewEdges that surround the ending * ViewVertex of begin. If false, we'll search over the ViewEdges surrounding the ending * ViewVertex of begin. */ ChainPredicateIterator(bool iRestrictToSelection = true, bool iRestrictToUnvisited = true, ViewEdge *begin = NULL, bool orientation = true) : ChainingIterator(iRestrictToSelection, iRestrictToUnvisited, begin, orientation) { _binary_predicate = 0; _unary_predicate = 0; } /*! Builds a ChainPredicateIterator from a unary predicate, a binary predicate, a starting * ViewEdge and its orientation. * \param iRestrictToSelection: * Indicates whether to force the chaining to stay * within the set of selected ViewEdges or not. * \param iRestrictToUnvisited: * Indicates whether a ViewEdge that has already been chained must be ignored ot not. * \param upred: * The unary predicate that the next ViewEdge must satisfy. * \param bpred: * The binary predicate that the next ViewEdge must satisfy together with the actual pointed * ViewEdge. * \param begin: * The ViewEdge from where to start the iteration. * \param orientation: * If true, we'll look for the next ViewEdge among the ViewEdges that surround the ending * ViewVertex of begin. If false, we'll search over the ViewEdges surrounding the ending * ViewVertex of begin. */ ChainPredicateIterator(UnaryPredicate1D &upred, BinaryPredicate1D &bpred, bool iRestrictToSelection = true, bool iRestrictToUnvisited = true, ViewEdge *begin = NULL, bool orientation = true) : ChainingIterator(iRestrictToSelection, iRestrictToUnvisited, begin, orientation) { _unary_predicate = &upred; _binary_predicate = &bpred; } /*! Copy constructor */ ChainPredicateIterator(const ChainPredicateIterator &brother) : ChainingIterator(brother) { _unary_predicate = brother._unary_predicate; _binary_predicate = brother._binary_predicate; } /*! Destructor. */ virtual ~ChainPredicateIterator() { _unary_predicate = 0; _binary_predicate = 0; } /*! Returns the string "ChainPredicateIterator" */ virtual string getExactTypeName() const { return "ChainPredicateIterator"; } /*! This method iterates over the potential next ViewEdges and returns the one that will be * followed next. When reaching the end of a chain, 0 is returned. */ virtual int traverse(const AdjacencyIterator &it); /*! Inits the iterator context */ virtual int init() { return 0; } }; } /* namespace Freestyle */