25fdc0475d910adcdcfb2fa9a87f014a3785a3f1
[blender-staging.git] / source / blender / freestyle / intern / stroke / ChainingIterators.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * ***** END GPL LICENSE BLOCK *****
19  */
20
21 /** \file blender/freestyle/intern/stroke/ChainingIterators.cpp
22  *  \ingroup freestyle
23  *  \brief Chaining iterators
24  *  \author Stephane Grabli
25  *  \date 01/07/2003
26  */
27
28 #include "../python/Director.h"
29
30 #include "ChainingIterators.h"
31
32 #include "../system/TimeStamp.h"
33
34 namespace Freestyle {
35
36 ViewEdge *AdjacencyIterator::operator*()
37 {
38         return (*_internalIterator).first;
39 }
40
41 bool AdjacencyIterator::isIncoming() const
42 {
43         return (*_internalIterator).second;
44 }
45
46 int AdjacencyIterator::increment()
47 {
48         ++_internalIterator;
49         while ((!_internalIterator.isEnd()) && (!isValid((*_internalIterator).first)))
50                 ++_internalIterator;
51         return 0;
52 }
53
54 bool AdjacencyIterator::isValid(ViewEdge *edge)
55 {
56         if (_restrictToSelection) {
57                 if (edge->getTimeStamp() != TimeStamp::instance()->getTimeStamp())
58                         return false;
59         }
60         if (_restrictToUnvisited) {
61                 if (edge->getChainingTimeStamp() > TimeStamp::instance()->getTimeStamp())
62                         return false;
63         }
64         return true;
65 }
66
67 int ChainingIterator::init()
68 {
69         return Director_BPy_ChainingIterator_init(this);
70 }
71
72 int ChainingIterator::traverse(const AdjacencyIterator &it)
73 {
74         return Director_BPy_ChainingIterator_traverse(this, const_cast<AdjacencyIterator &>(it));
75 }
76
77 int ChainingIterator::increment()
78 {
79         _increment = true;
80         ViewVertex *vertex = getVertex();
81         if (!vertex) {
82                 _edge = 0;
83                 return 0;
84         }
85         AdjacencyIterator it = AdjacencyIterator(vertex, _restrictToSelection, _restrictToUnvisited);
86         if (it.isEnd()) {
87                 _edge = 0;
88                 return 0;
89         }
90         if (traverse(it) < 0)
91                 return -1;
92         _edge = result;
93         if (_edge == 0)
94                 return 0;
95         if (_edge->A() == vertex)
96                 _orientation = true;
97         else
98                 _orientation = false;
99         return 0;
100 }
101
102 int ChainingIterator::decrement()
103 {
104         _increment = false;
105         ViewVertex *vertex = getVertex();
106         if (!vertex) {
107                 _edge = 0;
108                 return 0;
109         }
110         AdjacencyIterator it = AdjacencyIterator(vertex, _restrictToSelection, _restrictToUnvisited);
111         if (it.isEnd()) {
112                 _edge = 0;
113                 return 0;
114         }
115         if (traverse(it) < 0)
116                 return -1;
117         _edge = result;
118         if (_edge == 0)
119                 return 0;
120         if (_edge->B() == vertex)
121                 _orientation = true;
122         else
123                 _orientation = false;
124         return 0;
125 }
126
127 //
128 // ChainSilhouetteIterators
129 //
130 ///////////////////////////////////////////////////////////
131
132 int ChainSilhouetteIterator::traverse(const AdjacencyIterator& ait)
133 {
134         AdjacencyIterator it(ait);
135         ViewVertex *nextVertex = getVertex();
136         // we can't get a NULL nextVertex here, it was intercepted before
137         if (nextVertex->getNature() & Nature::T_VERTEX) {
138                 TVertex *tvertex = (TVertex *)nextVertex;
139                 ViewEdge *mate = (tvertex)->mate(getCurrentEdge());
140                 while (!it.isEnd()) {
141                         ViewEdge *ve = *it;
142                         if (ve == mate) {
143                                 result = ve;
144                                 return 0;
145                         }
146                         ++it;
147                 }
148                 result = 0;
149                 return 0;
150         }
151         if (nextVertex->getNature() & Nature::NON_T_VERTEX) {
152                 //soc NonTVertex *nontvertex = (NonTVertex*)nextVertex;
153                 ViewEdge *newEdge(0);
154                 // we'll try to chain the edges by keeping the same nature...
155                 // the preseance order is : SILHOUETTE, BORDER, CREASE, MATERIAL_BOUNDARY, EDGE_MARK, SUGGESTIVE, VALLEY, RIDGE
156                 Nature::EdgeNature natures[8] = {
157                         Nature::SILHOUETTE,
158                         Nature::BORDER,
159                         Nature::CREASE,
160                         Nature::MATERIAL_BOUNDARY,
161                         Nature::EDGE_MARK,
162                         Nature::SUGGESTIVE_CONTOUR,
163                         Nature::VALLEY,
164                         Nature::RIDGE
165                 };
166                 int numNatures = sizeof(natures) / sizeof(Nature::EdgeNature);
167                 for (unsigned int i = 0; i < numNatures; ++i) {
168                         if (getCurrentEdge()->getNature() & natures[i]) {
169                                 int n = 0;
170                                 while (!it.isEnd()) {
171                                         ViewEdge *ve = *it;
172                                         if (ve->getNature() & natures[i]) {
173                                                 ++n;
174                                                 newEdge = ve;
175                                         }
176                                         ++it;
177                                 }
178                                 if (n == 1) {
179                                         result = newEdge;
180                                 }
181                                 else {
182                                         result = 0;
183                                 }
184                                 return 0;
185                         }
186                 }
187         }
188         result = 0;
189         return 0;
190 }
191
192 int ChainPredicateIterator::traverse(const AdjacencyIterator& ait)
193 {
194         AdjacencyIterator it(ait);
195         // Iterates over next edges to see if one of them respects the predicate:
196         while (!it.isEnd()) {
197                 ViewEdge *ve = *it;
198                 if (_unary_predicate->operator()(*ve) < 0)
199                         return -1;
200                 if (_unary_predicate->result) {
201                         if (_binary_predicate->operator()(*(getCurrentEdge()), *(ve)) < 0)
202                                 return -1;
203                         if (_binary_predicate->result) {
204                                 result = ve;
205                                 return 0;
206                         }
207                 }
208                 ++it;
209         }
210         result = 0;
211         return 0;
212 }
213
214 } /* namespace Freestyle */