diff options
Diffstat (limited to 'source/blender/freestyle/intern/stroke/Operators.h')
-rw-r--r-- | source/blender/freestyle/intern/stroke/Operators.h | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/source/blender/freestyle/intern/stroke/Operators.h b/source/blender/freestyle/intern/stroke/Operators.h new file mode 100644 index 00000000000..aafbc2350d9 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/Operators.h @@ -0,0 +1,274 @@ +/* + * ***** 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. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_OPERATORS_H__ +#define __FREESTYLE_OPERATORS_H__ + +/** \file blender/freestyle/intern/stroke/Operators.h + * \ingroup freestyle + * \brief Class gathering stroke creation algorithms + * \author Stephane Grabli + * \author Emmanuel Turquin + * \date 01/07/2003 + */ + +#include <iostream> +#include <vector> + +#include "Chain.h" +#include "ChainingIterators.h" +#include "Predicates0D.h" +#include "Predicates1D.h" +#include "StrokeShader.h" + +#include "../system/TimeStamp.h" + +#include "../view_map/Interface1D.h" +#include "../view_map/ViewMap.h" + +/*! Class defining the operators used in a style module. + * There are 4 classes of operators: Selection, Chaining, Splitting and Creating. All these operators are + * user controlled in the scripting language through Functors, Predicates and Shaders that are taken as arguments. + */ +class LIB_STROKE_EXPORT Operators { + +public: + typedef vector<Interface1D*> I1DContainer; + typedef vector<Stroke*> StrokesContainer; + + // + // Operators + // + //////////////////////////////////////////////// + + /*! Selects the ViewEdges of the ViewMap verifying a specified condition. + * \param pred The predicate expressing this condition + */ + static int select(UnaryPredicate1D& pred); + + /*! Builds a set of chains from the current set of ViewEdges. + * Each ViewEdge of the current list starts a new chain. The chaining operator then iterates over the ViewEdges + * of the ViewMap using the user specified iterator. + * This operator only iterates using the increment operator and is therefore unidirectional. + * \param it + * The iterator on the ViewEdges of the ViewMap. It contains the chaining rule. + * \param pred + * The predicate on the ViewEdge that expresses the stopping condition. + * \param modifier + * A function that takes a ViewEdge as argument and that is used to modify the processed ViewEdge + * state (the timestamp incrementation is a typical illustration of such a modifier) + */ + static int chain(ViewEdgeInternal::ViewEdgeIterator& it, UnaryPredicate1D& pred, UnaryFunction1D_void& modifier); + + /*! Builds a set of chains from the current set of ViewEdges. + * Each ViewEdge of the current list starts a new chain. The chaining operator then iterates over the ViewEdges + * of the ViewMap using the user specified iterator. + * This operator only iterates using the increment operator and is therefore unidirectional. + * This chaining operator is different from the previous one because it doesn't take any modifier as argument. + * Indeed, the time stamp (insuring that a ViewEdge is processed one time) is automatically managed in this case. + * \param it + * The iterator on the ViewEdges of the ViewMap. It contains the chaining rule. + * \param pred + * The predicate on the ViewEdge that expresses the stopping condition. + */ + static int chain(ViewEdgeInternal::ViewEdgeIterator& it, UnaryPredicate1D& pred); + + /*! Builds a set of chains from the current set of ViewEdges. + * Each ViewEdge of the current list potentially starts a new chain. The chaining operator then iterates over + * the ViewEdges of the ViewMap using the user specified iterator. + * This operator iterates both using the increment and decrement operators and is therefore bidirectional. + * This operator works with a ChainingIterator which contains the chaining rules. It is this last one which can + * be told to chain only edges that belong to the selection or not to process twice a ViewEdge during the chaining. + * Each time a ViewEdge is added to a chain, its chaining time stamp is incremented. This allows you to keep track + * of the number of chains to which a ViewEdge belongs to. + * \param it + * The ChainingIterator on the ViewEdges of the ViewMap. It contains the chaining rule. + * \param pred + * The predicate on the ViewEdge that expresses the stopping condition. + */ + static int bidirectionalChain(ChainingIterator& it, UnaryPredicate1D& pred); + + /*! The only difference with the above bidirectional chaining algorithm is that we don't need to pass a stopping + * criterion. This might be desirable when the stopping criterion is already contained in the iterator definition. + * Builds a set of chains from the current set of ViewEdges. + * Each ViewEdge of the current list potentially starts a new chain. The chaining operator then iterates over + * the ViewEdges of the ViewMap using the user specified iterator. + * This operator iterates both using the increment and decrement operators and is therefore bidirectional. + * This operator works with a ChainingIterator which contains the chaining rules. It is this last one which can be + * told to chain only edges that belong to the selection or not to process twice a ViewEdge during the chaining. + * Each time a ViewEdge is added to a chain, its chaining time stamp is incremented. This allows you to keep track + * of the number of chains to which a ViewEdge belongs to. + * \param it + * The ChainingIterator on the ViewEdges of the ViewMap. It contains the chaining rule. + */ + static int bidirectionalChain(ChainingIterator& it); + + /*! Splits each chain of the current set of chains in a sequential way. + * The points of each chain are processed (with a specified sampling) sequentially. + * Each time a user specified starting condition is verified, a new chain begins and ends as soon as a + * user-defined stopping predicate is verified. + * This allows chains overlapping rather than chains partitioning. + * The first point of the initial chain is the first point of one of the resulting chains. + * The splitting ends when no more chain can start. + * \param startingPred + * The predicate on a point that expresses the starting condition + * \param stoppingPred + * The predicate on a point that expresses the stopping condition + * \param sampling + * The resolution used to sample the chain for the predicates evaluation. (The chain is not actually + * resampled, a virtual point only progresses along the curve using this resolution) + */ + static int sequentialSplit(UnaryPredicate0D& startingPred, UnaryPredicate0D& stoppingPred, float sampling = 0.0f); + + /*! Splits each chain of the current set of chains in a sequential way. + * The points of each chain are processed (with a specified sampling) sequentially and each time a user + * specified condition is verified, the chain is split into two chains. + * The resulting set of chains is a partition of the initial chain + * \param pred + * The predicate on a point that expresses the splitting condition + * \param sampling + * The resolution used to sample the chain for the predicate evaluation. (The chain is not actually + * resampled, a virtual point only progresses along the curve using this resolution) + */ + static int sequentialSplit(UnaryPredicate0D& pred, float sampling = 0.0f); + + /*! Splits the current set of chains in a recursive way. + * We process the points of each chain (with a specified sampling) to find the point minimizing a specified + * function. The chain is split in two at this point and the two new chains are processed in the same way. + * The recursivity level is controlled through a predicate 1D that expresses a stopping condition + * on the chain that is about to be processed. + * \param func + * The Unary Function evaluated at each point of the chain. + * The splitting point is the point minimizing this function + * \param pred + * The Unary Predicate ex pressing the recursivity stopping condition. + * This predicate is evaluated for each curve before it actually gets split. + * If pred(chain) is true, the curve won't be split anymore. + * \param sampling + * The resolution used to sample the chain for the predicates evaluation. (The chain is not actually + * resampled, a virtual point only progresses along the curve using this resolution) + */ + static int recursiveSplit(UnaryFunction0D<double>& func, UnaryPredicate1D& pred, float sampling = 0); + + /*! Splits the current set of chains in a recursive way. + * We process the points of each chain (with a specified sampling) to find the point minimizing a specified + * function. The chain is split in two at this point and the two new chains are processed in the same way. + * The user can specify a 0D predicate to make a first selection on the points that can potentially be split. + * A point that doesn't verify the 0D predicate won't be candidate in realizing the min. + * The recursivity level is controlled through a predicate 1D that expresses a stopping condition + * on the chain that is about to be processed. + * \param func + * The Unary Function evaluated at each point of the chain. + * The splitting point is the point minimizing this function + * \param pred0d + * The Unary Predicate 0D used to select the candidate points where the split can occur. + * For example, it is very likely that would rather have your chain splitting around its middle point + * than around one of its extremities. A 0D predicate working on the curvilinear abscissa allows + * to add this kind of constraints. + * \param pred + * The Unary Predicate ex pressing the recursivity stopping condition. + * This predicate is evaluated for each curve before it actually gets split. + * If pred(chain) is true, the curve won't be split anymore. + * \param sampling + * The resolution used to sample the chain for the predicates evaluation. (The chain is not actually + * resampled, a virtual point only progresses along the curve using this resolution) + */ + static int recursiveSplit(UnaryFunction0D<double>& func, UnaryPredicate0D& pred0d, UnaryPredicate1D& pred, + float sampling = 0.0f); + + /*! Sorts the current set of chains (or viewedges) according to the comparison predicate given as argument. + * \param pred + * The binary predicate used for the comparison + */ + static int sort(BinaryPredicate1D& pred); + + /*! Creates and shades the strokes from the current set of chains. + * A predicate can be specified to make a selection pass on the chains. + * \param pred + * The predicate that a chain must verify in order to be transform as a stroke + * \param shaders + * The list of shaders used to shade the strokes + */ + static int create(UnaryPredicate1D& pred, vector<StrokeShader*> shaders); + + // + // Data access + // + //////////////////////////////////////////////// + + static ViewEdge *getViewEdgeFromIndex(unsigned i) + { + return dynamic_cast<ViewEdge*>(_current_view_edges_set[i]); + } + + static Chain *getChainFromIndex(unsigned i) + { + return dynamic_cast<Chain*>(_current_chains_set[i]); + } + + static Stroke *getStrokeFromIndex(unsigned i) + { + return _current_strokes_set[i]; + } + + static unsigned getViewEdgesSize() + { + return _current_view_edges_set.size(); + } + + static unsigned getChainsSize() + { + return _current_chains_set.size(); + } + + static unsigned getStrokesSize() + { + return _current_strokes_set.size(); + } + + // + // Not exported in Python + // + ////////////////////////////////////////////////// + + static StrokesContainer *getStrokesSet() + { + return &_current_strokes_set; + } + + static void reset(); + +private: + Operators() {} + + static I1DContainer _current_view_edges_set; + static I1DContainer _current_chains_set; + static I1DContainer *_current_set; + static StrokesContainer _current_strokes_set; +}; + +#endif // __FREESTYLE_OPERATORS_H__ |