Merged changes in the trunk up to revision 28600.
[blender.git] / source / blender / freestyle / intern / stroke / CurveIterators.h
1 //
2 //  Filename         : CurveIterators.h
3 //  Author(s)        : Stephane Grabli
4 //  Purpose          : Iterators used to iterate over the elements of the Curve
5 //  Date of creation : 01/08/2003
6 //
7 ///////////////////////////////////////////////////////////////////////////////
8
9
10 //
11 //  Copyright (C) : Please refer to the COPYRIGHT file distributed 
12 //   with this source distribution. 
13 //
14 //  This program is free software; you can redistribute it and/or
15 //  modify it under the terms of the GNU General Public License
16 //  as published by the Free Software Foundation; either version 2
17 //  of the License, or (at your option) any later version.
18 //
19 //  This program is distributed in the hope that it will be useful,
20 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
21 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 //  GNU General Public License for more details.
23 //
24 //  You should have received a copy of the GNU General Public License
25 //  along with this program; if not, write to the Free Software
26 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27 //
28 ///////////////////////////////////////////////////////////////////////////////
29
30 #ifndef  CURVEITERATORS_H
31 # define CURVEITERATORS_H
32
33 #include "Stroke.h"
34 #include "Curve.h"
35
36 namespace CurveInternal {
37
38   /*! iterator on a curve. Allows an iterating outside 
39    *  initial vertices. A CurvePoint is instanciated an returned 
40    *  when the iterator is dereferenced.
41    */
42
43   class CurvePointIterator : public Interface0DIteratorNested
44   { 
45   public:
46     friend class ::Curve; 
47   public:
48     float _CurvilinearLength;
49     float _step;
50     ::Curve::vertex_container::iterator __A;
51     ::Curve::vertex_container::iterator __B;
52     ::Curve::vertex_container::iterator _begin;
53     ::Curve::vertex_container::iterator _end;
54     int _n;
55     int _currentn;
56     float _t;
57     mutable CurvePoint _Point;
58     float _CurveLength;
59
60   public:
61     
62   public:
63     inline CurvePointIterator(float step = 0.f)
64       : Interface0DIteratorNested()
65     {
66       _step = step;
67       _CurvilinearLength = 0.f;
68       _t = 0.f;
69       //_Point = 0;
70       _n = 0;
71       _currentn = 0;
72       _CurveLength=0;
73     }
74     
75     inline CurvePointIterator(const CurvePointIterator& iBrother)
76       : Interface0DIteratorNested()
77     {
78       __A = iBrother.__A;
79       __B = iBrother.__B;
80       _begin = iBrother._begin;
81       _end = iBrother._end;
82       _CurvilinearLength = iBrother._CurvilinearLength;
83       _step = iBrother._step;
84       _t = iBrother._t;
85       _Point = iBrother._Point;
86       _n = iBrother._n;
87       _currentn = iBrother._currentn;
88       _CurveLength = iBrother._CurveLength;
89     }
90     inline CurvePointIterator& operator=(const CurvePointIterator& iBrother)
91     {
92       __A = iBrother.__A;
93       __B = iBrother.__B;
94       _begin = iBrother._begin;
95       _end = iBrother._end;
96       _CurvilinearLength = iBrother._CurvilinearLength;
97       _step = iBrother._step;
98       _t = iBrother._t;
99       _Point = iBrother._Point;
100       _n = iBrother._n;
101       _currentn = iBrother._currentn;
102       _CurveLength = iBrother._CurveLength;
103       return *this;
104     }
105     virtual ~CurvePointIterator()
106     {
107     }
108   protected:
109     inline CurvePointIterator(::Curve::vertex_container::iterator iA, 
110                               ::Curve::vertex_container::iterator iB, 
111                               ::Curve::vertex_container::iterator ibegin, 
112                               ::Curve::vertex_container::iterator iend,
113                               int currentn,
114       int n,
115       float iCurveLength,
116       float step, float t=0.f, float iCurvilinearLength = 0.f)
117       : Interface0DIteratorNested()
118     {
119       __A = iA;
120       __B = iB;
121       _begin = ibegin;
122       _end = iend;
123       _CurvilinearLength = iCurvilinearLength;
124       _step = step;
125       _t = t;
126       _n = n;
127       _currentn = currentn;
128       _CurveLength = iCurveLength;
129     }
130  
131   public:
132
133     virtual CurvePointIterator* copy() const {
134       return new CurvePointIterator(*this);
135     }
136
137     inline Interface0DIterator castToInterface0DIterator() const{
138       Interface0DIterator ret(new CurveInternal::CurvePointIterator(*this));
139       return ret;
140     }
141     virtual string getExactTypeName() const {
142       return "CurvePointIterator";
143     }
144     
145     // operators
146     inline CurvePointIterator& operator++()  // operator corresponding to ++i
147     { 
148       increment();
149       return *this;
150     }
151    
152     inline CurvePointIterator& operator--()  // operator corresponding to ++i
153     { 
154       decrement();
155       return *this;
156     }
157     
158     // comparibility
159     virtual bool operator==(const Interface0DIteratorNested& b) const
160     {
161       const CurvePointIterator* it_exact = dynamic_cast<const CurvePointIterator*>(&b);
162       if (!it_exact)
163           return false;
164       return ((__A==it_exact->__A) && (__B==it_exact->__B) && (_t == it_exact->_t));
165     }
166     
167     // dereferencing
168     virtual CurvePoint& operator*()  
169     {
170       return (_Point = CurvePoint(*__A,*__B,_t));
171     }
172     virtual CurvePoint* operator->() { return &(operator*());}
173   public:
174     virtual bool isBegin() const 
175     {
176       if((__A == _begin) && (_t < (float)M_EPSILON))
177         return true;
178       return false;
179     }
180     virtual bool isEnd() const 
181     {
182       if(__B == _end)
183         return true;
184       return false;
185     }
186  
187 // protected:
188
189     virtual int increment() 
190     {
191       if((_currentn == _n-1) && (_t == 1.f))
192       {
193         // we're setting the iterator to end
194         ++__A;
195         ++__B;
196         ++_currentn;
197         _t = 0.f;
198         return 0;
199       }
200       
201       if(0 == _step) // means we iterate over initial vertices
202       {
203               Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d());
204         _CurvilinearLength += (float)vec_tmp.norm();
205         if(_currentn == _n-1)
206         { 
207           _t = 1.f;   
208           return 0;
209         }
210         ++__B;
211         ++__A;
212         ++_currentn;
213         return 0;
214       }
215       
216       // compute the new position:
217       Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d());
218       float normAB = (float)vec_tmp2.norm();
219
220       if(normAB > M_EPSILON)
221       {
222         _CurvilinearLength += _step;
223         _t = _t + _step/normAB;
224       }
225       else
226         _t = 1.f; // AB is a null segment, we're directly at its end
227         //if normAB ~= 0, we don't change these values
228       if(_t >= 1)
229       { 
230         _CurvilinearLength -= normAB*(_t-1);
231         if(_currentn == _n-1)
232           _t=1.f;
233         else
234         {
235           _t = 0.f;
236           ++_currentn;
237           ++__A;++__B;
238         }
239       }
240           return 0;
241     }
242     virtual int decrement() 
243     {
244       if(_t == 0.f) //we're at the beginning of the edge
245       {
246         _t = 1.f;
247         --_currentn;
248         --__A; --__B;
249         if(_currentn == _n-1)
250           return 0;
251       }
252
253       if(0 == _step) // means we iterate over initial vertices
254       {
255               Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d());
256         _CurvilinearLength -= (float)vec_tmp.norm();
257         _t = 0;
258         return 0;
259       }
260       
261       // compute the new position:
262       Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d());
263       float normAB = (float)vec_tmp2.norm();
264       
265       if(normAB >M_EPSILON)
266       {
267         _CurvilinearLength -= _step;
268         _t = _t - _step/normAB;
269       }
270       else
271         _t = -1.f; // We just need a negative value here
272
273       // round value
274       if(fabs(_t) < (float)M_EPSILON)
275         _t = 0.0;
276       if(_t < 0)
277       { 
278         if(_currentn == 0)
279           _CurvilinearLength = 0.f;
280         else
281         _CurvilinearLength += normAB*(-_t);
282         _t = 0.f;
283       } 
284           return 0;
285     }
286
287     virtual float t() const{
288       return _CurvilinearLength;
289     } 
290     virtual float u() const{
291       return _CurvilinearLength/_CurveLength;
292     } 
293   };
294
295   
296
297 } // end of namespace StrokeInternal
298
299 #endif // CURVEITERATORS_H