/* * ***** BEGIN GPL LICENSE BLOCK ***** * * 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. * * ***** END GPL LICENSE BLOCK ***** */ #ifndef __FREESTYLE_CHAINING_ITERATORS_H__ #define __FREESTYLE_CHAINING_ITERATORS_H__ /** \file blender/freestyle/intern/stroke/ChainingIterators.h * \ingroup freestyle * \brief Chaining iterators * \author Stephane Grabli * \date 01/07/2003 */ #include #include "Predicates1D.h" #include "../system/Iterator.h" #include "../view_map/ViewMap.h" #include "../view_map/ViewMapIterators.h" #include "../view_map/ViewMapAdvancedIterators.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 */ #endif // __FREESTYLE_CHAINING_ITERATORS_H__